mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			1073 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | dca395a018 | ||
|  | f875c7cbf5 | ||
|  | eed88fc103 | ||
|  | 6fc54d1d27 | ||
|  | 0ef52bf909 | ||
|  | 95e34af6ef | ||
|  | 650b99ead2 | ||
|  | 57941a19de | ||
|  | 6157db0b6a | ||
|  | c9358acf5d | ||
|  | ed29eb8a5d | ||
|  | bcf7452312 | ||
|  | b9000519e4 | ||
|  | 2694297466 | ||
|  | 53ff5c1490 | ||
|  | 32a036b076 | ||
|  | aae2ab2693 | ||
|  | 4ef23e28a3 | ||
|  | 38beb7f8d2 | ||
|  | 0129a66906 | ||
|  | 45bced7b34 | ||
|  | 7f5a55dffb | ||
|  | 80289df6d3 | ||
|  | 2115c3ced8 | ||
|  | 1c2d0e6618 | ||
|  | ea4f7f79ce | ||
|  | b17f8ac311 | ||
|  | 6870d13b72 | ||
|  | 81fa304fd2 | ||
|  | a663ddb0d9 | ||
|  | f7969afc22 | ||
|  | 52ce4cd313 | ||
|  | 247175881f | ||
|  | fcf5009338 | ||
|  | 12542d8f63 | ||
|  | e94194e28b | ||
|  | 115499f3b2 | ||
|  | 12af05b94f | ||
|  | 88b83d8164 | ||
|  | fcc22c692a | ||
|  | a876e8005c | ||
|  | 2288e3705a | ||
|  | e8b58154e0 | ||
|  | 4393475af3 | ||
|  | 3fc560597c | ||
|  | 9f9af0b693 | ||
|  | a83fe2caea | ||
|  | 30c5376217 | ||
|  | 6dddd6629d | ||
|  | f80de12cb5 | ||
|  | 544ffca3a5 | ||
|  | e0730c7b39 | ||
|  | 3d59d141c4 | ||
|  | ccddc2623d | ||
|  | fcc47b58b4 | ||
|  | f67ac2e25e | ||
|  | 26127c9ccf | ||
|  | d624efa799 | ||
|  | ed3d40a4e0 | ||
|  | 6e90ce5496 | ||
|  | ab851b1be4 | ||
|  | 340de53825 | ||
|  | a867b60af0 | ||
|  | 26eafb0bd2 | ||
|  | 0dbe44764b | ||
|  | 2159df6802 | ||
|  | 23389b9f17 | ||
|  | 6d3e3b894a | ||
|  | 55340aefa3 | ||
|  | 94bc751e41 | ||
|  | 89259c11e2 | ||
|  | 6bbaf1523c | ||
|  | fa3f18b60f | ||
|  | 3dc794002f | ||
|  | f50b133f2e | ||
|  | 1d6f6d28c9 | ||
|  | c913de3c8b | ||
|  | bbc7b54a38 | ||
|  | 05fa1b40d1 | ||
|  | 6a88c8634d | ||
|  | 8ae1efa230 | ||
|  | ab8df4c8ab | ||
|  | c259a46ed3 | ||
|  | 5dc0677599 | ||
|  | 7ed662ecc2 | ||
|  | 4361cc69d4 | ||
|  | 461cbcbc28 | ||
|  | 09ae6c488b | ||
|  | 271a0ade26 | ||
|  | 4b076d227a | ||
|  | 3c4e7158a1 | ||
|  | 0b16765f37 | ||
|  | 20c2ff3443 | ||
|  | 96f2e598f4 | ||
|  | 7374f0f9dd | ||
|  | ccc44a74a0 | ||
|  | 66cd63a68d | ||
|  | decf7e5485 | ||
|  | 063c8025aa | ||
|  | 2fa7d2bd56 | ||
|  | e55e7bce74 | ||
|  | f572445a65 | ||
|  | 8b4f656d90 | ||
|  | 6c1e093ebd | ||
|  | 6dd1b4537a | ||
|  | 39ca9bea72 | ||
|  | 999103277e | ||
|  | 3cc57ab89c | ||
|  | 4e830079de | ||
|  | ea7231e9fe | ||
|  | ddfaca6d0c | ||
|  | 3b11bd0593 | ||
|  | 3f89057528 | ||
|  | 2f1073712f | ||
|  | 678e504c48 | ||
|  | e69545fd95 | ||
|  | a7ed025cd6 | ||
|  | 3d8e1f2484 | ||
|  | c38c9608da | ||
|  | 2396b75e3c | ||
|  | e5c19b7562 | ||
|  | 114788567d | ||
|  | 17ae4b7d2a | ||
|  | 12d652bd0e | ||
|  | ff1bed97b8 | ||
|  | 56490f0e84 | ||
|  | 0b028a8923 | ||
|  | 43ac541cb8 | ||
|  | 5218443678 | ||
|  | d9028ed9b7 | ||
|  | 9b9bd11ebb | ||
|  | 07011ec5f7 | ||
|  | c3990ac32f | ||
|  | 081ff3ff55 | ||
|  | 93996ada96 | ||
|  | a60671d4c1 | ||
|  | 3f716cc369 | ||
|  | 9f23cffd1b | ||
|  | 07c416cfbf | ||
|  | 389fcc1c8d | ||
|  | fa07811375 | ||
|  | fc91a50979 | ||
|  | f9c518f321 | ||
|  | 015b439f0d | ||
|  | 0675622508 | ||
|  | e9969bdd5f | ||
|  | 1139f950ed | ||
|  | 284732c7a6 | ||
|  | 0cb0720d8b | ||
|  | 8ad1ede0c5 | ||
|  | a349aac8a4 | ||
|  | 83b169c6ef | ||
|  | 49c37baac5 | ||
|  | 8d62088576 | ||
|  | f5437a17f8 | ||
|  | 92af4e5c96 | ||
|  | 0619adb0cd | ||
|  | 65a5107854 | ||
|  | 0fcc1e252b | ||
|  | 4b7f817475 | ||
|  | 0439599971 | ||
|  | fa344d5308 | ||
|  | f0316f09ed | ||
|  | b1af6bab28 | ||
|  | ad2aebb54d | ||
|  | 23fc652092 | ||
|  | f0a5756f25 | ||
|  | 14c7ad201a | ||
|  | 08ca3c89d3 | ||
|  | edda470bf8 | ||
|  | 7183d72e5c | ||
|  | 5e38ebfce5 | ||
|  | 56e36847a5 | ||
|  | 6dba916d02 | ||
|  | fd57086ffd | ||
|  | d98d366eea | ||
|  | b261b0b447 | ||
|  | c6042a9053 | ||
|  | ae1245abec | ||
|  | e26d2376fc | ||
|  | bb36ad64a7 | ||
|  | 262d4f92d4 | ||
|  | 675530458c | ||
|  | 19e34b460f | ||
|  | dddb8cdbc0 | ||
|  | 0d0df5f143 | ||
|  | d1cf683f57 | ||
|  | d099c33e5b | ||
|  | 21fb41545b | ||
|  | 4c56814785 | ||
|  | cffe05e22b | ||
|  | 4237850299 | ||
|  | b5fc36a8e1 | ||
|  | 4586c1ef52 | ||
|  | 2722f0b749 | ||
|  | d6cf7c4872 | ||
|  | 3aedfed432 | ||
|  | edeaf13259 | ||
|  | c1290c4e9b | ||
|  | b2c1527b17 | ||
|  | a4a65ea56e | ||
|  | ccf0e1875e | ||
|  | 9c009aceaf | ||
|  | da4b1c7276 | ||
|  | add098d5c0 | ||
|  | aca096548c | ||
|  | 75aa3abcae | ||
|  | e685d262cc | ||
|  | d2599d6ef9 | ||
|  | cd5223d98d | ||
|  | 7b68d9047d | ||
|  | 9a7ea06d66 | ||
|  | c69ef34ac9 | ||
|  | 021999d05f | ||
|  | 6054430a5e | ||
|  | 8f578ed95a | ||
|  | fc5c339e27 | ||
|  | defad3d820 | ||
|  | c0f96aa948 | ||
|  | f2eae2fc98 | ||
|  | 0e4f786978 | ||
|  | d36b2318fd | ||
|  | d83b508bbc | ||
|  | 5b9c2cdc13 | ||
|  | 49066c282a | ||
|  | 3e28c0c00a | ||
|  | 220d689f69 | ||
|  | 5a0a28a04c | ||
|  | b44e69e09b | ||
|  | fcbe10f5ec | ||
|  | 182fe170fd | ||
|  | 184e9bdaf6 | ||
|  | 0096f50cde | ||
|  | 460f14deca | ||
|  | 910ad45bee | ||
|  | 74e319855d | ||
|  | 9af0fb4cd5 | ||
|  | 185f5cce29 | ||
|  | aca1174566 | ||
|  | e791f7fde2 | ||
|  | 7bba7fcf66 | ||
|  | 1d78f98ec8 | ||
|  | 7ed2e03654 | ||
|  | 549e0f3477 | ||
|  | 7785ec0222 | ||
|  | ca504965f9 | ||
|  | 3841259779 | ||
|  | 169d1065cc | ||
|  | e864f5507a | ||
|  | 434b4ded4a | ||
|  | 3d01669cea | ||
|  | 1499b2cd40 | ||
|  | 6b54ef8398 | ||
|  | 07ad43f7a2 | ||
|  | 72e72c60c2 | ||
|  | f9a242d33e | ||
|  | b0f43eaa07 | ||
|  | b02046b884 | ||
|  | 864c931ee9 | ||
|  | 5cd8da6d91 | ||
|  | 4a4671c2ae | ||
|  | 8de142cd9a | ||
|  | 1a42bec51c | ||
|  | 577e38759e | ||
|  | 9cdf43a2c9 | ||
|  | 62d43c2cb2 | ||
|  | 2dc67d1674 | ||
|  | fb1c78c657 | ||
|  | 37e58ac13a | ||
|  | de715c14be | ||
|  | c4d8a0da05 | ||
|  | 1b54b14671 | ||
|  | a92efbc55f | ||
|  | 1bd02529e0 | ||
|  | bc16298b6e | ||
|  | 804a97cad7 | ||
|  | ab52bdec15 | ||
|  | ddc3e82c14 | ||
|  | 57691471bb | ||
|  | c502dd445b | ||
|  | ed475b1b9c | ||
|  | df165a817c | ||
|  | d16015d625 | ||
|  | a4b3bf3ef4 | ||
|  | 6b006853e6 | ||
|  | 6001180e29 | ||
|  | 662fbed1d0 | ||
|  | 19c7e08c5d | ||
|  | 72f04aaedc | ||
|  | 2998382969 | ||
|  | 37fe79944f | ||
|  | 536735519a | ||
|  | 6b0a711395 | ||
|  | 13d3d40376 | ||
|  | 6873336aca | ||
|  | c2d2eb53e8 | ||
|  | 210d597a48 | ||
|  | e41ede0a6b | ||
|  | 4a8b17ac7c | ||
|  | 1f5f515d72 | ||
|  | 1e6242b89f | ||
|  | dde09f9f89 | ||
|  | 916d85c3fe | ||
|  | b243ed93aa | ||
|  | 70d28bbf6e | ||
|  | 3c76da7132 | ||
|  | 3254565c09 | ||
|  | cd0033791f | ||
|  | 2427ee44a5 | ||
|  | ff0e617b2a | ||
|  | e6cfe040b5 | ||
|  | 94e2f9b6dc | ||
|  | 512b81ad93 | ||
|  | fc0e76f431 | ||
|  | 9da69358e2 | ||
|  | aa246b0b2b | ||
|  | 6ed649bc8a | ||
|  | 725f5b7110 | ||
|  | 5a890c5c3a | ||
|  | 7752329b94 | ||
|  | 5f48f13890 | ||
|  | a734e04561 | ||
|  | 5aa1db293f | ||
|  | f89aee37f5 | ||
|  | 538018fed1 | ||
|  | a2327c50ec | ||
|  | c2711023e2 | ||
|  | cac30f0b4c | ||
|  | 4bb17019a4 | ||
|  | ba2a40bdf3 | ||
|  | f3460cca49 | ||
|  | 64ce53ac30 | ||
|  | a43238360c | ||
|  | b2cbadf5d8 | ||
|  | 81640ba06d | ||
|  | 9327430484 | ||
|  | a24c90eae8 | ||
|  | 1d3987ece6 | ||
|  | 83f5b5e293 | ||
|  | f231263085 | ||
|  | 4ad67a87f1 | ||
|  | b766d93d9a | ||
|  | 0905ceb1d5 | ||
|  | 2fbf837354 | ||
|  | 4bd79c880c | ||
|  | 4af041e015 | ||
|  | 8dc3e3ec93 | ||
|  | f4b68d26d6 | ||
|  | 1887977b92 | ||
|  | 8eb84acf4f | ||
|  | 1b685da3e3 | ||
|  | 406b658801 | ||
|  | bba1ee1264 | ||
|  | 02b6191d47 | ||
|  | c5a3de09cd | ||
|  | 0afe2a680e | ||
|  | 03e0510c4f | ||
|  | 1068dcb8a4 | ||
|  | 10a93df653 | ||
|  | 79ff67852f | ||
|  | a36cab969f | ||
|  | 45447646fa | ||
|  | 8a0f76ab68 | ||
|  | 037135e764 | ||
|  | 21e89c3b64 | ||
|  | bd11ec69fa | ||
|  | 9e2b34bc12 | ||
|  | 0faebc290f | ||
|  | fc0ef4b79d | ||
|  | 027b954b50 | ||
|  | 33c830a432 | ||
|  | a7887f1e25 | ||
|  | fa7a59572a | ||
|  | d9c2df5b0d | ||
|  | a854b2c17e | ||
|  | 7d4006b205 | ||
|  | 86ecca6011 | ||
|  | 0ea5cf2caa | ||
|  | a950e02e9b | ||
|  | 9eec6641dd | ||
|  | 18f46676fd | ||
|  | 9735ef6d41 | ||
|  | d3e8ceee00 | ||
|  | 144e329eca | ||
|  | 21d5420b2a | ||
|  | 3011b5074d | ||
|  | 83190572c7 | ||
|  | 9cf9e5f865 | ||
|  | 5bdef7f1c7 | ||
|  | ba285a2d2d | ||
|  | 0dff371e62 | ||
|  | ce4a2a5851 | ||
|  | 2c978dc89a | ||
|  | 4b8b819109 | ||
|  | c230b3a806 | ||
|  | df08b9c5c6 | ||
|  | eca65376a3 | ||
|  | 88e3705636 | ||
|  | 5476509ef5 | ||
|  | 0bd6636453 | ||
|  | 105894e00d | ||
|  | 230a319510 | ||
|  | ae16a2b14f | ||
|  | da0c0742bf | ||
|  | 61d60a9048 | ||
|  | 3e28e9a016 | ||
|  | 423f9fefa9 | ||
|  | 5707dc7579 | ||
|  | 3be1cdb249 | ||
|  | 426d3d948c | ||
|  | 9a3aed8038 | ||
|  | fb58bf1bf5 | ||
|  | a6dbd912c6 | ||
|  | 65ce277a20 | ||
|  | 0b2d423c87 | ||
|  | da056092fb | ||
|  | 45aa85d690 | ||
|  | 5c35fee0c2 | ||
|  | 24bdc319dd | ||
|  | f1dcc41e42 | ||
|  | 550f301ba2 | ||
|  | d9bf4d1c0d | ||
|  | c3c1a6eb22 | ||
|  | 2c4454418e | ||
|  | e44de572f5 | ||
|  | f27919f91b | ||
|  | ba9968bde0 | ||
|  | 05ea8216ff | ||
|  | fa1695672a | ||
|  | ac6f98fc47 | ||
|  | 1a1f89f555 | ||
|  | 6c3262e176 | ||
|  | b4bdb48f1e | ||
|  | 823afe877b | ||
|  | cb8e082414 | ||
|  | 98c1fcc68f | ||
|  | 8c439a2852 | ||
|  | 50c6109be7 | ||
|  | 6e362663b5 | ||
|  | 74c9feb53f | ||
|  | 402e8588cf | ||
|  | 778a42bcc0 | ||
|  | 584f7ced84 | ||
|  | 8e892e7ea5 | ||
|  | 3386c8b455 | ||
|  | 6fa73ee28d | ||
|  | 8ec8042045 | ||
|  | cddc123539 | ||
|  | 4c2938c5cd | ||
|  | 6d03ddadcc | ||
|  | 64311da4b4 | ||
|  | 0cbb50ae9d | ||
|  | 7e96054dc2 | ||
|  | 578298580e | ||
|  | ee5afaa6bc | ||
|  | 15b023d116 | ||
|  | 1ef96c0b4d | ||
|  | 8c3ae40de1 | ||
|  | 94fcfacec4 | ||
|  | ba7c01c6bc | ||
|  | 9f92e1b7bd | ||
|  | 1f0e692ee2 | ||
|  | 0acd75a24f | ||
|  | eedf27f8a5 | ||
|  | b451e207e2 | ||
|  | c0c37eec7b | ||
|  | 89363ecfa3 | ||
|  | 593e799ca1 | ||
|  | 8fc055cad9 | ||
|  | 75f86462e2 | ||
|  | 40892ccfa7 | ||
|  | 87fbf9c1a5 | ||
|  | 4944b233b6 | ||
|  | 9f23462c42 | ||
|  | 84a24f0333 | ||
|  | 7a885bfc3c | ||
|  | 3ba0cf1454 | ||
|  | 2d67a3159d | ||
|  | 290f25f1a0 | ||
|  | 1659904f81 | ||
|  | 230bd6e40a | ||
|  | ce27e97b92 | ||
|  | 18c1223c7b | ||
|  | 8ef659f5de | ||
|  | 037452e525 | ||
|  | e3482011d5 | ||
|  | 62748fa255 | ||
|  | 7a9df05f6b | ||
|  | 335279e728 | ||
|  | 0332104738 | ||
|  | 9f04854902 | ||
|  | 73008a35fe | ||
|  | eae96cd2af | ||
|  | cb670bb27d | ||
|  | fe1fb23e5b | ||
|  | c2dd61e96b | ||
|  | 80f5e61b6b | ||
|  | dbcae16b75 | ||
|  | 886dcae822 | ||
|  | ed495ec600 | ||
|  | ddb60ccdc5 | ||
|  | 335e2083af | ||
|  | 7b1d9d4962 | ||
|  | da6ff9f90a | ||
|  | 48f26c7bf1 | ||
|  | 3ce317b170 | ||
|  | b741565f57 | ||
|  | d8fea44968 | ||
|  | 778300b67e | ||
|  | cb2b44fef3 | ||
|  | cdb5875d6b | ||
|  | 01c5e15bcd | ||
|  | f0babb4be7 | ||
|  | 10b00da874 | ||
|  | e9f391b2eb | ||
|  | 50be39b054 | ||
|  | a94e0bb3da | ||
|  | 3f65d5d760 | ||
|  | 48cb528ae4 | ||
|  | e62e0345df | ||
|  | 441f011fba | ||
|  | af1349160a | ||
|  | 2072607889 | ||
|  | 073fd5aa0d | ||
|  | 7b4703e4ff | ||
|  | 1484621300 | ||
|  | 40709c8367 | ||
|  | b6ab5770a2 | ||
|  | 83b7cb4ff9 | ||
|  | 256dba66b2 | ||
|  | 6ac12f8ffa | ||
|  | 82e438d29b | ||
|  | e86547645c | ||
|  | 8b901084fe | ||
|  | 1a0cbbdb31 | ||
|  | 30ac62ffb7 | ||
|  | 8ab294e90b | ||
|  | f5edb15f43 | ||
|  | eed6107ce7 | ||
|  | d49dc599a2 | ||
|  | 3c5179f145 | ||
|  | 067d17c09c | ||
|  | 4c88c9af86 | ||
|  | 1c84afe186 | ||
|  | 9d4c4be468 | ||
|  | de7db8db78 | ||
|  | 407ba4dd6d | ||
|  | 5135be3000 | ||
|  | b8ab7d1a14 | ||
|  | 6211fd8496 | ||
|  | a4f273b48b | ||
|  | 68d820a97c | ||
|  | ebadfd6358 | ||
|  | cf93a88adc | ||
|  | bd2c4252bb | ||
|  | 84e7af04b9 | ||
|  | 37c63bc6b5 | ||
|  | e7d3716549 | ||
|  | 73bc5372c0 | ||
|  | b999a8f0fb | ||
|  | 16678aa5e1 | ||
|  | f9ab49911d | ||
|  | 3fabe2e9fb | ||
|  | 9a8a3e94d6 | ||
|  | 32ef2ef801 | ||
|  | 76cd3d35e2 | ||
|  | 900dea2c66 | ||
|  | 8e6ca0dd05 | ||
|  | 4b4ad7f1a8 | ||
|  | 21a0a5d573 | ||
|  | 3cfa3f3b27 | ||
|  | c77b43458e | ||
|  | 9ab0a83f7c | ||
|  | d3cda8811d | ||
|  | 55740c0d97 | ||
|  | c0a524c8a3 | ||
|  | e51c2d10f0 | ||
|  | 7af55b7268 | ||
|  | 7350b1da1b | ||
|  | 136adbe723 | ||
|  | cb2863eaf3 | ||
|  | d054f9b92f | ||
|  | 9c83c18137 | ||
|  | 999a7481e4 | ||
|  | a3b684b4ed | ||
|  | cb312ca025 | ||
|  | 1335a52db3 | ||
|  | 727221e2cb | ||
|  | 360f286ed3 | ||
|  | 6aecd77b77 | ||
|  | ca85cab6fb | ||
|  | 742479bb01 | ||
|  | 68e54a9297 | ||
|  | 056d83eda4 | ||
|  | 42ec55d0db | ||
|  | c89bd89d9a | ||
|  | 31a0be5bb4 | ||
|  | 07610ae8fb | ||
|  | dbc95dd878 | ||
|  | 792e8a9947 | ||
|  | d774cde109 | ||
|  | cc111d14b0 | ||
|  | bb3ba42ce2 | ||
|  | f4ecf2d1aa | ||
|  | 1997666196 | ||
|  | 3aa9057c5f | ||
|  | 834f8382e9 | ||
|  | 357638a26c | ||
|  | 919a0c01e4 | ||
|  | 6ff618e388 | ||
|  | ac765b7e4c | ||
|  | 2134e87c31 | ||
|  | 0d37288129 | ||
|  | 7cbd41137d | ||
|  | ba43d7063f | ||
|  | c9b2e29ba0 | ||
|  | 4720519aef | ||
|  | d7b0106e7d | ||
|  | 0a2cbaa047 | ||
|  | 3e5f615ffc | ||
|  | 00dc73e6d9 | ||
|  | aa5b9a1727 | ||
|  | f63a287a6c | ||
|  | b9d4c8dcd6 | ||
|  | 94433f1714 | ||
|  | a4dd4358b4 | ||
|  | 4e79b43395 | ||
|  | 6bb54bfa85 | ||
|  | 0df6c3a8dc | ||
|  | dc25086eab | ||
|  | 3299188edf | ||
|  | f6afb46f6f | ||
|  | 98993cfa9b | ||
|  | 5a920d5efd | ||
|  | 935276af88 | ||
|  | 5a505c8469 | ||
|  | 2c2abe8b8e | ||
|  | 638099d989 | ||
|  | 0f32f6be4c | ||
|  | 1f7c98bdcf | ||
|  | 72068a4b78 | ||
|  | c8038e0774 | ||
|  | 6b39beecb4 | ||
|  | b1ba64db12 | ||
|  | ad53832766 | ||
|  | d5bffc8ed7 | ||
|  | 69b36ddd1d | ||
|  | 9f926394a6 | ||
|  | 1e7ecbdf9d | ||
|  | beb8a461cf | ||
|  | e235a57e2f | ||
|  | 114b27079e | ||
|  | 6e19bc01f5 | ||
|  | f9dfdeafb3 | ||
|  | f05d626e38 | ||
|  | 918041258e | ||
|  | a5b13aa67f | ||
|  | 1383cbd4d5 | ||
|  | e9b7e82aea | ||
|  | fd6e7fc1ab | ||
|  | 743deb4227 | ||
|  | b051278d2e | ||
|  | bfda4bc199 | ||
|  | 4456ef2326 | ||
|  | 7336367eff | ||
|  | 9cb6c7697e | ||
|  | cd44f51072 | ||
|  | d8976379b1 | ||
|  | 8aa847c718 | ||
|  | 6691b238f7 | ||
|  | cca2758138 | ||
|  | 4a74e68e31 | ||
|  | 3d3842b9d6 | ||
|  | 9d889d05e4 | ||
|  | 9f920bcfe3 | ||
|  | 1bb49fa496 | ||
|  | 6b1d8d3aaa | ||
|  | c6b6ed7fa8 | ||
|  | 34454261d2 | ||
|  | ddf9f52737 | ||
|  | 10b969a074 | ||
|  | 5df0634380 | ||
|  | f0f965421c | ||
|  | 6381408fba | ||
|  | 43e738cb44 | ||
|  | 6d4303aa3f | ||
|  | 13c2db5378 | ||
|  | 36f6bda525 | ||
|  | 78886e7b1f | ||
|  | 3dce194930 | ||
|  | ec776bb6eb | ||
|  | 243d942a6e | ||
|  | ea6aba62c4 | ||
|  | 73743721b1 | ||
|  | 61eb5b341d | ||
|  | d758f72393 | ||
|  | 1b1367f4c2 | ||
|  | 07388dd58a | ||
|  | 359c71ef2f | ||
|  | 93d4d3df1d | ||
|  | d3a7596be2 | ||
|  | 114d3812cc | ||
|  | b2d4dcfbf1 | ||
|  | 0baf8f6d18 | ||
|  | 2f8e3a0707 | ||
|  | d7a4bf22c6 | ||
|  | 0c2f9d22b9 | ||
|  | e75c5aac49 | ||
|  | 77e5024f54 | ||
|  | 7329c0b200 | ||
|  | 0afe3c48a1 | ||
|  | 1ab5e923bc | ||
|  | 90b3bd77e7 | ||
|  | 9c60443f97 | ||
|  | 058e5602a3 | ||
|  | eebac2a66d | ||
|  | 7e8f5c9548 | ||
|  | d34b49bd48 | ||
|  | ccffae287d | ||
|  | ad69011ac5 | ||
|  | f8ea0f971d | ||
|  | 9918410954 | ||
|  | 4f4e6fac16 | ||
|  | 15e99bd672 | ||
|  | 696e9a6fde | ||
|  | 36cbb3d71f | ||
|  | f69598c6aa | ||
|  | 5fc31f3c1e | ||
|  | 6581ee0ee0 | ||
|  | 69e7501d47 | ||
|  | 314abbea8b | ||
|  | 82c9a75578 | ||
|  | 651101912c | ||
|  | fb0d463040 | ||
|  | 8c254554eb | ||
|  | 2d9c89375a | ||
|  | 61aba29df7 | ||
|  | 8c949e6190 | ||
|  | 6eb9188690 | ||
|  | 6832f2ebd0 | ||
|  | 3e02b50ea1 | ||
|  | 7b7743c03e | ||
|  | de20563275 | ||
|  | 9e720c3a38 | ||
|  | 54685c1f5f | ||
|  | eb8f8fa935 | ||
|  | 9adbbd872c | ||
|  | 4bd38f97a2 | ||
|  | 78ab1e200a | ||
|  | 11280e473d | ||
|  | f9750a64f8 | ||
|  | ac2ab65471 | ||
|  | 0530c0402c | ||
|  | a58a560bbb | ||
|  | 96ab112b22 | ||
|  | b388dcc7d4 | ||
|  | f511a25c94 | ||
|  | 58d8b6f95b | ||
|  | 953d68c3a2 | ||
|  | 9e2f7af59b | ||
|  | 840dfa6696 | ||
|  | 4a20c008ff | ||
|  | 981ffe4194 | ||
|  | 2597633b0e | ||
|  | 71d174d765 | ||
|  | 4aa9a04516 | ||
|  | 258d6a1688 | ||
|  | 2e2c12d6a4 | ||
|  | 44d189d7d3 | ||
|  | ab508a3d9e | ||
|  | 4e166c7d2e | ||
|  | 7f175a4870 | ||
|  | 0a627f6f9e | ||
|  | d34cc65984 | ||
|  | 78d034d366 | ||
|  | 638fa9005f | ||
|  | 5cb9907bf8 | ||
|  | f08fcc36fb | ||
|  | d231cd9f61 | ||
|  | 86a586f866 | ||
|  | 9d4cba1620 | ||
|  | e9afd55e9d | ||
|  | 9fa326f630 | ||
|  | af9473c126 | ||
|  | cb08df0770 | ||
|  | d49ca2eb11 | ||
|  | a3f8841ec3 | ||
|  | fd678c286d | ||
|  | 2a3f9b621b | ||
|  | 359e1b3943 | ||
|  | 754336b3cf | ||
|  | 4918f1c4cb | ||
|  | 5d5e308942 | ||
|  | 6a18f81cec | ||
|  | 1ff135d172 | ||
|  | e666e5e9e3 | ||
|  | 9874e77ddf | ||
|  | 27e3ec693a | ||
|  | 6bb1415ad7 | ||
|  | 83594e6f1f | ||
|  | 0f6008705c | ||
|  | c58b653bb7 | ||
|  | f69b6f9b4e | ||
|  | 7750b06476 | ||
|  | 873384a34b | ||
|  | ac299e7279 | ||
|  | 7895d7f5d0 | ||
|  | fe05d218fc | ||
|  | 8196313ac0 | ||
|  | 6d8f84654f | ||
|  | ab4f34a96b | ||
|  | 139d985904 | ||
|  | 44705f0e18 | ||
|  | ddea7d696a | ||
|  | f814f45e36 | ||
|  | f7117d47c2 | ||
|  | 01b0a1058d | ||
|  | 21f362c7b9 | ||
|  | aaab7f8e0e | ||
|  | 09e1f68c69 | ||
|  | 03729aa5ae | ||
|  | ef39f31ea1 | ||
|  | 0f1437dd6a | ||
|  | 03aac2f744 | ||
|  | 2f8b10e82c | ||
|  | 3231effd20 | ||
|  | f7722c1189 | ||
|  | 70c2450ac4 | ||
|  | 2d5b0d0f99 | ||
|  | f0c0002a6d | ||
|  | dd9f08d4fa | ||
|  | de2e384225 | ||
|  | ffcd1fde0f | ||
|  | d5e1da5948 | ||
|  | ad479a5c7f | ||
|  | 0707603b63 | ||
|  | 2f9c383004 | ||
|  | 8ad0d7af93 | ||
|  | 9b4391c0bf | ||
|  | da7802a0a4 | ||
|  | 9c69949e8c | ||
|  | b1d7a9451a | ||
|  | 004488d453 | ||
|  | fc91372dd0 | ||
|  | 5970a9dc91 | ||
|  | 264cac4f9b | ||
|  | 633328a965 | ||
|  | 4d4b62a766 | ||
|  | aeb2c7deeb | ||
|  | c323942d92 | ||
|  | a0afa25145 | ||
|  | 4533b46436 | ||
|  | e5f8db78f9 | ||
|  | 899f61671f | ||
|  | d84d88cc10 | ||
|  | 97e7ac4052 | ||
|  | ba4ffa44d2 | ||
|  | 07caeccf68 | ||
|  | d54832f61f | ||
|  | b212753633 | ||
|  | f38d80cbf5 | ||
|  | 8bea1acd8e | ||
|  | 42458ce11d | ||
|  | aceb683d07 | ||
|  | b7517b49ed | ||
|  | 849b711b79 | ||
|  | 25585b28c7 | ||
|  | 073da8fb2a | ||
|  | a787ff3f3c | ||
|  | 733b6d7eb7 | ||
|  | 36d8dee853 | ||
|  | 65a2e07d24 | ||
|  | 7c97c558ab | ||
|  | a6bb61050c | ||
|  | b184aa2315 | ||
|  | e4595333e7 | ||
|  | 41dd139bde | ||
|  | c577dd302a | ||
|  | 0ab87de78b | ||
|  | 8a22509b41 | ||
|  | b024c18441 | ||
|  | d9ac681a68 | ||
|  | 637a5579ec | ||
|  | 4794156e80 | ||
|  | 5f4db7874c | ||
|  | b4ea1839a5 | ||
|  | 6a6d889983 | ||
|  | 287c2e7af8 | ||
|  | 0fe6acc8cf | ||
|  | 7d2dab7ca0 | ||
|  | f68c1aff26 | ||
|  | 81662473a6 | ||
|  | d40645be68 | ||
|  | a53550537f | ||
|  | 223ad16616 | ||
|  | 3f060979d7 | ||
|  | 2eac9081ea | ||
|  | b3eef4f40b | ||
|  | dd70fbad3f | ||
|  | 8cb7a1aef8 | ||
|  | a687140056 | ||
|  | 3cba673a9c | ||
|  | 01de230785 | ||
|  | e405d06f23 | ||
|  | d9b70f7ad8 | ||
|  | 0ef5825d98 | ||
|  | 1e76a5fc3f | ||
|  | 1fbdb3d0ae | ||
|  | d5bcf5497f | ||
|  | 28aaea1aa3 | ||
|  | 980d9ce885 | ||
|  | ec601efa6e | ||
|  | b3209d3b4d | ||
|  | 4ce978b9f3 | ||
|  | a84064663a | ||
|  | 6798cea268 | ||
|  | 8e86196352 | ||
|  | 1b3d345fbd | ||
|  | 7d2627515f | ||
|  | aa9eb8ca64 | ||
|  | 9015d6ca16 | ||
|  | 217483639d | ||
|  | 78e80530d3 | ||
|  | 3bbecfe830 | ||
|  | 9ab3679d49 | ||
|  | fc44a52ba5 | ||
|  | bb2b71bdc0 | ||
|  | b23d2a9d95 | ||
|  | eeb773fd7b | ||
|  | 53a582f374 | ||
|  | 73110f6a51 | ||
|  | 5667663fef | ||
|  | fb664ba17d | ||
|  | 0c10190a8e | ||
|  | 183a323ef6 | ||
|  | 90bada5497 | ||
|  | 7c043e1923 | ||
|  | 2720ae3c46 | ||
|  | 401508577e | ||
|  | b0a31cebc2 | ||
|  | 95adb428fa | ||
|  | f92a0310dd | ||
|  | 84f0cb3765 | ||
|  | d49e6787d6 | ||
|  | 0884853a6f | ||
|  | 1967c63006 | ||
|  | 9461e7b70a | ||
|  | f1e5df566c | ||
|  | fb02a0d5ad | ||
|  | e438a02fa3 | ||
|  | b112452aa1 | ||
|  | 1a2fc81af3 | ||
|  | 38bbda982c | ||
|  | 41ad6e64d1 | ||
|  | efcad0b935 | ||
|  | e892b69a96 | ||
|  | 5dfc04e777 | ||
|  | c119a42d70 | ||
|  | 802541b796 | ||
|  | 0770c79777 | ||
|  | 5f4669341e | ||
|  | f15fc80233 | ||
|  | a7d75ea94a | ||
|  | ba4bddf756 | ||
|  | 6a26408552 | ||
|  | c39c59fff5 | ||
|  | c1ba8dc6a7 | ||
|  | f2825da878 | ||
|  | c61f1307d8 | ||
|  | 9e88d7a60d | ||
|  | 406ae25162 | ||
|  | dbfb342021 | ||
|  | 4632142e06 | ||
|  | 9ae036f297 | ||
|  | 497b8c48c8 | ||
|  | 5d11949313 | ||
|  | a91c9f04c5 | ||
|  | 4f3493f9ff | ||
|  | 49b8742082 | ||
|  | 69cee59e23 | ||
|  | 19402b9022 | ||
|  | 62ba40b687 | ||
|  | f9af9a4fbe | ||
|  | c2ab43d0ab | ||
|  | af28e6e7b9 | ||
|  | 114ad7f292 | ||
|  | 44eb67f94e | ||
|  | 0203fee174 | ||
|  | a1ba340ead | ||
|  | 0ae9ff4575 | ||
|  | 5b501cb942 | ||
|  | 0255b7a4a0 | ||
|  | 15ef0bab1d | ||
|  | decad6830b | ||
|  | b6e0b985c2 | ||
|  | c140f71878 | ||
|  | 87044e6b8e | ||
|  | affa9014d2 | ||
|  | 4bbc3c3bd8 | ||
|  | d296dbbc23 | ||
|  | 9bcd27b847 | ||
|  | 2a54b36db0 | ||
|  | 77fb02daa4 | ||
|  | 1963ac191f | ||
|  | 33da8aa987 | ||
|  | 0192484044 | ||
|  | 3c0863d8ea | ||
|  | 710d6dfb74 | ||
|  | 2359542d72 | ||
|  | e1a2b4b9af | ||
|  | 0eadfa1c83 | ||
|  | c8dd935460 | ||
|  | e2227271b5 | ||
|  | 7a639a1d6e | ||
|  | 9edb9b91b2 | ||
|  | b2adeb20d9 | ||
|  | fa665de847 | ||
|  | ab9e5f716d | ||
|  | 5788db9f07 | ||
|  | 3068a8d58d | ||
|  | 14aacf42b9 | ||
|  | d1b97da309 | ||
|  | 867074e7b2 | ||
|  | 18748510b1 | ||
|  | bcf71cdf85 | ||
|  | 3290ce85a9 | ||
|  | 60ef80c1a5 | ||
|  | 74e852b8bd | ||
|  | 90ae21d257 | ||
|  | fdf03cd8e2 | ||
|  | f6586be5e7 | ||
|  | f9dc627d84 | ||
|  | 309177ca9c | ||
|  | 456d2342b6 | ||
|  | 0717aa22d7 | ||
|  | b8e07ac38e | ||
|  | c7273e4b60 | ||
|  | 33d4fd4af0 | ||
|  | 71b11e26d2 | ||
|  | 77f4111b09 | ||
|  | 9965297f36 | ||
|  | 5ca466a826 | ||
|  | 90f417facc | ||
|  | eacbd038b7 | ||
|  | 5446e85424 | ||
|  | 77b4942691 | ||
|  | 824cf71e0b | ||
|  | 239bbd30c0 | ||
|  | 6f6b653d54 | ||
|  | e4155ce735 | ||
|  | 7eaf307834 | ||
|  | 7db7950415 | ||
|  | fcc184cd2a | ||
|  | 6423feff3a | ||
|  | e97da25d5a | ||
|  | f49a37a38e | ||
|  | 07e6b33095 | ||
|  | 9136b50e3c | ||
|  | c3fd5c7136 | ||
|  | 98612dd253 | ||
|  | 4d7f5238dd | ||
|  | f472a01a80 | ||
|  | 420b5790e3 | ||
|  | 2e342e47a7 | ||
|  | 58b3334f05 | ||
|  | 4cd955e5cf | ||
|  | 4dbf410cdf | ||
|  | 074e6d52b1 | ||
|  | a0a36c5137 | ||
|  | 9db4137a1b | ||
|  | 85f1e744b8 | ||
|  | 8d90061d90 | ||
|  | b20d84e4b8 | 
| @@ -1 +1,3 @@ | ||||
| src_dir: . | ||||
| coverage_clover: storage/coverage/clover.xml | ||||
| json_path: storage/coverage/coveralls-upload.json | ||||
							
								
								
									
										16
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| APP_ENV=local | ||||
| APP_DEBUG=true | ||||
| APP_KEY=SomeRandomString | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=localhost | ||||
| DB_DATABASE=homestead | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD=secret | ||||
|  | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
| EMAIL_SMTP= | ||||
| EMAIL_USERNAME= | ||||
| EMAIL_PASSWORD= | ||||
							
								
								
									
										13
									
								
								.env.testing
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.env.testing
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| APP_ENV=testing | ||||
| APP_DEBUG=true | ||||
| APP_KEY=SomeRandomString | ||||
|  | ||||
| DB_CONNECTION=sqlite | ||||
| DB_HOST=localhost | ||||
| DB_DATABASE=homestead | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD=secret | ||||
|  | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
							
								
								
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,30 @@ | ||||
| /bootstrap/compiled.php | ||||
| /vendor | ||||
| composer.phar | ||||
| composer.lock | ||||
| .env.*.php | ||||
| .env.php | ||||
| .DS_Store | ||||
| Thumbs.db | ||||
| .idea/ | ||||
| .DS_Store | ||||
| tests/_output/* | ||||
| _ide_helper.php | ||||
| /build/logs/clover.xml | ||||
| index.html* | ||||
| app/storage/firefly-export* | ||||
| app/storage/firefly-export* | ||||
| .vagrant | ||||
| firefly-iii-import-*.json | ||||
| tests/_output/* | ||||
| testing.sqlite | ||||
| _ide_helper_models.php | ||||
| clean.sqlite | ||||
| tests/acceptance/AcceptanceTester.php | ||||
| tests/functional/FunctionalTester.php | ||||
| tests/unit/UnitTester.php | ||||
| pi.php | ||||
| tests/_data/db.sqlite | ||||
| tests/_data/dump.sql | ||||
| db.sqlite_snapshot | ||||
| c3.php | ||||
| db.sqlite-journal | ||||
| tests/_output/* | ||||
| .env | ||||
| clover.xml | ||||
| node_modules/ | ||||
							
								
								
									
										18
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,13 +1,25 @@ | ||||
| language: php | ||||
| sudo: false | ||||
|  | ||||
|  | ||||
| php: | ||||
|   - 5.5 | ||||
|   - 5.4 | ||||
|   - hhvm | ||||
|   - 5.6 | ||||
|  | ||||
| addons: | ||||
|   code_climate: | ||||
|     repo_token: 26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61 | ||||
|  | ||||
| install: | ||||
|   - rm composer.lock | ||||
|   - composer install | ||||
|   - php artisan env | ||||
|   - mv -v .env.testing .env | ||||
|   - touch tests/database/db.sqlite | ||||
|   - php artisan migrate --seed | ||||
|  | ||||
| script: | ||||
|   - phpunit --debug | ||||
|  | ||||
| after_script: | ||||
|   - php vendor/bin/coveralls | ||||
|  | ||||
|   | ||||
							
								
								
									
										78
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,55 +1,79 @@ | ||||
| firefly-iii | ||||
| Firefly III (v3.3.4) | ||||
| =========== | ||||
|  | ||||
| [](https://travis-ci.org/JC5/firefly-iii) | ||||
| [](https://coveralls.io/r/JC5/firefly-iii?branch=master) | ||||
|  | ||||
| [](https://travis-ci.org/JC5/firefly-iii) | ||||
| [](http://stillmaintained.com/JC5/firefly-iii) | ||||
| [](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) | ||||
| [](https://codeclimate.com/github/JC5/firefly-iii) | ||||
| [](https://codeclimate.com/github/JC5/firefly-iii) | ||||
|  | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
|  | ||||
| Firefly III is a tool to help you manage your finances. Please read the full description [in the wiki](https://github.com/JC5/firefly-iii/wiki/full-description). | ||||
|  | ||||
| Firefly Mark III is a new version of Firefly built upon best practices and lessons learned | ||||
| from building [Firefly](https://github.com/JC5/Firefly). It's Mark III since the original Firefly never made it outside of my | ||||
| laptop and [Firefly II](https://github.com/JC5/Firefly) is live. | ||||
|  | ||||
| If you're not sure if this tool is for you, please read the [full description](https://github.com/JC5/firefly-iii/wiki/full-description). | ||||
|  | ||||
| To install and use Firefly III, please read [the installation guide](https://github.com/JC5/firefly-iii/wiki/Installation), | ||||
|  [the upgrade guide](https://github.com/JC5/firefly-iii/wiki/Upgrade-instructions) (if applicable) and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)** | ||||
|  | ||||
| ## Current features | ||||
|  | ||||
| - [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system); | ||||
| - You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management; | ||||
| - It's possible to create, change and manage money using _budgets_; | ||||
| - Organize transactions using categories; | ||||
| - Save towards a goal using piggy banks; | ||||
| - Predict and anticipate bills; | ||||
| - View income / expense reports; | ||||
| - Lots of help text in case you don't get it; | ||||
|  | ||||
| Everything is organised: | ||||
|  | ||||
| - Clear views that should show you how you're doing; | ||||
| - Easy navigation through your records; | ||||
| - Browse back and forth to see previous months or even years; | ||||
| - Lots of charts because we all love them. | ||||
| - Financial reporting showing you how well you are doing; | ||||
|  | ||||
| ## Changes | ||||
|  | ||||
| Firefly III will feature: | ||||
| Firefly III will feature, but does not feature yet: | ||||
|  | ||||
|  | ||||
| - Double-entry bookkeeping system; | ||||
| - Better budgeting tools; | ||||
| - Better financial reporting; | ||||
| - More control over other resources outside of personal finance | ||||
|   - Accounts shared with a partner (household accounts) | ||||
|   - Debts | ||||
|   - Credit cards | ||||
| - More robust code base (mainly for my own peace of mind); | ||||
| - More test-coverage (aka: actual test coverage); | ||||
|  | ||||
| ## More features | ||||
|   | ||||
| - More test-coverage; | ||||
| - Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control. | ||||
| - Firefly will be able to join transactions. | ||||
| - Transfers and transactions will be combined into one internal datatype which is more consistent with what you're actually doing: moving money from A to B. The fact that A or B or both are yours should not matter. And it will not, in the future. | ||||
| - The nesting of budgets, categories and beneficiaries will be removed. | ||||
| - Firefly will be able to automatically login a specified account. Although this is pretty unsafe, it removes the need for you to login to your own tool.  | ||||
| - Any other features I might not have thought of. | ||||
|  | ||||
| ## Not changed | ||||
| Some stuff has been removed: | ||||
|  | ||||
| - Firefly will not encrypt the content of the (MySQL) tables. Old versions of Firefly had this capability but it sucks when searching, sorting and organizing entries. | ||||
| - The nesting of budgets, categories and beneficiaries is removed because it was pretty pointless. | ||||
|  | ||||
| ## Screenshots | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Current state | ||||
| I have the basics up and running and test coverage is doing very well. | ||||
| I have the basics up and running. Test coverage is currently coming, slowly. | ||||
|  | ||||
| Current issues are the consistent look-and-feel of forms and likewise, the consistent inner workings of most of Firefly. | ||||
| Example: every "create"-action tends to be slightly different from the rest. Also is the fact that not all lists | ||||
| and forms are equally well thought of; some are not looking very well or miss feedback. | ||||
|  | ||||
| Most forms will not allow you to enter invalid data because the database cracks, not because it's actually checked. | ||||
| I'm still thinking about a way to build consistent forms. Laravel doesn't really cut it. | ||||
|  | ||||
| A lot of views have CSRF vulnerabilities. The general advice is NOT to use this tool in production. | ||||
| Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all | ||||
| views escape all characters by default. Will be fixed. | ||||
|  | ||||
| Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! | ||||
|   | ||||
							
								
								
									
										11
									
								
								app/Commands/Command.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/Commands/Command.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| <?php namespace FireflyIII\Commands; | ||||
| /** | ||||
|  * Class Command | ||||
|  * | ||||
|  * @package FireflyIII\Commands | ||||
|  */ | ||||
| abstract class Command | ||||
| { | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										37
									
								
								app/Console/Commands/Inspire.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Console/Commands/Inspire.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <?php namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Foundation\Inspiring; | ||||
|  | ||||
| /** | ||||
|  * Class Inspire | ||||
|  * | ||||
|  * @package FireflyIII\Console\Commands | ||||
|  */ | ||||
| class Inspire extends Command | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Display an inspiring quote'; | ||||
|     /** | ||||
|      * The console command name. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $name = 'inspire'; | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle() | ||||
|     { | ||||
|         $this->comment(PHP_EOL . Inspiring::quote() . PHP_EOL); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										37
									
								
								app/Console/Kernel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Console/Kernel.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <?php namespace FireflyIII\Console; | ||||
|  | ||||
| use Illuminate\Console\Scheduling\Schedule; | ||||
| use Illuminate\Foundation\Console\Kernel as ConsoleKernel; | ||||
|  | ||||
| /** | ||||
|  * Class Kernel | ||||
|  * | ||||
|  * @package FireflyIII\Console | ||||
|  */ | ||||
| class Kernel extends ConsoleKernel | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The Artisan commands provided by your application. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $commands | ||||
|         = [ | ||||
|             'FireflyIII\Console\Commands\Inspire', | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * Define the application's command schedule. | ||||
|      * | ||||
|      * @param  \Illuminate\Console\Scheduling\Schedule $schedule | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     protected function schedule(Schedule $schedule) | ||||
|     { | ||||
|         $schedule->command('inspire') | ||||
|                  ->hourly(); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										13
									
								
								app/Events/Event.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/Events/Event.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?php namespace FireflyIII\Events; | ||||
|  | ||||
| /** | ||||
|  * Class Event | ||||
|  * | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| abstract class Event | ||||
| { | ||||
|  | ||||
|     // | ||||
|  | ||||
| } | ||||
							
								
								
									
										33
									
								
								app/Events/JournalCreated.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/Events/JournalCreated.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <?php namespace FireflyIII\Events; | ||||
|  | ||||
| use FireflyIII\Events\Event; | ||||
|  | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class JournalCreated | ||||
|  * | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| class JournalCreated extends Event { | ||||
|  | ||||
| 	use SerializesModels; | ||||
|  | ||||
|     public $journal; | ||||
|     public $piggyBankId; | ||||
|  | ||||
| 	/** | ||||
| 	 * Create a new event instance. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function __construct(TransactionJournal $journal, $piggyBankId) | ||||
| 	{ | ||||
| 		// | ||||
|         $this->journal = $journal; | ||||
|         $this->piggyBankId = $piggyBankId; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										20
									
								
								app/Events/JournalDeleted.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Events/JournalDeleted.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| <?php namespace FireflyIII\Events; | ||||
|  | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| class JournalDeleted extends Event | ||||
| { | ||||
|  | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										25
									
								
								app/Events/JournalSaved.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Events/JournalSaved.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| <?php namespace FireflyIII\Events; | ||||
|  | ||||
| use FireflyIII\Events\Event; | ||||
|  | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| class JournalSaved extends Event { | ||||
|  | ||||
| 	use SerializesModels; | ||||
|  | ||||
|     public $journal; | ||||
|  | ||||
| 	/** | ||||
| 	 * Create a new event instance. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function __construct(TransactionJournal $journal) | ||||
| 	{ | ||||
| 		// | ||||
|         $this->journal = $journal; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,14 +1,14 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Firefly\Exception; | ||||
| namespace FireflyIII\Exceptions; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Class FireflyException | ||||
|  * | ||||
|  * @package Firefly\Exception | ||||
|  * @package FireflyIII\Exceptions | ||||
|  */ | ||||
| class FireflyException extends \Exception | ||||
| { | ||||
| 
 | ||||
| }  | ||||
| }  | ||||
							
								
								
									
										56
									
								
								app/Exceptions/Handler.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/Exceptions/Handler.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| <?php namespace FireflyIII\Exceptions; | ||||
|  | ||||
| use Exception; | ||||
| use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; | ||||
|  | ||||
| /** | ||||
|  * Class Handler | ||||
|  * | ||||
|  * @package FireflyIII\Exceptions | ||||
|  */ | ||||
| class Handler extends ExceptionHandler | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * A list of the exception types that should not be reported. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $dontReport | ||||
|         = [ | ||||
|             'Symfony\Component\HttpKernel\Exception\HttpException' | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * Render an exception into an HTTP response. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Exception               $e | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function render($request, Exception $e) | ||||
|     { | ||||
|         if ($this->isHttpException($e)) { | ||||
|             return $this->renderHttpException($e); | ||||
|         } else { | ||||
|             return parent::render($request, $e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Report or log an exception. | ||||
|      * | ||||
|      * This is a great spot to send exceptions to Sentry, Bugsnag, etc. | ||||
|      * | ||||
|      * @param  \Exception $e | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function report(Exception $e) | ||||
|     { | ||||
|         /** @noinspection PhpInconsistentReturnPointsInspection */ | ||||
|         return parent::report($e); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										13
									
								
								app/Exceptions/NotImplementedException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/Exceptions/NotImplementedException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Exceptions; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class NotImplementedException | ||||
|  * | ||||
|  * @package FireflyIII\Exceptions | ||||
|  */ | ||||
| class NotImplementedException extends \Exception | ||||
| { | ||||
|  | ||||
| }  | ||||
							
								
								
									
										12
									
								
								app/Exceptions/ValidationException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/Exceptions/ValidationException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Exceptions; | ||||
|  | ||||
| /** | ||||
|  * Class ValidationExceptions | ||||
|  * | ||||
|  * @package FireflyIII\Exception | ||||
|  */ | ||||
| class ValidationException extends \Exception | ||||
| { | ||||
|  | ||||
| }  | ||||
							
								
								
									
										89
									
								
								app/Handlers/Events/ConnectJournalToPiggyBank.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								app/Handlers/Events/ConnectJournalToPiggyBank.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Events\JournalCreated; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class ConnectJournalToPiggyBank | ||||
|  * | ||||
|  * @package FireflyIII\Handlers\Events | ||||
|  */ | ||||
| class ConnectJournalToPiggyBank | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle the event when journal is saved. | ||||
|      * | ||||
|      * @param  JournalCreated $event | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(JournalCreated $event) | ||||
|     { | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal     = $event->journal; | ||||
|         $piggyBankId = $event->piggyBankId; | ||||
|         if(intval($piggyBankId) < 1) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         Log::debug('JournalCreated event: ' . $journal->id . ', ' . $piggyBankId); | ||||
|  | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         $piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']); | ||||
|  | ||||
|         if (is_null($piggyBank) || $journal->transactionType->type != 'Transfer') { | ||||
|             return; | ||||
|         } | ||||
|         Log::debug('Found a piggy bank'); | ||||
|         $amount = 0; | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             if ($transaction->account_id === $piggyBank->account_id) { | ||||
|                 // this transaction is the relevant one. | ||||
|                 $amount = floatval($transaction->amount); | ||||
|             } | ||||
|         } | ||||
|         Log::debug('Amount: ' . $amount); | ||||
|         if ($amount == 0) { | ||||
|             return; | ||||
|         } | ||||
|         // update piggy bank rep for date of transaction journal. | ||||
|         $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|         if (is_null($repetition)) { | ||||
|             Log::debug('Found no repetition for piggy bank for date '.$journal->date->format('Y M d')); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         Log::debug('Found rep! ' . $repetition->id); | ||||
|         $repetition->currentamount += $amount; | ||||
|         $repetition->save(); | ||||
|  | ||||
|         PiggyBankEvent::create( | ||||
|             [ | ||||
|                 'piggy_bank_id'          => $piggyBank->id, | ||||
|                 'transaction_journal_id' => $journal->id, | ||||
|                 'date'                   => $journal->date, | ||||
|                 'amount'                 => $amount | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										33
									
								
								app/Handlers/Events/JournalDeletedHandler.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/Handlers/Events/JournalDeletedHandler.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use FireflyIII\Events\JournalDeleted; | ||||
| use Illuminate\Contracts\Queue\ShouldBeQueued; | ||||
| use Illuminate\Queue\InteractsWithQueue; | ||||
|  | ||||
| class JournalDeletedHandler | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  JournalDeleted $event | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(JournalDeleted $event) | ||||
|     { | ||||
|         // | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										53
									
								
								app/Handlers/Events/RescanJournal.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								app/Handlers/Events/RescanJournal.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use Log; | ||||
| use App; | ||||
|  | ||||
| /** | ||||
|  * Class RescanJournal | ||||
|  * | ||||
|  * @package FireflyIII\Handlers\Events | ||||
|  */ | ||||
| class RescanJournal | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  JournalSaved $event | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(JournalSaved $event) | ||||
|     { | ||||
|         $journal = $event->journal; | ||||
|  | ||||
|         Log::debug('Triggered saved event for journal #' . $journal->id . ' (' . $journal->description . ')'); | ||||
|  | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $list       = $journal->user->bills()->where('active', 1)->where('automatch', 1)->get(); | ||||
|  | ||||
|         Log::debug('Found ' . $list->count() . ' bills to check.'); | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($list as $bill) { | ||||
|             Log::debug('Now calling bill #' . $bill->id . ' (' . $bill->name . ')'); | ||||
|             $repository->scan($bill, $journal); | ||||
|         } | ||||
|  | ||||
|         Log::debug('Done!'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										64
									
								
								app/Handlers/Events/UpdateJournalConnection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								app/Handlers/Events/UpdateJournalConnection.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
|  | ||||
| class UpdateJournalConnection | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  JournalSaved $event | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(JournalSaved $event) | ||||
|     { | ||||
|         $journal = $event->journal; | ||||
|  | ||||
|         // get the event connected to this journal: | ||||
|         /** @var PiggyBankEvent $event */ | ||||
|         $event      = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first(); | ||||
|         if(is_null($event)) { | ||||
|             return; | ||||
|         } | ||||
|         $piggyBank  = $event->piggyBank()->first(); | ||||
|         $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|  | ||||
|         if (is_null($repetition)) { | ||||
|             return; | ||||
|         } | ||||
|         $amount = 0; | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             if ($transaction->account_id === $piggyBank->account_id) { | ||||
|                 // this transaction is the relevant one. | ||||
|                 $amount = floatval($transaction->amount); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // update current repetition: | ||||
|         $diff = $amount - $event->amount; | ||||
|  | ||||
|         $repetition->currentamount += $diff; | ||||
|         $repetition->save(); | ||||
|  | ||||
|  | ||||
|         $event->amount = $amount; | ||||
|         $event->save(); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										146
									
								
								app/Helpers/Reminders/ReminderHelper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								app/Helpers/Reminders/ReminderHelper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Reminders; | ||||
|  | ||||
| use Amount; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use Navigation; | ||||
|  | ||||
| /** | ||||
|  * Class ReminderHelper | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Reminders | ||||
|  */ | ||||
| class ReminderHelper implements ReminderHelperInterface | ||||
| { | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $start | ||||
|      * @param Carbon    $end | ||||
|      * | ||||
|      * @return Reminder | ||||
|      */ | ||||
|     public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $reminder = Auth::user()->reminders()->where('remindersable_id', $piggyBank->id)->onDates($start, $end)->first(); | ||||
|         if (is_null($reminder)) { | ||||
|  | ||||
|             if (!is_null($piggyBank->targetdate)) { | ||||
|                 // get ranges again, but now for the start date | ||||
|                 $ranges      = $this->getReminderRanges($piggyBank, $start); | ||||
|                 $currentRep  = $piggyBank->currentRelevantRep(); | ||||
|                 $left        = $piggyBank->targetamount - $currentRep->currentamount; | ||||
|                 $perReminder = $left / count($ranges); | ||||
|             } else { | ||||
|                 $perReminder = null; | ||||
|                 $ranges      = []; | ||||
|                 $left        = 0; | ||||
|             } | ||||
|             $metaData = [ | ||||
|                 'perReminder' => $perReminder, | ||||
|                 'rangesCount' => count($ranges), | ||||
|                 'ranges'      => $ranges, | ||||
|                 'leftToSave'  => $left, | ||||
|             ]; | ||||
|  | ||||
|  | ||||
|             // create one: | ||||
|             $reminder = new Reminder; | ||||
|             $reminder->user()->associate(Auth::user()); | ||||
|             $reminder->startdate = $start; | ||||
|             $reminder->enddate   = $end; | ||||
|             $reminder->active    = true; | ||||
|             $reminder->metadata  = $metaData; | ||||
|             $reminder->notnow    = false; | ||||
|             $reminder->remindersable()->associate($piggyBank); | ||||
|             $reminder->save(); | ||||
|  | ||||
|             return $reminder; | ||||
|  | ||||
|         } else { | ||||
|             return $reminder; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This routine will return an array consisting of two dates which indicate the start | ||||
|      * and end date for each reminder that this piggy bank will have, if the piggy bank has | ||||
|      * any reminders. For example: | ||||
|      * | ||||
|      * [12 mar - 15 mar] | ||||
|      * [15 mar - 18 mar] | ||||
|      * | ||||
|      * etcetera. | ||||
|      * | ||||
|      * Array is filled with tiny arrays with Carbon objects in them. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $date ; | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getReminderRanges(PiggyBank $piggyBank, Carbon $date = null) | ||||
|     { | ||||
|         $ranges = []; | ||||
|         if (is_null($date)) { | ||||
|             $date = new Carbon; | ||||
|         } | ||||
|  | ||||
|         if ($piggyBank->remind_me === false) { | ||||
|             return $ranges; | ||||
|         } | ||||
|  | ||||
|         if (!is_null($piggyBank->targetdate)) { | ||||
|             // count back until now. | ||||
|             //                    echo 'Count back!<br>'; | ||||
|             $start = $piggyBank->targetdate; | ||||
|             $end   = $piggyBank->startdate; | ||||
|  | ||||
|             while ($start > $end) { | ||||
|                 $currentEnd   = clone $start; | ||||
|                 $start        = Navigation::subtractPeriod($start, $piggyBank->reminder, 1); | ||||
|                 $currentStart = clone $start; | ||||
|                 $ranges[]     = ['start' => clone $currentStart, 'end' => clone $currentEnd]; | ||||
|             } | ||||
|         } else { | ||||
|             $start = clone $piggyBank->startdate; | ||||
|             while ($start < $date) { | ||||
|                 $currentStart = clone $start; | ||||
|                 $start        = Navigation::addPeriod($start, $piggyBank->reminder, 0); | ||||
|                 $currentEnd   = clone $start; | ||||
|                 $ranges[]     = ['start' => clone $currentStart, 'end' => clone $currentEnd]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $ranges; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Takes a reminder, finds the piggy bank and tells you what to do now. | ||||
|      * Aka how much money to put in. | ||||
|      * | ||||
|      * | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getReminderText(Reminder $reminder) | ||||
|     { | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         $piggyBank = $reminder->remindersable; | ||||
|  | ||||
|         if (is_null($piggyBank)) { | ||||
|             return 'Piggy bank no longer exists.'; | ||||
|         } | ||||
|  | ||||
|         if (is_null($piggyBank->targetdate)) { | ||||
|             return 'Add money to this piggy bank to reach your target of ' . Amount::format($piggyBank->targetamount); | ||||
|         } | ||||
|  | ||||
|         return 'Add ' . Amount::format($reminder->metadata->perReminder) . ' to fill this piggy bank on ' . $piggyBank->targetdate->format('jS F Y'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										51
									
								
								app/Helpers/Reminders/ReminderHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/Helpers/Reminders/ReminderHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Reminders; | ||||
|  | ||||
| use FireflyIII\Models\Reminder; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use Carbon\Carbon; | ||||
|  | ||||
| /** | ||||
|  * Interface ReminderHelperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Reminders | ||||
|  */ | ||||
| interface ReminderHelperInterface { | ||||
|     /** | ||||
|      * Takes a reminder, finds the piggy bank and tells you what to do now. | ||||
|      * Aka how much money to put in. | ||||
|      * | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getReminderText(Reminder $reminder); | ||||
|  | ||||
|     /** | ||||
|      * This routine will return an array consisting of two dates which indicate the start | ||||
|      * and end date for each reminder that this piggy bank will have, if the piggy bank has | ||||
|      * any reminders. For example: | ||||
|      * | ||||
|      * [12 mar - 15 mar] | ||||
|      * [15 mar - 18 mar] | ||||
|      * | ||||
|      * etcetera. | ||||
|      * | ||||
|      * Array is filled with tiny arrays with Carbon objects in them. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getReminderRanges(PiggyBank $piggyBank); | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $start | ||||
|      * @param Carbon    $end | ||||
|      * | ||||
|      * @return Reminder | ||||
|      */ | ||||
|     public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end); | ||||
| } | ||||
							
								
								
									
										171
									
								
								app/Helpers/Report/ReportHelper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								app/Helpers/Report/ReportHelper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class ReportHelper | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Report | ||||
|  */ | ||||
| class ReportHelper implements ReportHelperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This methods fails to take in account transfers FROM shared accounts. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15) | ||||
|     { | ||||
|         $result  = $this->_queries->journalsByExpenseAccount($start, $end); | ||||
|         $array   = $this->_helper->makeArray($result); | ||||
|         $limited = $this->_helper->limitArray($array, $limit); | ||||
|  | ||||
|         return $limited; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method gets some kind of list for a monthly overview. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetsForMonth(Carbon $date) | ||||
|     { | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|         // all budgets | ||||
|         $set = Auth::user()->budgets() | ||||
|                    ->leftJoin( | ||||
|                        'budget_limits', function (JoinClause $join) use ($date) { | ||||
|                        $join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d')); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->get(['budgets.*', 'budget_limits.amount as amount']); | ||||
|  | ||||
|  | ||||
|         $budgets               = $this->_helper->makeArray($set); | ||||
|         $amountSet             = $this->_queries->journalsByBudget($start, $end); | ||||
|         $amounts               = $this->_helper->makeArray($amountSet); | ||||
|         $combined              = $this->_helper->mergeArrays($budgets, $amounts); | ||||
|         $combined[0]['spent']  = isset($combined[0]['spent']) ? $combined[0]['spent'] : 0.0; | ||||
|         $combined[0]['amount'] = isset($combined[0]['amount']) ? $combined[0]['amount'] : 0.0; | ||||
|         $combined[0]['name']   = 'No budget'; | ||||
|  | ||||
|         // find transactions to shared expense accounts, which are without a budget by default: | ||||
|         $transfers = $this->_queries->sharedExpenses($start, $end); | ||||
|         foreach ($transfers as $transfer) { | ||||
|             $combined[0]['spent'] += floatval($transfer->amount) * -1; | ||||
|         } | ||||
|  | ||||
|         return $combined; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date) | ||||
|     { | ||||
|         $start  = clone $date; | ||||
|         $end    = Carbon::now(); | ||||
|         $months = []; | ||||
|         while ($start <= $end) { | ||||
|             $year            = $start->format('Y'); | ||||
|             $months[$year][] = [ | ||||
|                 'formatted' => $start->format('F Y'), | ||||
|                 'month'     => intval($start->format('m')), | ||||
|                 'year'      => intval($start->format('Y')), | ||||
|             ]; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         return $months; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfYears(Carbon $date) | ||||
|     { | ||||
|         $start = clone $date; | ||||
|         $end   = Carbon::now(); | ||||
|         $years = []; | ||||
|         while ($start <= $end) { | ||||
|             $years[] = $start->format('Y'); | ||||
|             $start->addYear(); | ||||
|         } | ||||
|  | ||||
|         return $years; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearBalanceReport(Carbon $date, $showSharedReports = false) | ||||
|     { | ||||
|         $start          = clone $date; | ||||
|         $end            = clone $date; | ||||
|         $sharedAccounts = []; | ||||
|         if ($showSharedReports === false) { | ||||
|             $sharedCollection = \Auth::user()->accounts() | ||||
|                                      ->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id') | ||||
|                                      ->where('account_meta.name', '=', 'accountRole') | ||||
|                                      ->where('account_meta.data', '=', json_encode('sharedAsset')) | ||||
|                                      ->get(['accounts.id']); | ||||
|  | ||||
|             foreach ($sharedCollection as $account) { | ||||
|                 $sharedAccounts[] = $account->id; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']) | ||||
|                         ->filter( | ||||
|                             function (Account $account) use ($sharedAccounts) { | ||||
|                                 if (!in_array($account->id, $sharedAccounts)) { | ||||
|                                     return $account; | ||||
|                                 } | ||||
|  | ||||
|                                 return null; | ||||
|                             } | ||||
|                         ); | ||||
|         $report   = []; | ||||
|         $start->startOfYear()->subDay(); | ||||
|         $end->endOfYear(); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $startBalance = Steam::balance($account, $start); | ||||
|             $endBalance   = Steam::balance($account, $end); | ||||
|             $report[]     = [ | ||||
|                 'start'   => $startBalance, | ||||
|                 'end'     => $endBalance, | ||||
|                 'hide'    => ($startBalance == 0 && $endBalance == 0), | ||||
|                 'account' => $account, | ||||
|                 'shared'  => $account->accountRole == 'sharedAsset' | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $report; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								app/Helpers/Report/ReportHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/Helpers/Report/ReportHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ReportHelperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Report | ||||
|  */ | ||||
| interface ReportHelperInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * This methods fails to take in account transfers FROM shared accounts. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15); | ||||
|  | ||||
|     /** | ||||
|      * This method gets some kind of list for a monthly overview. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetsForMonth(Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfYears(Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearBalanceReport(Carbon $date, $showSharedReports = false); | ||||
| } | ||||
							
								
								
									
										607
									
								
								app/Helpers/Report/ReportQuery.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								app/Helpers/Report/ReportQuery.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,607 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class ReportQuery | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Report | ||||
|  */ | ||||
| class ReportQuery implements ReportQueryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This query retrieves a list of accounts that are active and not shared. | ||||
|      * | ||||
|      * @param bool $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function accountList($showSharedReports = false) | ||||
|     { | ||||
|         $query = Auth::user()->accounts(); | ||||
|         if ($showSharedReports === false) { | ||||
|  | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole"); | ||||
|             } | ||||
|             )->where( | ||||
|                 function (Builder $query) { | ||||
|                     $query->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|                     $query->orWhereNull('account_meta.data'); | ||||
|                 } | ||||
|             ); | ||||
|  | ||||
|         } | ||||
|         $query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') | ||||
|               ->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account']) | ||||
|               ->where('active', 1) | ||||
|               ->orderBy('accounts.name', 'ASC'); | ||||
|  | ||||
|         return $query->get(['accounts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method will get a list of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|  | ||||
|         $set = TransactionJournal:: | ||||
|         leftJoin('transaction_group_transaction_journal', 'transaction_group_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transaction_group_transaction_journal as otherFromGroup', function (JoinClause $join) { | ||||
|                                      $join->on('otherFromGroup.transaction_group_id', '=', 'transaction_group_transaction_journal.transaction_group_id') | ||||
|                                           ->on('otherFromGroup.transaction_journal_id', '!=', 'transaction_journals.id'); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('transaction_journals as otherJournals', 'otherJournals.id', '=', 'otherFromGroup.transaction_journal_id') | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'otherJournals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'otherJournals.id') | ||||
|                                  ->before($end)->after($start) | ||||
|                                  ->where('transaction_types.type', 'Withdrawal') | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->whereNull('budget_transaction_journal.budget_id')->whereNull('transaction_journals.deleted_at') | ||||
|                                  ->whereNull('otherJournals.deleted_at') | ||||
|                                  ->where('transactions.account_id', $account->id) | ||||
|                                 ->orderBy('transaction_journals.date', 'DESC') | ||||
|                                 ->orderBy('transaction_journals.order','ASC') | ||||
|                                 ->orderBy('transaction_journals.id','DESC') | ||||
|                                  ->whereNotNull('transaction_group_transaction_journal.transaction_group_id') | ||||
|                                  ->get( | ||||
|                                      [ | ||||
|                                          'transaction_journals.*', | ||||
|                                          'transactions.amount' | ||||
|                                      ] | ||||
|                                  ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method will get the sum of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set = $this->balancedTransactionsList($account, $start, $end); | ||||
|         $sum = 0; | ||||
|         foreach ($set as $entry) { | ||||
|             $sum += floatval($entry->amount); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a users accounts combined with various meta-data related to the start and end date. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC') | ||||
|                      ->accountTypeIn(['Default account', 'Asset account', 'Cash account']); | ||||
|         if ($showSharedReports === false) { | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             ) | ||||
|                   ->orderBy('accounts.name', 'ASC') | ||||
|                   ->where( | ||||
|                       function (Builder $query) use ($showSharedReports) { | ||||
|  | ||||
|                           $query->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|                           $query->orWhereNull('account_meta.data'); | ||||
|  | ||||
|                       } | ||||
|                   ); | ||||
|         } | ||||
|         $set = $query->get(['accounts.*']); | ||||
|         $set->each( | ||||
|             function (Account $account) use ($start, $end) { | ||||
|                 /** @noinspection PhpParamsInspection */ | ||||
|                 $account->startBalance = Steam::balance($account, $start); | ||||
|                 $account->endBalance   = Steam::balance($account, $end); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Grabs a summary of all expenses grouped by budget, related to the account. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getBudgetSummary(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set = TransactionJournal:: | ||||
|         leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                  ->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id') | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->before($end) | ||||
|                                  ->after($start) | ||||
|                                  ->where('accounts.id', $account->id) | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->where('transaction_types.type', 'Withdrawal') | ||||
|                                  ->groupBy('budgets.id') | ||||
|                                  ->orderBy('budgets.name', 'ASC') | ||||
|                                  ->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `amount`')]); | ||||
|  | ||||
|         return $set; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a list of transaction journals that have no budget, filtered for the specified account | ||||
|      * and the specified date range. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set = TransactionJournal:: | ||||
|         leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                  ->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id') | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->before($end) | ||||
|                                  ->after($start) | ||||
|                                  ->where('accounts.id', $account->id) | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->where('transaction_types.type', 'Withdrawal') | ||||
|                                  ->whereNull('budgets.id') | ||||
|                                  ->orderBy('transaction_journals.date', 'ASC') | ||||
|                                  ->get(['budgets.name', 'transactions.amount', 'transaction_journals.*']); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns all "income" journals in a certain period, which are both transfers from a shared account | ||||
|      * and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = TransactionJournal:: | ||||
|         leftJoin( | ||||
|             'transactions as t_from', function (JoinClause $join) { | ||||
|             $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); | ||||
|         } | ||||
|         ) | ||||
|                                    ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_from', function (JoinClause $join) { | ||||
|                                        $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin( | ||||
|                                        'transactions as t_to', function (JoinClause $join) { | ||||
|                                        $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_to', function (JoinClause $join) { | ||||
|                                        $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); | ||||
|         if ($showSharedReports === false) { | ||||
|             // only get deposits not to a shared account | ||||
|             // and transfers to a shared account. | ||||
|             $query->where( | ||||
|                 function ($query) { | ||||
|                     $query->where( | ||||
|                         function ($q) { | ||||
|                             $q->where('transaction_types.type', 'Deposit'); | ||||
|                             $q->where('acm_to.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function ($q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_from.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             // any deposit is fine. | ||||
|             $query->where('transaction_types.type', 'Deposit'); | ||||
|         } | ||||
|         $query->before($end)->after($start) | ||||
|               ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|               ->groupBy('t_from.account_id')->orderBy('transaction_journals.date'); | ||||
|  | ||||
|         return $query->get( | ||||
|             ['transaction_journals.id', | ||||
|              'transaction_journals.description', | ||||
|              'transaction_journals.encrypted', | ||||
|              'transaction_types.type', | ||||
|              DB::Raw('SUM(`t_to`.`amount`) as `amount`'), | ||||
|              'transaction_journals.date', | ||||
|              't_from.account_id as account_id', | ||||
|              'ac_from.name as name'] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expenses grouped by the budget they were filed under. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = Auth::user()->transactionjournals() | ||||
|                      ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                      ->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id') | ||||
|                      ->leftJoin( | ||||
|                          'transactions', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id'); | ||||
|         if ($showSharedReports === false) { | ||||
|  | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             )->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|         } | ||||
|         $query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') | ||||
|               ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|               ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|               ->where('transaction_types.type', 'Withdrawal') | ||||
|               ->groupBy('budgets.id') | ||||
|               ->orderBy('budgets.name', 'ASC'); | ||||
|  | ||||
|         return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of categories and the expenses therein, grouped by the relevant category. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = Auth::user()->transactionjournals() | ||||
|                      ->leftJoin( | ||||
|                          'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                      ) | ||||
|                      ->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                      ->leftJoin( | ||||
|                          'transactions', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id'); | ||||
|         if ($showSharedReports === false) { | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             )->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|         } | ||||
|         $query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') | ||||
|               ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|               ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|               ->where('transaction_types.type', 'Withdrawal') | ||||
|               ->groupBy('categories.id') | ||||
|               ->orderBy('amount'); | ||||
|  | ||||
|         return $query->get(['categories.id', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expense accounts and the expenses therein, grouped by that expense account. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * So now it will include them! | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = TransactionJournal::leftJoin( | ||||
|             'transactions as t_from', function (JoinClause $join) { | ||||
|             $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); | ||||
|         } | ||||
|         )->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_from', function (JoinClause $join) { | ||||
|                                        $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin( | ||||
|                                        'transactions as t_to', function (JoinClause $join) { | ||||
|                                        $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_to', function (JoinClause $join) { | ||||
|                                        $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); | ||||
|  | ||||
|         if ($showSharedReports === false) { | ||||
|             // get all withdrawals not from a shared accounts | ||||
|             // and all transfers to a shared account | ||||
|             $query->where( | ||||
|                 function ($query) { | ||||
|                     $query->where( | ||||
|                         function ($q) { | ||||
|                             $q->where('transaction_types.type', 'Withdrawal'); | ||||
|                             $q->where('acm_from.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function ($q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_to.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             // any withdrawal goes: | ||||
|             $query->where('transaction_types.type', 'Withdrawal'); | ||||
|         } | ||||
|         $query->before($end) | ||||
|               ->after($start) | ||||
|               ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|               ->groupBy('t_to.account_id') | ||||
|               ->orderBy('amount', 'DESC'); | ||||
|  | ||||
|         return $query->get(['t_to.account_id as id', 'ac_to.name as name', DB::Raw('SUM(t_to.amount) as `amount`')]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns all deposits into asset accounts, grouped by the revenue account, | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = TransactionJournal:: | ||||
|         leftJoin( | ||||
|             'transactions as t_from', function (JoinClause $join) { | ||||
|             $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); | ||||
|         } | ||||
|         ) | ||||
|                                    ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_from', function (JoinClause $join) { | ||||
|                                        $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin( | ||||
|                                        'transactions as t_to', function (JoinClause $join) { | ||||
|                                        $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_to', function (JoinClause $join) { | ||||
|                                        $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); | ||||
|         if ($showSharedReports === false) { | ||||
|  | ||||
|             // show queries where transfer type is deposit, and its not to a shared account | ||||
|             // or where its a transfer and its from a shared account (both count as incomes) | ||||
|             $query->where( | ||||
|                 function ($query) { | ||||
|                     $query->where( | ||||
|                         function ($q) { | ||||
|                             $q->where('transaction_types.type', 'Deposit'); | ||||
|                             $q->where('acm_to.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function ($q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_from.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             // any deposit goes: | ||||
|             $query->where('transaction_types.type', 'Deposit'); | ||||
|         } | ||||
|         $query->before($end)->after($start) | ||||
|               ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|               ->groupBy('t_from.account_id')->orderBy('amount'); | ||||
|  | ||||
|         return $query->get(['t_from.account_id as account_id', 'ac_from.name as name', DB::Raw('SUM(t_from.amount) as `amount`')]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * With an equally misleading name, this query returns are transfers to shared accounts. These are considered | ||||
|      * expenses. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpenses(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return TransactionJournal:: | ||||
|         leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where( | ||||
|                                          'transactions.amount', '>', 0 | ||||
|                                      ); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'account_meta', function (JoinClause $join) { | ||||
|                                      $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->where('account_meta.data', '"sharedAsset"') | ||||
|                                  ->after($start) | ||||
|                                  ->before($end) | ||||
|                                  ->where('transaction_types.type', 'Transfer') | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->get( | ||||
|                                      ['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name', | ||||
|                                       'transactions.amount'] | ||||
|                                  ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * With a slightly misleading name, this query returns all transfers to shared accounts | ||||
|      * which are technically expenses, since it won't be just your money that gets spend. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpensesByCategory(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return TransactionJournal:: | ||||
|         leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where( | ||||
|                                          'transactions.amount', '>', 0 | ||||
|                                      ); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'account_meta', function (JoinClause $join) { | ||||
|                                      $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin( | ||||
|                                      'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                                  ) | ||||
|                                  ->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                                  ->where('account_meta.data', '"sharedAsset"') | ||||
|                                  ->after($start) | ||||
|                                  ->before($end) | ||||
|                                  ->where('transaction_types.type', 'Transfer') | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->groupBy('categories.name') | ||||
|                                  ->get( | ||||
|                                      [ | ||||
|                                          'categories.id', | ||||
|                                          'categories.name as name', | ||||
|                                          DB::Raw('SUM(`transactions`.`amount`) * -1 AS `amount`') | ||||
|                                      ] | ||||
|                                  ); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										166
									
								
								app/Helpers/Report/ReportQueryInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								app/Helpers/Report/ReportQueryInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ReportQueryInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Report | ||||
|  */ | ||||
| interface ReportQueryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This query retrieves a list of accounts that are active and not shared. | ||||
|      * | ||||
|      * @param bool $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function accountList($showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * This method will get a list of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * This method will get the sum of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Get a users accounts combined with various meta-data related to the start and end date. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Grabs a summary of all expenses grouped by budget, related to the account. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getBudgetSummary(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Get a list of transaction journals that have no budget, filtered for the specified account | ||||
|      * and the specified date range. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * This method returns all "income" journals in a certain period, which are both transfers from a shared account | ||||
|      * and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expenses grouped by the budget they were filed under. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of categories and the expenses therein, grouped by the relevant category. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expense accounts and the expenses therein, grouped by that expense account. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * So now it will include them! | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * This method returns all deposits into asset accounts, grouped by the revenue account, | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * With an equally misleading name, this query returns are transfers to shared accounts. These are considered | ||||
|      * expenses. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpenses(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * With a slightly misleading name, this query returns all transfers to shared accounts | ||||
|      * which are technically expenses, since it won't be just your money that gets spend. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpensesByCategory(Carbon $start, Carbon $end); | ||||
| } | ||||
							
								
								
									
										238
									
								
								app/Http/Controllers/AccountController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								app/Http/Controllers/AccountController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\AccountFormRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use Steam; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('mainTitleIcon', 'fa-credit-card'); | ||||
|         View::share('title', 'Accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $what | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function create($what = 'asset') | ||||
|     { | ||||
|         $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $subTitle     = 'Create a new ' . e($what) . ' account'; | ||||
|  | ||||
|         return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(Account $account) | ||||
|     { | ||||
|         $subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|  | ||||
|         return view('accounts.delete', compact('account', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(Account $account, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|         $type     = $account->accountType->type; | ||||
|         $typeName = Config::get('firefly.shortNamesByFullName.' . $type); | ||||
|         $name     = $account->name; | ||||
|  | ||||
|         $repository->destroy($account); | ||||
|  | ||||
|         Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.'); | ||||
|  | ||||
|         return Redirect::route('accounts.index', $typeName); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account                    $account | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function edit(Account $account, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $what           = Config::get('firefly.shortNamesByFullName')[$account->accountType->type]; | ||||
|         $subTitle       = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|         $subTitleIcon   = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $openingBalance = $repository->openingBalanceTransaction($account); | ||||
|  | ||||
|         // pre fill some useful values. | ||||
|  | ||||
|         // the opening balance is tricky: | ||||
|         $openingBalanceAmount = null; | ||||
|         if ($openingBalance) { | ||||
|             $transaction          = $openingBalance->transactions()->where('account_id', $account->id)->first(); | ||||
|             $openingBalanceAmount = $transaction->amount; | ||||
|         } | ||||
|  | ||||
|         $preFilled = [ | ||||
|             'accountRole'        => $account->getMeta('accountRole'), | ||||
|             'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null, | ||||
|             'openingBalance'     => $openingBalanceAmount | ||||
|         ]; | ||||
|         Session::flash('preFilled', $preFilled); | ||||
|  | ||||
|         return view('accounts.edit', compact('account', 'subTitle', 'subTitleIcon', 'openingBalance', 'what')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $what | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function index($what = 'default') | ||||
|     { | ||||
|         $subTitle     = Config::get('firefly.subTitlesByIdentifier.' . $what); | ||||
|         $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $types        = Config::get('firefly.accountTypesByIdentifier.' . $what); | ||||
|         $size         = 50; | ||||
|         $page         = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); | ||||
|         $offset       = ($page - 1) * $size; | ||||
|  | ||||
|  | ||||
|         // move to repository: | ||||
|         $set   = Auth::user()->accounts()->with( | ||||
|             ['accountmeta' => function ($query) { | ||||
|                 $query->where('name', 'accountRole'); | ||||
|             }] | ||||
|         )->accountTypeIn($types)->take($size)->offset($offset)->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|         $total = Auth::user()->accounts()->accountTypeIn($types)->count(); | ||||
|  | ||||
|         // last activity: | ||||
|         $start = clone Session::get('start'); | ||||
|         $start->subDay(); | ||||
|         $set->each( | ||||
|             function (Account $account) use ($start) { | ||||
|                 $lastTransaction = $account->transactions()->leftJoin( | ||||
|                     'transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                 )->orderBy('transaction_journals.date', 'DESC')->first(['transactions.*', 'transaction_journals.date']); | ||||
|                 if ($lastTransaction) { | ||||
|                     $account->lastActivityDate = $lastTransaction->transactionjournal->date; | ||||
|                 } else { | ||||
|                     $account->lastActivityDate = null; | ||||
|                 } | ||||
|                 $account->startBalance = Steam::balance($account, $start); | ||||
|                 $account->endBalance   = Steam::balance($account, clone Session::get('end')); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $accounts = new LengthAwarePaginator($set, $total, $size, $page); | ||||
|         $accounts->setPath(route('accounts.index', $what)); | ||||
|  | ||||
|  | ||||
|         return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account                    $account | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function show(Account $account, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $page         = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); | ||||
|         $subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type); | ||||
|         $what         = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $journals     = $repository->getJournals($account, $page); | ||||
|         $subTitle     = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|         $journals->setPath('accounts/show/'.$account->id); | ||||
|         return view('accounts.show', compact('account', 'what', 'subTitleIcon', 'journals', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountFormRequest         $request | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(AccountFormRequest $request, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $accountData = [ | ||||
|             'name'                   => $request->input('name'), | ||||
|             'accountType'            => $request->input('what'), | ||||
|             'active'                 => true, | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'accountRole'            => $request->input('accountRole'), | ||||
|             'openingBalance'         => floatval($request->input('openingBalance')), | ||||
|             'openingBalanceDate'     => new Carbon($request->input('openingBalanceDate')), | ||||
|             'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|  | ||||
|         ]; | ||||
|         $account     = $repository->store($accountData); | ||||
|  | ||||
|         Session::flash('success', 'New account "' . $account->name . '" stored!'); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('accounts.create', $request->input('what'))->withInput(); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('accounts.index', $request->input('what')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account                    $account | ||||
|      * @param AccountFormRequest         $request | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(Account $account, AccountFormRequest $request, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $what        = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $accountData = [ | ||||
|             'name'                   => $request->input('name'), | ||||
|             'active'                 => $request->input('active'), | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'accountRole'            => $request->input('accountRole'), | ||||
|             'openingBalance'         => floatval($request->input('openingBalance')), | ||||
|             'openingBalanceDate'     => new Carbon($request->input('openingBalanceDate')), | ||||
|             'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|         ]; | ||||
|  | ||||
|         $repository->update($account, $accountData); | ||||
|  | ||||
|         Session::flash('success', 'Account "' . $account->name . '" updated.'); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('accounts.edit', $account->id); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('accounts.index', $what); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										88
									
								
								app/Http/Controllers/Auth/AuthController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								app/Http/Controllers/Auth/AuthController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Contracts\Auth\Registrar; | ||||
| use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; | ||||
| use Illuminate\Http\Request; | ||||
| use Mail; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class AuthController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Auth | ||||
|  */ | ||||
| class AuthController extends Controller | ||||
| { | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Registration & Login Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller handles the registration of new users, as well as the | ||||
|     | authentication of existing users. By default, this controller uses | ||||
|     | a simple trait to add these behaviors. Why don't you explore it? | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     use AuthenticatesAndRegistersUsers; | ||||
|  | ||||
|     public $redirectTo = '/'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new authentication controller instance. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\Auth\Guard     $auth | ||||
|      * @param  \Illuminate\Contracts\Auth\Registrar $registrar | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth, Registrar $registrar) | ||||
|     { | ||||
|         $this->auth      = $auth; | ||||
|         $this->registrar = $registrar; | ||||
|  | ||||
|         $this->middleware('guest', ['except' => 'getLogout']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle a registration request for the application. | ||||
|      * | ||||
|      * @param  Request $request | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function postRegister(Request $request) | ||||
|     { | ||||
|         $validator = $this->registrar->validator($request->all()); | ||||
|  | ||||
|         if ($validator->fails()) { | ||||
|             $this->throwValidationException( | ||||
|                 $request, $validator | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $data  =$request->all(); | ||||
|         $data['password'] = bcrypt($data['password']); | ||||
|  | ||||
|         $this->auth->login($this->registrar->create($data)); | ||||
|  | ||||
|         // get the email address | ||||
|         $email = $this->auth->user()->email; | ||||
|  | ||||
|         // send email. | ||||
|         Mail::send( | ||||
|             'emails.registered', [], function ($message) use ($email) { | ||||
|             $message->to($email, $email)->subject('Welcome to Firefly III!'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // set flash message | ||||
|         Session::flash('success', 'You have registered successfully!'); | ||||
|  | ||||
|  | ||||
|         return redirect($this->redirectPath()); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										48
									
								
								app/Http/Controllers/Auth/PasswordController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/Http/Controllers/Auth/PasswordController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Contracts\Auth\PasswordBroker; | ||||
| use Illuminate\Foundation\Auth\ResetsPasswords; | ||||
|  | ||||
| /** | ||||
|  * Class PasswordController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Auth | ||||
|  */ | ||||
| class PasswordController extends Controller | ||||
| { | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Password Reset Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller is responsible for handling password reset requests | ||||
|     | and uses a simple trait to include this behavior. You're free to | ||||
|     | explore this trait and override any methods you wish to tweak. | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     use ResetsPasswords; | ||||
|  | ||||
|  | ||||
|     protected $redirectPath = '/'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new password controller instance. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\Auth\Guard          $auth | ||||
|      * @param  \Illuminate\Contracts\Auth\PasswordBroker $passwords | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth, PasswordBroker $passwords) | ||||
|     { | ||||
|         $this->auth      = $auth; | ||||
|         $this->passwords = $passwords; | ||||
|  | ||||
|  | ||||
|         $this->middleware('guest'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										220
									
								
								app/Http/Controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								app/Http/Controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,220 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\BillFormRequest; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use URL; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class BillController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|  | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('title', 'Bills'); | ||||
|         View::share('mainTitleIcon', 'fa-calendar-o'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return view('bills.create')->with('periods', $periods)->with('subTitle', 'Create new'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(Bill $bill) | ||||
|     { | ||||
|         return view('bills.delete')->with('bill', $bill)->with('subTitle', 'Delete "' . e($bill->name) . '"'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(Bill $bill) | ||||
|     { | ||||
|         $bill->delete(); | ||||
|         Session::flash('success', 'The bill was deleted.'); | ||||
|  | ||||
|         return Redirect::route('bills.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(Bill $bill) | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return view('bills.edit')->with('periods', $periods)->with('bill', $bill)->with('subTitle', 'Edit "' . e($bill->name) . '"'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $bills = Auth::user()->bills()->orderBy('name', 'ASC')->get(); | ||||
|         $bills->each( | ||||
|             function (Bill $bill) use ($repository) { | ||||
|                 $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); | ||||
|                 $last                    = $bill->transactionjournals()->orderBy('date', 'DESC')->first(); | ||||
|                 $bill->lastFoundMatch    = null; | ||||
|                 if ($last) { | ||||
|                     $bill->lastFoundMatch = $last->date; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return view('bills.index', compact('bills')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function rescan(Bill $bill, BillRepositoryInterface $repository) | ||||
|     { | ||||
|         if (intval($bill->active) == 0) { | ||||
|             Session::flash('warning', 'Inactive bills cannot be scanned.'); | ||||
|  | ||||
|             return Redirect::intended('/'); | ||||
|         } | ||||
|  | ||||
|         $set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get( | ||||
|             ['transaction_journal_id'] | ||||
|         ); | ||||
|         $ids = []; | ||||
|  | ||||
|         /** @var Transaction $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $ids[] = intval($entry->transaction_journal_id); | ||||
|         } | ||||
|         if (count($ids) > 0) { | ||||
|             $journals = Auth::user()->transactionjournals()->whereIn('id', $ids)->get(); | ||||
|             /** @var TransactionJournal $journal */ | ||||
|             foreach ($journals as $journal) { | ||||
|                 $repository->scan($bill, $journal); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'Rescanned everything.'); | ||||
|  | ||||
|         return Redirect::to(URL::previous()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function show(Bill $bill, BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $journals                = $bill->transactionjournals()->withRelevantData() | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.order','ASC') | ||||
|             ->orderBy('transaction_journals.id','DESC') | ||||
|  | ||||
|             ->get(); | ||||
|         $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); | ||||
|         $hideBill                = true; | ||||
|  | ||||
|  | ||||
|         return view('bills.show', compact('journals', 'hideBill', 'bill'))->with('subTitle', e($bill->name)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function store(BillFormRequest $request, BillRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|         var_dump($request->all()); | ||||
|  | ||||
|         $billData = [ | ||||
|             'name'               => $request->get('name'), | ||||
|             'match'              => $request->get('match'), | ||||
|             'amount_min'         => floatval($request->get('amount_min')), | ||||
|             'amount_currency_id' => floatval($request->get('amount_currency_id')), | ||||
|             'amount_max'         => floatval($request->get('amount_max')), | ||||
|             'date'               => new Carbon($request->get('date')), | ||||
|             'user'               => Auth::user()->id, | ||||
|             'repeat_freq'        => $request->get('repeat_freq'), | ||||
|             'skip'               => intval($request->get('skip')), | ||||
|             'automatch'          => intval($request->get('automatch')) === 1, | ||||
|             'active'             => intval($request->get('active')) === 1, | ||||
|         ]; | ||||
|  | ||||
|         $bill = $repository->store($billData); | ||||
|         Session::flash('success', 'Bill "' . e($bill->name) . '" stored.'); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('bills.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('bills.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function update(Bill $bill, BillFormRequest $request, BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $billData = [ | ||||
|             'name'               => $request->get('name'), | ||||
|             'match'              => $request->get('match'), | ||||
|             'amount_min'         => floatval($request->get('amount_min')), | ||||
|             'amount_currency_id' => floatval($request->get('amount_currency_id')), | ||||
|             'amount_max'         => floatval($request->get('amount_max')), | ||||
|             'date'               => new Carbon($request->get('date')), | ||||
|             'user'               => Auth::user()->id, | ||||
|             'repeat_freq'        => $request->get('repeat_freq'), | ||||
|             'skip'               => intval($request->get('skip')), | ||||
|             'automatch'          => intval($request->get('automatch')) === 1, | ||||
|             'active'             => intval($request->get('active')) === 1, | ||||
|         ]; | ||||
|  | ||||
|         $bill = $repository->update($bill, $billData); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('bills.edit', $bill->id); | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'Bill "' . e($bill->name) . '" updated.'); | ||||
|  | ||||
|         return Redirect::route('bills.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										234
									
								
								app/Http/Controllers/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								app/Http/Controllers/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\BudgetFormRequest; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Redirect; | ||||
| use Response; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|  | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('title', 'Budgets'); | ||||
|         View::share('mainTitleIcon', 'fa-tasks'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function amount(Budget $budget, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $amount          = intval(Input::get('amount')); | ||||
|         $date            = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $limitRepetition = $repository->updateLimitAmount($budget, $date, $amount); | ||||
|  | ||||
|         return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         return view('budgets.create')->with('subTitle', 'Create a new budget'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(Budget $budget) | ||||
|     { | ||||
|         $subTitle = 'Delete budget' . e($budget->name) . '"'; | ||||
|  | ||||
|         return view('budgets.delete', compact('budget', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(Budget $budget, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|         $name = $budget->name; | ||||
|         $repository->destroy($budget); | ||||
|  | ||||
|         Session::flash('success', 'The  budget "' . e($name) . '" was deleted.'); | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(Budget $budget) | ||||
|     { | ||||
|         $subTitle = 'Edit budget "' . e($budget->name) . '"'; | ||||
|  | ||||
|         return view('budgets.edit', compact('budget', 'subTitle')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function index(BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $budgets = Auth::user()->budgets()->get(); | ||||
|  | ||||
|         // loop the budgets: | ||||
|         $budgets->each( | ||||
|             function (Budget $budget) use ($repository) { | ||||
|                 $date               = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|                 $budget->spent      = $repository->spentInMonth($budget, $date); | ||||
|                 $budget->currentRep = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $date          = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         $spent         = $budgets->sum('spent'); | ||||
|         $amount        = Preferences::get('budgetIncomeTotal' . $date, 1000)->data; | ||||
|         $overspent     = $spent > $amount; | ||||
|         $spentPCT      = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100); | ||||
|         $budgetMax     = Preferences::get('budgetMaximum', 1000); | ||||
|         $budgetMaximum = $budgetMax->data; | ||||
|  | ||||
|         return view('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function noBudget() | ||||
|     { | ||||
|         $start    = \Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = \Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $list     = Auth::user() | ||||
|                         ->transactionjournals() | ||||
|                         ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                         ->whereNull('budget_transaction_journal.id') | ||||
|                         ->before($end) | ||||
|                         ->after($start) | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.order','ASC') | ||||
|             ->orderBy('transaction_journals.id','DESC') | ||||
|                         ->get(['transaction_journals.*']); | ||||
|         $subTitle = 'Transactions without a budget in ' . $start->format('F Y'); | ||||
|  | ||||
|         return view('budgets.noBudget', compact('list', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function postUpdateIncome() | ||||
|     { | ||||
|  | ||||
|         $date = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         Preferences::set('budgetIncomeTotal' . $date, intval(Input::get('amount'))); | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetFormRequest         $request | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $budgetData = [ | ||||
|             'name' => $request->input('name'), | ||||
|             'user' => Auth::user()->id, | ||||
|         ]; | ||||
|         $budget     = $repository->store($budgetData); | ||||
|  | ||||
|         Session::flash('success', 'New budget "' . $budget->name . '" stored!'); | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Budget          $budget | ||||
|      * @param LimitRepetition $repetition | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) { | ||||
|             return view('error')->with('message', 'Invalid selection.'); | ||||
|         } | ||||
|  | ||||
|         $hideBudget = true; // used in transaction list. | ||||
|         $journals   = $repository->getJournals($budget, $repetition); | ||||
|         $limits     = !is_null($repetition->id) ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); | ||||
|         $subTitle   = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); | ||||
|  | ||||
|         return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget                    $budget | ||||
|      * @param BudgetFormRequest         $request | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(Budget $budget, BudgetFormRequest $request, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $budgetData = [ | ||||
|             'name' => $request->input('name'), | ||||
|         ]; | ||||
|  | ||||
|         $repository->update($budget, $budgetData); | ||||
|  | ||||
|         Session::flash('success', 'Budget "' . $budget->name . '" updated.'); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('budgets.edit', $budget->id); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function updateIncome() | ||||
|     { | ||||
|         $date         = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         $budgetAmount = Preferences::get('budgetIncomeTotal' . $date, 1000); | ||||
|  | ||||
|         return view('budgets.income')->with('amount', $budgetAmount); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										208
									
								
								app/Http/Controllers/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								app/Http/Controllers/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\CategoryFormRequest; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('title', 'Categories'); | ||||
|         View::share('mainTitleIcon', 'fa-bar-chart'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         return view('categories.create')->with('subTitle', 'Create a new category'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(Category $category) | ||||
|     { | ||||
|         $subTitle = 'Delete category' . e($category->name) . '"'; | ||||
|  | ||||
|         return view('categories.delete', compact('category', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(Category $category, CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|         $name = $category->name; | ||||
|         $repository->destroy($category); | ||||
|  | ||||
|         Session::flash('success', 'The  category "' . e($name) . '" was deleted.'); | ||||
|  | ||||
|         return Redirect::route('categories.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(Category $category) | ||||
|     { | ||||
|         $subTitle = 'Edit category "' . e($category->name) . '"'; | ||||
|  | ||||
|         return view('categories.edit', compact('category', 'subTitle')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $categories = Auth::user()->categories()->orderBy('name', 'ASC')->get(); | ||||
|  | ||||
|         $categories->each( | ||||
|             function (Category $category) { | ||||
|                 $latest = $category->transactionjournals() | ||||
|                     ->orderBy('transaction_journals.date', 'DESC') | ||||
|                     ->orderBy('transaction_journals.order','ASC') | ||||
|                     ->orderBy('transaction_journals.id','DESC') | ||||
|                     ->first(); | ||||
|                 if ($latest) { | ||||
|                     $category->lastActivity = $latest->date; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return view('categories.index', compact('categories')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function noCategory() | ||||
|     { | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $list  = Auth::user() | ||||
|                      ->transactionjournals() | ||||
|                      ->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                      ->whereNull('category_transaction_journal.id') | ||||
|                      ->before($end) | ||||
|                      ->after($start) | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.order','ASC') | ||||
|             ->orderBy('transaction_journals.id','DESC') | ||||
|                      ->get(['transaction_journals.*']); | ||||
|  | ||||
|         $subTitle = 'Transactions without a category between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y'); | ||||
|  | ||||
|         return view('categories.noCategory', compact('list', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function show(Category $category, CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|         $hideCategory = true; // used in list. | ||||
|         $page         = intval(Input::get('page')); | ||||
|         $offset       = $page > 0 ? $page * 50 : 0; | ||||
|         $set          = $category->transactionJournals()->withRelevantData()->take(50)->offset($offset) | ||||
|  | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.order','ASC') | ||||
|             ->orderBy('transaction_journals.id','DESC') | ||||
|  | ||||
|             ->get( | ||||
|             ['transaction_journals.*'] | ||||
|         ); | ||||
|         $count        = $category->transactionJournals()->count(); | ||||
|  | ||||
|         $journals = new LengthAwarePaginator($set, $count, 50, $page); | ||||
|  | ||||
|         return view('categories.show', compact('category', 'journals', 'hideCategory')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryFormRequest         $request | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|         $categoryData = [ | ||||
|             'name' => $request->input('name'), | ||||
|             'user' => Auth::user()->id, | ||||
|         ]; | ||||
|         $category     = $repository->store($categoryData); | ||||
|  | ||||
|         Session::flash('success', 'New category "' . $category->name . '" stored!'); | ||||
|          | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('categories.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('categories.create'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('categories.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category                    $category | ||||
|      * @param CategoryFormRequest         $request | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(Category $category, CategoryFormRequest $request, CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|         $categoryData = [ | ||||
|             'name' => $request->input('name'), | ||||
|         ]; | ||||
|  | ||||
|         $repository->update($category, $categoryData); | ||||
|  | ||||
|         Session::flash('success', 'Category "' . $category->name . '" updated.'); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('categories.edit', $category->id); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('categories.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										17
									
								
								app/Http/Controllers/Controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/Http/Controllers/Controller.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Foundation\Bus\DispatchesCommands; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
|  | ||||
| /** | ||||
|  * Class Controller | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| abstract class Controller extends BaseController | ||||
| { | ||||
|  | ||||
|     use DispatchesCommands, ValidatesRequests; | ||||
|  | ||||
| } | ||||
							
								
								
									
										183
									
								
								app/Http/Controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								app/Http/Controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Cache; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\CurrencyFormRequest; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class CurrencyController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|  | ||||
|         View::share('title', 'Currencies'); | ||||
|         View::share('mainTitleIcon', 'fa-usd'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $subTitleIcon = 'fa-plus'; | ||||
|         $subTitle     = 'Create a new currency'; | ||||
|  | ||||
|         return view('currency.create', compact('subTitleIcon', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function defaultCurrency(TransactionCurrency $currency) | ||||
|     { | ||||
|  | ||||
|         $currencyPreference       = Preferences::get('currencyPreference', 'EUR'); | ||||
|         $currencyPreference->data = $currency->code; | ||||
|         $currencyPreference->save(); | ||||
|  | ||||
|         Session::flash('success', $currency->name . ' is now the default currency.'); | ||||
|         Cache::forget('FFCURRENCYSYMBOL'); | ||||
|         Cache::forget('FFCURRENCYCODE'); | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(TransactionCurrency $currency) | ||||
|     { | ||||
|         if ($currency->transactionJournals()->count() > 0) { | ||||
|             Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); | ||||
|  | ||||
|             return Redirect::route('currency.index'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return view('currency.delete', compact('currency')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(TransactionCurrency $currency) | ||||
|     { | ||||
|         if ($currency->transactionJournals()->count() > 0) { | ||||
|             Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); | ||||
|  | ||||
|             return Redirect::route('currency.index'); | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'Currency "' . e($currency->name) . '" deleted'); | ||||
|  | ||||
|         $currency->delete(); | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function edit(TransactionCurrency $currency) | ||||
|     { | ||||
|         $subTitleIcon     = 'fa-pencil'; | ||||
|         $subTitle         = 'Edit currency "' . e($currency->name) . '"'; | ||||
|         $currency->symbol = htmlentities($currency->symbol); | ||||
|  | ||||
|         return view('currency.edit', compact('currency', 'subTitle', 'subTitleIcon')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $currencies         = TransactionCurrency::get(); | ||||
|         $currencyPreference = Preferences::get('currencyPreference', 'EUR'); | ||||
|         $defaultCurrency    = TransactionCurrency::whereCode($currencyPreference->data)->first(); | ||||
|  | ||||
|  | ||||
|         return view('currency.index', compact('currencies', 'defaultCurrency')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(CurrencyFormRequest $request) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         // no repository, because the currency controller is relatively simple. | ||||
|         $currency = TransactionCurrency::create( | ||||
|             [ | ||||
|                 'name'   => $request->get('name'), | ||||
|                 'code'   => $request->get('code'), | ||||
|                 'symbol' => $request->get('symbol'), | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         Session::flash('success', 'Currency "' . $currency->name . '" created'); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('currency.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(TransactionCurrency $currency, CurrencyFormRequest $request) | ||||
|     { | ||||
|  | ||||
|         $currency->code   = $request->get('code'); | ||||
|         $currency->symbol = $request->get('symbol'); | ||||
|         $currency->name   = $request->get('name'); | ||||
|         $currency->save(); | ||||
|  | ||||
|         Session::flash('success', 'Currency "' . e($currency->name) . '" updated.'); | ||||
|  | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('currency.edit', $currency->id); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										668
									
								
								app/Http/Controllers/GoogleChartController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										668
									
								
								app/Http/Controllers/GoogleChartController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,668 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use App; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use Exception; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Database\Query\Builder as QueryBuilder; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleChartController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class GoogleChartController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $view | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function accountBalanceChart(Account $account, GChart $chart) | ||||
|     { | ||||
|         $chart->addColumn('Day of month', 'date'); | ||||
|         $chart->addColumn('Balance for ' . $account->name, 'number'); | ||||
|         $chart->addCertainty(1); | ||||
|  | ||||
|         $start   = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end     = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $current = clone $start; | ||||
|         $today = new Carbon; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $certain = $current < $today; | ||||
|             $chart->addRow(clone $current, Steam::balance($account, $current), $certain); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart $chart | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allAccountsBalanceChart(GChart $chart) | ||||
|     { | ||||
|         $chart->addColumn('Day of the month', 'date'); | ||||
|  | ||||
|         $frontPage = Preferences::get('frontPageAccounts', []); | ||||
|         $start     = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end       = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         if ($frontPage->data == []) { | ||||
|             $accounts = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); | ||||
|         } else { | ||||
|             $accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|         } | ||||
|         $index = 1; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $chart->addColumn('Balance for ' . $account->name, 'number'); | ||||
|             $chart->addCertainty($index); | ||||
|             $index++; | ||||
|         } | ||||
|         $current = clone $start; | ||||
|         $current->subDay(); | ||||
|         $today = Carbon::now(); | ||||
|         while ($end >= $current) { | ||||
|             $row     = [clone $current]; | ||||
|             $certain = $current < $today; | ||||
|             foreach ($accounts as $account) { | ||||
|                 $row[] = Steam::balance($account, $current); | ||||
|                 $row[] = $certain; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $year | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|         $budgets = Auth::user()->budgets()->get(); | ||||
|         $budgets->sortBy('name'); | ||||
|         $chart->addColumn('Month', 'date'); | ||||
|         foreach ($budgets as $budget) { | ||||
|             $chart->addColumn($budget->name, 'number'); | ||||
|         } | ||||
|         $start = Carbon::createFromDate(intval($year), 1, 1); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfYear(); | ||||
|  | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $row = [clone $start]; | ||||
|             foreach ($budgets as $budget) { | ||||
|                 $spent = $repository->spentInMonth($budget, $start); | ||||
|                 $row[] = $spent; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart $chart | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allBudgetsHomeChart(GChart $chart) | ||||
|     { | ||||
|         $chart->addColumn('Budget', 'string'); | ||||
|         $chart->addColumn('Budgeted', 'number'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $budgets = Auth::user()->budgets()->orderBy('name', 'DESC')->get(); | ||||
|         $start   = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end     = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|  | ||||
|             /** @var Collection $repetitions */ | ||||
|             $repetitions = LimitRepetition:: | ||||
|             leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                                           ->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00')) | ||||
|                                           ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00')) | ||||
|                                           ->where('budget_limits.budget_id', $budget->id) | ||||
|                                           ->get(['limit_repetitions.*']); | ||||
|  | ||||
|             // no results? search entire range for expenses and list those. | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $expenses = floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; | ||||
|                 if ($expenses > 0) { | ||||
|                     $chart->addRow($budget->name, 0, $expenses); | ||||
|                 } | ||||
|             } else { | ||||
|                 // add with foreach: | ||||
|                 /** @var LimitRepetition $repetition */ | ||||
|                 foreach ($repetitions as $repetition) { | ||||
|  | ||||
|                     $expenses | ||||
|                         = | ||||
|                         floatval($budget->transactionjournals()->before($repetition->enddate)->after($repetition->startdate)->lessThan(0)->sum('amount')) * -1; | ||||
|                     if ($expenses > 0) { | ||||
|                         $chart->addRow($budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $noBudgetSet = Auth::user() | ||||
|                            ->transactionjournals() | ||||
|                            ->whereNotIn( | ||||
|                                'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) { | ||||
|                                $query | ||||
|                                    ->select('transaction_journals.id') | ||||
|                                    ->from('transaction_journals') | ||||
|                                    ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                    ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) | ||||
|                                    ->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00')) | ||||
|                                    ->whereNotNull('budget_transaction_journal.budget_id'); | ||||
|                            } | ||||
|                            ) | ||||
|                            ->before($end) | ||||
|                            ->after($start) | ||||
|                            ->lessThan(0) | ||||
|                            ->transactionTypes(['Withdrawal']) | ||||
|                            ->get(); | ||||
|         $sum         = $noBudgetSet->sum('amount') * -1; | ||||
|         $chart->addRow('No budget', 0, $sum); | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart $chart | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allCategoriesHomeChart(GChart $chart) | ||||
|     { | ||||
|         $chart->addColumn('Category', 'string'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         // query! | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $set   = TransactionJournal:: | ||||
|             where('transaction_journals.user_id',Auth::user()->id) | ||||
|             ->leftJoin( | ||||
|             'transactions', | ||||
|             function (JoinClause $join) { | ||||
|                 $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); | ||||
|             } | ||||
|         ) | ||||
|                                    ->leftJoin( | ||||
|                                        'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                                    ) | ||||
|                                    ->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id') | ||||
|                                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                    ->before($end) | ||||
|                                    ->where('categories.user_id',Auth::user()->id) | ||||
|                                    ->after($start) | ||||
|                                    ->where('transaction_types.type', 'Withdrawal') | ||||
|                                    ->groupBy('categories.id') | ||||
|                                    ->orderBy('sum', 'DESC') | ||||
|                                    ->get(['categories.id', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->name = strlen($entry->name) == 0 ? '(no category)' : $entry->name; | ||||
|             $chart->addRow($entry->name, floatval($entry->sum)); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function billOverview(Bill $bill, GChart $chart) | ||||
|     { | ||||
|  | ||||
|         $chart->addColumn('Date', 'date'); | ||||
|         $chart->addColumn('Max amount', 'number'); | ||||
|         $chart->addColumn('Min amount', 'number'); | ||||
|         $chart->addColumn('Current entry', 'number'); | ||||
|  | ||||
|         // get first transaction or today for start: | ||||
|         $first = $bill->transactionjournals()->orderBy('date', 'ASC')->first(); | ||||
|         if ($first) { | ||||
|             $start = $first->date; | ||||
|         } else { | ||||
|             $start = new Carbon; | ||||
|         } | ||||
|         $end = new Carbon; | ||||
|         while ($start <= $end) { | ||||
|             $result = $bill->transactionjournals()->before($end)->after($start)->first(); | ||||
|             if ($result) { | ||||
|                 /** @var Transaction $tr */ | ||||
|                 foreach ($result->transactions()->get() as $tr) { | ||||
|                     if (floatval($tr->amount) > 0) { | ||||
|                         $amount = floatval($tr->amount); | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 $amount = 0; | ||||
|             } | ||||
|             unset($result); | ||||
|             $chart->addRow(clone $start, $bill->amount_max, $bill->amount_min, $amount); | ||||
|             $start = Navigation::addPeriod($start, $bill->repeat_freq, 0); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart $chart | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function billsOverview(GChart $chart, BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn('Name', 'string'); | ||||
|         $chart->addColumn('Amount', 'number'); | ||||
|  | ||||
|  | ||||
|         $paid   = ['items' => [], 'amount' => 0]; | ||||
|         $unpaid = ['items' => [], 'amount' => 0]; | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         $bills = Auth::user()->bills()->where('active', 1)->get(); | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 // paid a bill in this range? | ||||
|                 $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); | ||||
|                 if ($count == 0) { | ||||
|                     $unpaid['items'][] = $bill->name . ' (' . $range['start']->format('jS M Y') . ')'; | ||||
|                     $unpaid['amount'] += ($bill->amount_max + $bill->amount_min / 2); | ||||
|  | ||||
|                 } else { | ||||
|                     $journal         = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); | ||||
|                     $paid['items'][] = $journal->description; | ||||
|                     $amount          = 0; | ||||
|                     foreach ($journal->transactions as $t) { | ||||
|                         if (floatval($t->amount) > 0) { | ||||
|                             $amount = floatval($t->amount); | ||||
|                         } | ||||
|                     } | ||||
|                     $paid['amount'] += $amount; | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']); | ||||
|         $chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']); | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Budget          $budget | ||||
|      * @param LimitRepetition $repetition | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart) | ||||
|     { | ||||
|         $start = clone $repetition->startdate; | ||||
|         $end   = $repetition->enddate; | ||||
|  | ||||
|         $chart->addColumn('Day', 'date'); | ||||
|         $chart->addColumn('Left', 'number'); | ||||
|  | ||||
|  | ||||
|         $amount = $repetition->amount; | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             /* | ||||
|              * Sum of expenses on this day: | ||||
|              */ | ||||
|             $sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount')); | ||||
|             $amount += $sum; | ||||
|             $chart->addRow(clone $start, $amount); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @param int    $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetsAndSpending(Budget $budget, $year = 0) | ||||
|     { | ||||
|  | ||||
|         $chart      = App::make('Grumpydictator\Gchart\GChart'); | ||||
|         $repository = App::make('FireflyIII\Repositories\Budget\BudgetRepository'); | ||||
|         $chart->addColumn('Month', 'date'); | ||||
|         $chart->addColumn('Budgeted', 'number'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|         if ($year == 0) { | ||||
|             // grab the first budgetlimit ever: | ||||
|             $firstLimit = $budget->budgetlimits()->orderBy('startdate', 'ASC')->first(); | ||||
|             if ($firstLimit) { | ||||
|                 $start = new Carbon($firstLimit->startdate); | ||||
|             } else { | ||||
|                 $start = Carbon::now()->startOfYear(); | ||||
|             } | ||||
|  | ||||
|             // grab the last budget limit ever: | ||||
|             $lastLimit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first(); | ||||
|             if ($lastLimit) { | ||||
|                 $end = new Carbon($lastLimit->startdate); | ||||
|             } else { | ||||
|                 $end = Carbon::now()->endOfYear(); | ||||
|             } | ||||
|         } else { | ||||
|             $start = Carbon::createFromDate(intval($year), 1, 1); | ||||
|             $end   = clone $start; | ||||
|             $end->endOfYear(); | ||||
|         } | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $spent      = $repository->spentInMonth($budget, $start); | ||||
|             $repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                                          ->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00')) | ||||
|                                          ->where('budget_limits.budget_id', $budget->id) | ||||
|                                          ->first(['limit_repetitions.*']); | ||||
|  | ||||
|             if ($repetition) { | ||||
|                 $budgeted = floatval($repetition->amount); | ||||
|                 \Log::debug('Found a repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name . '!'); | ||||
|             } else { | ||||
|                 \Log::debug('No repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name); | ||||
|                 $budgeted = null; | ||||
|             } | ||||
|             $chart->addRow(clone $start, $budgeted, $spent); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function categoryOverviewChart(Category $category, GChart $chart) | ||||
|     { | ||||
|         // oldest transaction in category: | ||||
|         /** @var TransactionJournal $first */ | ||||
|         $first = $category->transactionjournals()->orderBy('date', 'ASC')->first(); | ||||
|         $start = $first->date; | ||||
|         /** @var Preference $range */ | ||||
|         $range = Preferences::get('viewRange', '1M'); | ||||
|         // jump to start of week / month / year / etc (TODO). | ||||
|         $start = Navigation::startOfPeriod($start, $range->data); | ||||
|  | ||||
|         $chart->addColumn('Period', 'date'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $end = new Carbon; | ||||
|         while ($start <= $end) { | ||||
|  | ||||
|             $currentEnd = Navigation::endOfPeriod($start, $range->data); | ||||
|             $spent      = floatval($category->transactionjournals()->before($currentEnd)->after($start)->lessThan(0)->sum('amount')) * -1; | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|  | ||||
|             $start = Navigation::addPeriod($start, $range->data, 0); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function categoryPeriodChart(Category $category, GChart $chart) | ||||
|     { | ||||
|         // oldest transaction in category: | ||||
|         /** @var TransactionJournal $first */ | ||||
|         $start = clone Session::get('start'); | ||||
|         $chart->addColumn('Period', 'date'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $end = Session::get('end'); | ||||
|         while ($start <= $end) { | ||||
|             $spent = floatval($category->transactionjournals()->onDate($start)->lessThan(0)->sum('amount')) * -1; | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart) | ||||
|     { | ||||
|         $chart->addColumn('Date', 'date'); | ||||
|         $chart->addColumn('Balance', 'number'); | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $set = DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); | ||||
|         $sum = 0; | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum += floatval($entry->sum); | ||||
|             $chart->addRow(new Carbon($entry->date), $sum); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function yearInExp($year, GChart $chart, ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             $start = new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|         $chart->addColumn('Month', 'date'); | ||||
|         $chart->addColumn('Income', 'number'); | ||||
|         $chart->addColumn('Expenses', 'number'); | ||||
|  | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|  | ||||
|         // get report query interface. | ||||
|  | ||||
|         $end = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start < $end) { | ||||
|             $currentEnd = clone $start; | ||||
|             $currentEnd->endOfMonth(); | ||||
|             // total income: | ||||
|             $income    = $query->incomeByPeriod($start, $currentEnd, $showSharedReports); | ||||
|             $incomeSum = 0; | ||||
|             foreach ($income as $entry) { | ||||
|                 $incomeSum += floatval($entry->amount); | ||||
|             } | ||||
|  | ||||
|             // total expenses: | ||||
|             $expense    = $query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports); | ||||
|             $expenseSum = 0; | ||||
|             foreach ($expense as $entry) { | ||||
|                 $expenseSum += floatval($entry->amount); | ||||
|             } | ||||
|  | ||||
|             $chart->addRow(clone $start, $incomeSum, $expenseSum); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function yearInExpSum($year, GChart $chart, ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             $start = new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|         $chart->addColumn('Summary', 'string'); | ||||
|         $chart->addColumn('Income', 'number'); | ||||
|         $chart->addColumn('Expenses', 'number'); | ||||
|  | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|  | ||||
|         $income  = 0; | ||||
|         $expense = 0; | ||||
|         $count   = 0; | ||||
|  | ||||
|         $end = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start < $end) { | ||||
|             $currentEnd = clone $start; | ||||
|             $currentEnd->endOfMonth(); | ||||
|             // total income: | ||||
|             $incomeResult = $query->incomeByPeriod($start, $currentEnd, $showSharedReports); | ||||
|             $incomeSum    = 0; | ||||
|             foreach ($incomeResult as $entry) { | ||||
|                 $incomeSum += floatval($entry->amount); | ||||
|             } | ||||
|  | ||||
|             // total expenses: | ||||
|             $expenseResult = $query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports); | ||||
|             $expenseSum    = 0; | ||||
|             foreach ($expenseResult as $entry) { | ||||
|                 $expenseSum += floatval($entry->amount); | ||||
|             } | ||||
|  | ||||
|             $income += $incomeSum; | ||||
|             $expense += $expenseSum; | ||||
|             $count++; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->addRow('Sum', $income, $expense); | ||||
|         $count = $count > 0 ? $count : 1; | ||||
|         $chart->addRow('Average', ($income / $count), ($expense / $count)); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										92
									
								
								app/Http/Controllers/HelpController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								app/Http/Controllers/HelpController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Cache; | ||||
| use ErrorException; | ||||
| use FireflyIII\Http\Requests; | ||||
| use League\CommonMark\CommonMarkConverter; | ||||
| use Response; | ||||
| use Route; | ||||
|  | ||||
| /** | ||||
|  * Class HelpController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class HelpController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show($route) | ||||
|     { | ||||
|         $content = [ | ||||
|             'text'  => '<p>There is no help for this route!</p>', | ||||
|             'title' => 'Help', | ||||
|         ]; | ||||
|  | ||||
|         if (!Route::has($route)) { | ||||
|             \Log::error('No such route: ' . $route); | ||||
|  | ||||
|             return Response::json($content); | ||||
|         } | ||||
|  | ||||
|         if ($this->_inCache($route)) { | ||||
|             $content = [ | ||||
|                 'text'  => Cache::get('help.' . $route . '.text'), | ||||
|                 'title' => Cache::get('help.' . $route . '.title'), | ||||
|             ]; | ||||
|  | ||||
|             return Response::json($content); | ||||
|         } | ||||
|         $content = $this->_getFromGithub($route); | ||||
|  | ||||
|  | ||||
|         Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week. | ||||
|         Cache::put('help.' . $route . '.title', $content['title'], 10080); | ||||
|  | ||||
|         return Response::json($content); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function _inCache($route) | ||||
|     { | ||||
|         return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function _getFromGithub($route) | ||||
|     { | ||||
|         $uri     = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md'; | ||||
|         $content = [ | ||||
|             'text'  => '<p>There is no help for this route!</p>', | ||||
|             'title' => $route, | ||||
|         ]; | ||||
|         try { | ||||
|             $content['text'] = file_get_contents($uri); | ||||
|         } catch (ErrorException $e) { | ||||
|             \Log::error(trim($e->getMessage())); | ||||
|         } | ||||
|         if (strlen(trim($content['text'])) == 0) { | ||||
|             $content['text'] = '<p>There is no help for this route.</p>'; | ||||
|         } | ||||
|         $converter       = new CommonMarkConverter(); | ||||
|         $content['text'] = $converter->convertToHtml($content['text']); | ||||
|  | ||||
|         return $content; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										60
									
								
								app/Http/Controllers/HomeController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								app/Http/Controllers/HomeController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class HomeController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class HomeController extends Controller | ||||
| { | ||||
|  | ||||
|     public function dateRange() | ||||
|     { | ||||
|         $start = new Carbon(Input::get('start')); | ||||
|         $end   = new Carbon(Input::get('end')); | ||||
|  | ||||
|         $diff = $start->diffInDays($end); | ||||
|  | ||||
|         if ($diff > 50) { | ||||
|             Session::flash('warning', $diff . ' days of data may take a while to load.'); | ||||
|         } | ||||
|  | ||||
|         Session::put('start', $start); | ||||
|         Session::put('end', $end); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|         $count         = $repository->countAssetAccounts(); | ||||
|         $title         = 'Firefly'; | ||||
|         $subTitle      = 'What\'s playing?'; | ||||
|         $mainTitleIcon = 'fa-fire'; | ||||
|         $transactions  = []; | ||||
|         $frontPage     = Preferences::get('frontPageAccounts', []); | ||||
|         $start         = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end           = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $accounts      = $repository->getFrontpageAccounts($frontPage); | ||||
|         $savings       = $repository->getSavingsAccounts(); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $set = $repository->getFrontpageTransactions($account, $start, $end); | ||||
|             if (count($set) > 0) { | ||||
|                 $transactions[] = [$set, $account]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions')); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										200
									
								
								app/Http/Controllers/JsonController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								app/Http/Controllers/JsonController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,200 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Amount; | ||||
| use Auth; | ||||
| use DB; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Config; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| /** | ||||
|  * Class JsonController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class JsonController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function box(BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $amount = 0; | ||||
|         $start  = Session::get('start'); | ||||
|         $end    = Session::get('end'); | ||||
|         $box    = 'empty'; | ||||
|         switch (Input::get('box')) { | ||||
|             case 'in': | ||||
|                 $box = Input::get('box'); | ||||
|                 $in  = Auth::user()->transactionjournals() | ||||
|                            ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                            ->before($end) | ||||
|                            ->after($start) | ||||
|                            ->transactionTypes(['Deposit']) | ||||
|                            ->where('transactions.amount', '>', 0) | ||||
|                            ->first([DB::Raw('SUM(transactions.amount) as `amount`')]); | ||||
|                 if (!is_null($in)) { | ||||
|                     $amount = floatval($in->amount); | ||||
|                 } | ||||
|  | ||||
|                 break; | ||||
|             case 'out': | ||||
|                 $box = Input::get('box'); | ||||
|                 $in  = Auth::user()->transactionjournals() | ||||
|                            ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                            ->before($end) | ||||
|                            ->after($start) | ||||
|                            ->transactionTypes(['Withdrawal']) | ||||
|                            ->where('transactions.amount', '>', 0) | ||||
|                            ->first([DB::Raw('SUM(transactions.amount) as `amount`')]); | ||||
|                 if (!is_null($in)) { | ||||
|                     $amount = floatval($in->amount); | ||||
|                 } | ||||
|  | ||||
|                 break; | ||||
|             case 'bills-unpaid': | ||||
|                 $box   = 'bills-unpaid'; | ||||
|                 $bills = Auth::user()->bills()->where('active', 1)->get(); | ||||
|  | ||||
|                 /** @var Bill $bill */ | ||||
|                 foreach ($bills as $bill) { | ||||
|                     $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|                     foreach ($ranges as $range) { | ||||
|                         // paid a bill in this range? | ||||
|                         $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); | ||||
|                         if ($count == 0) { | ||||
|                             $amount += floatval($bill->amount_max + $bill->amount_min / 2); | ||||
|  | ||||
|                         } | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|                 break; | ||||
|             case 'bills-paid': | ||||
|                 $box = 'bills-paid'; | ||||
|                 // these two functions are the same as the chart TODO | ||||
|                 $bills = Auth::user()->bills()->where('active', 1)->get(); | ||||
|  | ||||
|                 /** @var Bill $bill */ | ||||
|                 foreach ($bills as $bill) { | ||||
|                     $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|                     foreach ($ranges as $range) { | ||||
|                         // paid a bill in this range? | ||||
|                         $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); | ||||
|                         if ($count != 0) { | ||||
|                             $journal         = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); | ||||
|                             $paid['items'][] = $journal->description; | ||||
|                             $currentAmount   = 0; | ||||
|                             foreach ($journal->transactions as $t) { | ||||
|                                 if (floatval($t->amount) > 0) { | ||||
|                                     $currentAmount = floatval($t->amount); | ||||
|                                 } | ||||
|                             } | ||||
|                             $amount += $currentAmount; | ||||
|                         } | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|         return Response::json(['box' => $box, 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of categories. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function categories() | ||||
|     { | ||||
|         $list   = Auth::user()->categories()->orderBy('name', 'ASC')->get(); | ||||
|         $return = []; | ||||
|         foreach ($list as $entry) { | ||||
|             $return[] = $entry->name; | ||||
|         } | ||||
|  | ||||
|         return Response::json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a JSON list of all beneficiaries. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function expenseAccounts() | ||||
|     { | ||||
|         $list   = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Expense account', 'Beneficiary account'])->get(); | ||||
|         $return = []; | ||||
|         foreach ($list as $entry) { | ||||
|             $return[] = $entry->name; | ||||
|         } | ||||
|  | ||||
|         return Response::json($return); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function revenueAccounts() | ||||
|     { | ||||
|         $list   = Auth::user()->accounts()->accountTypeIn(['Revenue account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|         $return = []; | ||||
|         foreach ($list as $entry) { | ||||
|             $return[] = $entry->name; | ||||
|         } | ||||
|  | ||||
|         return Response::json($return); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function setSharedReports() | ||||
|     { | ||||
|         $pref = Preferences::get('showSharedReports', false); | ||||
|         $new  = !$pref->data; | ||||
|         Preferences::set('showSharedReports', $new); | ||||
|  | ||||
|  | ||||
|         return Response::json(['value' => $new]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function showSharedReports() | ||||
|     { | ||||
|         $pref = Preferences::get('showSharedReports', false); | ||||
|  | ||||
|         return Response::json(['value' => $pref->data]); | ||||
|     } | ||||
|  | ||||
|     public function transactionJournals($what) | ||||
|     { | ||||
|         $descriptions = []; | ||||
|             $dbType   = TransactionType::whereType($what)->first(); | ||||
|             $journals = Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id) | ||||
|                 ->orderBy('id','DESC')->take(50) | ||||
|                 ->get(); | ||||
|             foreach($journals as $j) { | ||||
|                 $descriptions[] = $j->description; | ||||
|             } | ||||
|  | ||||
|         $descriptions = array_unique($descriptions); | ||||
|         sort($descriptions); | ||||
|         return Response::json($descriptions); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										360
									
								
								app/Http/Controllers/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								app/Http/Controllers/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,360 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Amount; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use ExpandedForm; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\PiggyBankFormRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use Steam; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('title', 'Piggy banks'); | ||||
|         View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Add money to piggy bank | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function add(PiggyBank $piggyBank, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $leftOnAccount = $repository->leftOnAccount($piggyBank->account); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $maxAmount     = min($leftOnAccount, $leftToSave); | ||||
|  | ||||
|  | ||||
|         \Log::debug('Now going to view for piggy bank #' . $piggyBank->id . ' (' . $piggyBank->name . ')'); | ||||
|  | ||||
|         return view('piggy-banks.add', compact('piggyBank', 'maxAmount')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|  | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
|         $accounts     = ExpandedForm::makeSelectList( | ||||
|             Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']) | ||||
|         ); | ||||
|         $subTitle     = 'Create new piggy bank'; | ||||
|         $subTitleIcon = 'fa-plus'; | ||||
|  | ||||
|         return view('piggy-banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(PiggyBank $piggyBank) | ||||
|     { | ||||
|         $subTitle = 'Delete "' . e($piggyBank->name) . '"'; | ||||
|  | ||||
|         return view('piggy-banks.delete', compact('piggyBank', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.'); | ||||
|         $piggyBank->delete(); | ||||
|  | ||||
|         return Redirect::route('piggy-banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
|         $accounts     = ExpandedForm::makeSelectList( | ||||
|             Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']) | ||||
|         ); | ||||
|         $subTitle     = 'Edit piggy bank "' . e($piggyBank->name) . '"'; | ||||
|         $subTitleIcon = 'fa-pencil'; | ||||
|  | ||||
|         /* | ||||
|          * Flash some data to fill the form. | ||||
|          */ | ||||
|         if (is_null($piggyBank->targetdate) || $piggyBank->targetdate == '') { | ||||
|             $targetDate = null; | ||||
|         } else { | ||||
|             $targetDate = new Carbon($piggyBank->targetdate); | ||||
|             $targetDate = $targetDate->format('Y-m-d'); | ||||
|         } | ||||
|         $preFilled = ['name'         => $piggyBank->name, | ||||
|                       'account_id'   => $piggyBank->account_id, | ||||
|                       'targetamount' => $piggyBank->targetamount, | ||||
|                       'targetdate'   => $targetDate, | ||||
|                       'reminder'     => $piggyBank->reminder, | ||||
|                       'remind_me'    => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false | ||||
|         ]; | ||||
|         Session::flash('preFilled', $preFilled); | ||||
|  | ||||
|         return view('piggy-banks.edit', compact('subTitle', 'subTitleIcon', 'piggyBank', 'accounts', 'periods', 'preFilled')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         /** @var Collection $piggyBanks */ | ||||
|         $piggyBanks = Auth::user()->piggyBanks()->where('repeats', 0)->orderBy('order', 'ASC')->get(); | ||||
|  | ||||
|         $accounts = []; | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         foreach ($piggyBanks as $piggyBank) { | ||||
|             $piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount); | ||||
|             $piggyBank->percentage = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100); | ||||
|             $piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar; | ||||
|  | ||||
|             /* | ||||
|              * Fill account information: | ||||
|              */ | ||||
|             $account = $piggyBank->account; | ||||
|             if (!isset($accounts[$account->id])) { | ||||
|                 $accounts[$account->id] = [ | ||||
|                     'name'              => $account->name, | ||||
|                     'balance'           => Steam::balance($account), | ||||
|                     'leftForPiggyBanks' => $repository->leftOnAccount($account), | ||||
|                     'sumOfSaved'        => $piggyBank->savedSoFar, | ||||
|                     'sumOfTargets'      => floatval($piggyBank->targetamount), | ||||
|                     'leftToSave'        => $piggyBank->leftToSave | ||||
|                 ]; | ||||
|             } else { | ||||
|                 $accounts[$account->id]['sumOfSaved'] += $piggyBank->savedSoFar; | ||||
|                 $accounts[$account->id]['sumOfTargets'] += floatval($piggyBank->targetamount); | ||||
|                 $accounts[$account->id]['leftToSave'] += $piggyBank->leftToSave; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return view('piggy-banks.index', compact('piggyBanks', 'accounts')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Allow user to order piggy banks. | ||||
|      */ | ||||
|     public function order(PiggyBankRepositoryInterface $repository) | ||||
|     { | ||||
|         $data = Input::get('order'); | ||||
|  | ||||
|         // set all users piggy banks to zero: | ||||
|         $repository->reset(); | ||||
|  | ||||
|         if (is_array($data)) { | ||||
|             foreach ($data as $order => $id) { | ||||
|                 $repository->setOrder(intval($id), (intval($order) + 1)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * POST add money to piggy bank | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function postAdd(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts) | ||||
|     { | ||||
|         $amount        = round(floatval(Input::get('amount')), 2); | ||||
|         $leftOnAccount = $accounts->leftOnAccount($piggyBank->account); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $maxAmount     = round(min($leftOnAccount, $leftToSave), 2); | ||||
|  | ||||
|         if ($amount <= $maxAmount) { | ||||
|             $repetition = $piggyBank->currentRelevantRep(); | ||||
|             $repetition->currentamount += $amount; | ||||
|             $repetition->save(); | ||||
|  | ||||
|             // create event. | ||||
|             PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]); | ||||
|  | ||||
|             /* | ||||
|              * Create event! | ||||
|              */ | ||||
|             //Event::fire('piggy_bank.addMoney', [$piggyBank, $amount]); // new and used. | ||||
|  | ||||
|             Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('piggy-banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function postRemove(PiggyBank $piggyBank) | ||||
|     { | ||||
|         $amount = floatval(Input::get('amount')); | ||||
|  | ||||
|         $savedSoFar = $piggyBank->currentRelevantRep()->currentamount; | ||||
|  | ||||
|         if ($amount <= $savedSoFar) { | ||||
|             $repetition = $piggyBank->currentRelevantRep(); | ||||
|             $repetition->currentamount -= $amount; | ||||
|             $repetition->save(); | ||||
|  | ||||
|             PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount * -1, 'piggy_bank_id' => $piggyBank->id]); | ||||
|  | ||||
|             /* | ||||
|              * Create event! | ||||
|              */ | ||||
|             //Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used. | ||||
|  | ||||
|             Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('piggy-banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @SuppressWarnings("Unused") | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function remove(PiggyBank $piggyBank) | ||||
|     { | ||||
|         return view('piggy-banks.remove', compact('piggyBank')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function show(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         $events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get(); | ||||
|  | ||||
|         /* | ||||
|          * Number of reminders: | ||||
|          */ | ||||
|  | ||||
|         $subTitle = e($piggyBank->name); | ||||
|  | ||||
|         return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBankFormRequest         $request | ||||
|      * @param PiggyBankRepositoryInterface $repository | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository) | ||||
|     { | ||||
|         $piggyBankData = [ | ||||
|             'repeats'      => false, | ||||
|             'name'         => $request->get('name'), | ||||
|             'startdate'    => new Carbon, | ||||
|             'account_id'   => intval($request->get('account_id')), | ||||
|             'targetamount' => floatval($request->get('targetamount')), | ||||
|             'targetdate'   => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null, | ||||
|             'reminder'     => $request->get('reminder'), | ||||
|             'remind_me'    => $request->get('remind_me'), | ||||
|         ]; | ||||
|  | ||||
|         $piggyBank = $repository->store($piggyBankData); | ||||
|  | ||||
|         Session::flash('success', 'Stored piggy bank "' . e($piggyBank->name) . '".'); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('piggy-banks.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return Redirect::route('piggy-banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function update(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request) | ||||
|     { | ||||
|         $piggyBankData = [ | ||||
|             'repeats'      => false, | ||||
|             'name'         => $request->get('name'), | ||||
|             'startdate'    => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate, | ||||
|             'account_id'   => intval($request->get('account_id')), | ||||
|             'targetamount' => floatval($request->get('targetamount')), | ||||
|             'targetdate'   => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null, | ||||
|             'reminder'     => $request->get('reminder'), | ||||
|             'remind_me'    => $request->get('remind_me') | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|         $piggyBank = $repository->update($piggyBank, $piggyBankData); | ||||
|  | ||||
|         Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".'); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('piggy-banks.edit', $piggyBank->id); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return Redirect::route('piggy-banks.index'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										75
									
								
								app/Http/Controllers/PreferencesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								app/Http/Controllers/PreferencesController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Http\Requests; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class PreferencesController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class PreferencesController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|  | ||||
|         View::share('title', 'Preferences'); | ||||
|         View::share('mainTitleIcon', 'fa-gear'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $accounts       = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|         $viewRange      = Preferences::get('viewRange', '1M'); | ||||
|         $viewRangeValue = $viewRange->data; | ||||
|         $frontPage      = Preferences::get('frontPageAccounts', []); | ||||
|         $budgetMax      = Preferences::get('budgetMaximum', 1000); | ||||
|         $budgetMaximum  = $budgetMax->data; | ||||
|  | ||||
|         return view('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with( | ||||
|             'viewRange', $viewRangeValue | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function postIndex() | ||||
|     { | ||||
|         // front page accounts | ||||
|         $frontPageAccounts = []; | ||||
|         foreach (Input::get('frontPageAccounts') as $id) { | ||||
|             $frontPageAccounts[] = intval($id); | ||||
|         } | ||||
|         Preferences::set('frontPageAccounts', $frontPageAccounts); | ||||
|  | ||||
|         // view range: | ||||
|         Preferences::set('viewRange', Input::get('viewRange')); | ||||
|         // forget session values: | ||||
|         Session::forget('start'); | ||||
|         Session::forget('end'); | ||||
|         Session::forget('range'); | ||||
|  | ||||
|         // budget maximum: | ||||
|         $budgetMaximum = intval(Input::get('budgetMaximum')); | ||||
|         Preferences::set('budgetMaximum', $budgetMaximum); | ||||
|  | ||||
|  | ||||
|         Session::flash('success', 'Preferences saved!'); | ||||
|  | ||||
|         return Redirect::route('preferences'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										90
									
								
								app/Http/Controllers/ProfileController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								app/Http/Controllers/ProfileController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\ProfileFormRequest; | ||||
| use Hash; | ||||
| use Redirect; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class ProfileController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class ProfileController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function changePassword() | ||||
|     { | ||||
|         return view('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', 'Change your password')->with( | ||||
|             'mainTitleIcon', 'fa-user' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      * | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         return view('profile.index')->with('title', 'Profile')->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function postChangePassword(ProfileFormRequest $request) | ||||
|     { | ||||
|         // old, new1, new2 | ||||
|         if (!Hash::check($request->get('current_password'), Auth::user()->password)) { | ||||
|             Session::flash('error', 'Invalid current password!'); | ||||
|  | ||||
|             return Redirect::route('change-password'); | ||||
|         } | ||||
|         $result = $this->_validatePassword($request->get('current_password'), $request->get('new_password'), $request->get('new_password_confirmation')); | ||||
|         if (!($result === true)) { | ||||
|             Session::flash('error', $result); | ||||
|  | ||||
|             return Redirect::route('change-password'); | ||||
|         } | ||||
|  | ||||
|         // update the user with the new password. | ||||
|         Auth::user()->password = $request->get('new_password'); | ||||
|         Auth::user()->save(); | ||||
|  | ||||
|         Session::flash('success', 'Password changed!'); | ||||
|  | ||||
|         return Redirect::route('profile'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @param string $old | ||||
|      * @param string $new1 | ||||
|      * @param string $new2 | ||||
|      * | ||||
|      * @return string|bool | ||||
|      */ | ||||
|     protected function _validatePassword($old, $new1, $new2) | ||||
|     { | ||||
|         if (strlen($new1) == 0 || strlen($new2) == 0) { | ||||
|             return 'Do fill in a password!'; | ||||
|  | ||||
|         } | ||||
|         if ($new1 == $old) { | ||||
|             return 'The idea is to change your password.'; | ||||
|         } | ||||
|  | ||||
|         if ($new1 !== $new2) { | ||||
|             return 'New passwords do not match!'; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										177
									
								
								app/Http/Controllers/RelatedController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								app/Http/Controllers/RelatedController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Response; | ||||
| use URL; | ||||
|  | ||||
| /** | ||||
|  * Class RelatedController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class RelatedController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function alreadyRelated(TransactionJournal $journal) | ||||
|     { | ||||
|         $ids = []; | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($journal->transactiongroups()->get() as $group) { | ||||
|             /** @var TransactionJournal $loopJournal */ | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id != $journal->id) { | ||||
|                     $ids[] = $loopJournal->id; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         $unique   = array_unique($ids); | ||||
|         $journals = new Collection; | ||||
|         if (count($unique) > 0) { | ||||
|  | ||||
|             $journals = Auth::user()->transactionjournals()->whereIn('id', $unique)->get(); | ||||
|             $journals->each( | ||||
|                 function (TransactionJournal $journal) { | ||||
|                     /** @var Transaction $t */ | ||||
|                     foreach ($journal->transactions()->get() as $t) { | ||||
|                         if ($t->amount > 0) { | ||||
|                             $journal->amount = $t->amount; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|         $parent = $journal; | ||||
|  | ||||
|         return view('related.alreadyRelated', compact('parent', 'journals')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @param TransactionJournal $parentJournal | ||||
|      * @param TransactionJournal $childJournal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function getRemoveRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal) | ||||
|     { | ||||
|         $groups = $parentJournal->transactiongroups()->get(); | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id == $childJournal->id) { | ||||
|                     // remove from group: | ||||
|                     $group->transactionjournals()->detach($childJournal); | ||||
|                 } | ||||
|             } | ||||
|             if ($group->transactionjournals()->count() == 1) { | ||||
|                 $group->delete(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return Redirect::to(URL::previous()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $parentJournal | ||||
|      * @param TransactionJournal $childJournal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function relate(TransactionJournal $parentJournal, TransactionJournal $childJournal) | ||||
|     { | ||||
|         $group           = new TransactionGroup; | ||||
|         $group->relation = 'balance'; | ||||
|         $group->user_id  = Auth::user()->id; | ||||
|         $group->save(); | ||||
|         $group->transactionjournals()->save($parentJournal); | ||||
|         $group->transactionjournals()->save($childJournal); | ||||
|  | ||||
|         return Response::json(true); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function related(TransactionJournal $journal) | ||||
|     { | ||||
|         $groups  = $journal->transactiongroups()->get(); | ||||
|         $members = new Collection; | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             /** @var TransactionJournal $loopJournal */ | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id != $journal->id) { | ||||
|                     $members->push($loopJournal); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return view('related.relate', compact('journal', 'members')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @param TransactionJournal $parentJournal | ||||
|      * @param TransactionJournal $childJournal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function removeRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal) | ||||
|     { | ||||
|         $groups = $parentJournal->transactiongroups()->get(); | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id == $childJournal->id) { | ||||
|                     // remove from group: | ||||
|                     $group->transactionjournals()->detach($childJournal); | ||||
|                 } | ||||
|             } | ||||
|             if ($group->transactionjournals()->count() == 1) { | ||||
|                 $group->delete(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return Response::json(true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function search(TransactionJournal $journal, JournalRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|         $search = e(trim(Input::get('searchValue'))); | ||||
|         $parent = $journal; | ||||
|  | ||||
|         $journals = $repository->searchRelated($search, $journal); | ||||
|  | ||||
|         return view('related.searchResult', compact('journals', 'search', 'parent')); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										128
									
								
								app/Http/Controllers/ReminderController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								app/Http/Controllers/ReminderController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Reminders\ReminderHelperInterface; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use URL; | ||||
|  | ||||
| /** | ||||
|  * Class ReminderController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class ReminderController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      */ | ||||
|     public function act(Reminder $reminder) | ||||
|     { | ||||
|         $data = [ | ||||
|             'description'   => 'Money for piggy bank "' . $reminder->remindersable->name . '"', | ||||
|             'amount'        => round($reminder->metadata->perReminder, 2), | ||||
|             'account_to_id' => $reminder->remindersable->account_id, | ||||
|             'piggy_bank_id' => $reminder->remindersable_id, | ||||
|             'reminder_id'   => $reminder->id, | ||||
|         ]; | ||||
|         Session::flash('_old_input', $data); | ||||
|  | ||||
|         return Redirect::route('transactions.create', 'transfer'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      */ | ||||
|     public function dismiss(Reminder $reminder) | ||||
|     { | ||||
|         $reminder->notnow = true; | ||||
|         $reminder->save(); | ||||
|  | ||||
|         return Redirect::to(URL::previous()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function index(ReminderHelperInterface $helper) | ||||
|     { | ||||
|  | ||||
|         $reminders = Auth::user()->reminders()->get(); | ||||
|  | ||||
|         $reminders->each( | ||||
|             function (Reminder $reminder) use ($helper) { | ||||
|                 $reminder->description = $helper->getReminderText($reminder); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $today = new Carbon; | ||||
|         // active reminders: | ||||
|         $active = $reminders->filter( | ||||
|             function (Reminder $reminder) use ($today) { | ||||
|                 if ($reminder->notnow === false && $reminder->active === true && $reminder->startdate <= $today && $reminder->enddate >= $today) { | ||||
|                     return $reminder; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         // expired reminders: | ||||
|         $expired = $reminders->filter( | ||||
|             function (Reminder $reminder) use ($today) { | ||||
|                 if ($reminder->notnow === false && $reminder->active === true && $reminder->startdate > $today || $reminder->enddate < $today) { | ||||
|                     return $reminder; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         // inactive reminders | ||||
|         $inactive = $reminders->filter( | ||||
|             function (Reminder $reminder) use ($today) { | ||||
|                 if ($reminder->active === false) { | ||||
|                     return $reminder; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         // dismissed reminders | ||||
|         $dismissed = $reminders->filter( | ||||
|             function (Reminder $reminder) use ($today) { | ||||
|                 if ($reminder->notnow === true) { | ||||
|                     return $reminder; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $title         = 'Reminders'; | ||||
|         $mainTitleIcon = 'fa-clock-o'; | ||||
|  | ||||
|         return view('reminders.index', compact('dismissed', 'expired', 'inactive', 'active', 'title', 'mainTitleIcon')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      */ | ||||
|     public function show(Reminder $reminder) | ||||
|     { | ||||
|         $title         = 'Reminder'; | ||||
|         $mainTitleIcon = 'fa-clock-o'; | ||||
|         if ($reminder->notnow === true) { | ||||
|             $subTitle = 'Dismissed reminder'; | ||||
|         } else { | ||||
|             $subTitle = 'Reminder'; | ||||
|         } | ||||
|         $subTitle .= ' for piggy bank "' . $reminder->remindersable->name . '"'; | ||||
|  | ||||
|  | ||||
|         return view('reminders.show', compact('reminder', 'title', 'subTitle', 'mainTitleIcon')); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										393
									
								
								app/Http/Controllers/ReportController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										393
									
								
								app/Http/Controllers/ReportController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,393 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Exception; | ||||
| use FireflyIII\Helpers\Report\ReportHelperInterface; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use Steam; | ||||
| use View; | ||||
| use FireflyIII\Models\Preference; | ||||
|  | ||||
| /** | ||||
|  * Class ReportController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class ReportController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('title', 'Reports'); | ||||
|         View::share('mainTitleIcon', 'fa-line-chart'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function budget($year = '2014', $month = '1', ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid date'); | ||||
|         } | ||||
|         $date  = new Carbon($year . '-' . $month . '-01'); | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|         $start->subDay(); | ||||
|  | ||||
|         // shared accounts preference: | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|  | ||||
|  | ||||
|         $dayEarly     = clone $date; | ||||
|         $subTitle     = 'Budget report for ' . $date->format('F Y'); | ||||
|         $subTitleIcon = 'fa-calendar'; | ||||
|         $dayEarly     = $dayEarly->subDay(); | ||||
|         $accounts     = $query->getAllAccounts($start, $end, $showSharedReports); | ||||
|         $start->addDay(); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($start, $end, $query) { | ||||
|                 $budgets        = $query->getBudgetSummary($account, $start, $end); | ||||
|                 $balancedAmount = $query->balancedTransactionsSum($account, $start, $end); | ||||
|                 $array          = []; | ||||
|                 $hide           = true; | ||||
|                 foreach ($budgets as $budget) { | ||||
|                     $id         = intval($budget->id); | ||||
|                     $data       = $budget->toArray(); | ||||
|                     $array[$id] = $data; | ||||
|                     if (floatval($data['amount']) != 0) { | ||||
|                         $hide = false; | ||||
|                     } | ||||
|                 } | ||||
|                 $account->hide              = $hide; | ||||
|                 $account->budgetInformation = $array; | ||||
|                 $account->balancedAmount    = $balancedAmount; | ||||
|  | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|  | ||||
|         /** | ||||
|          * Start getBudgetsForMonth DONE | ||||
|          */ | ||||
|         $set                  = Auth::user()->budgets()->orderBy('budgets.name', 'ASC') | ||||
|                                     ->leftJoin( | ||||
|                                         'budget_limits', function (JoinClause $join) use ($date) { | ||||
|                                         $join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d')); | ||||
|                                     } | ||||
|                                     ) | ||||
|                                     ->get(['budgets.*', 'budget_limits.amount as amount']); | ||||
|         $budgets              = Steam::makeArray($set); | ||||
|         $amountSet            = $query->journalsByBudget($start, $end, $showSharedReports); | ||||
|         $amounts              = Steam::makeArray($amountSet); | ||||
|         $budgets              = Steam::mergeArrays($budgets, $amounts); | ||||
|         $budgets[0]['spent']  = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0; | ||||
|         $budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0; | ||||
|         $budgets[0]['name']   = 'No budget'; | ||||
|  | ||||
|         // find transactions to shared asset accounts, which are without a budget by default: | ||||
|         // which is only relevant when shared asset accounts are hidden. | ||||
|         if ($showSharedReports === false) { | ||||
|             $transfers = $query->sharedExpenses($start, $end); | ||||
|             foreach ($transfers as $transfer) { | ||||
|                 $budgets[0]['spent'] += floatval($transfer->amount) * -1; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * End getBudgetsForMonth DONE | ||||
|          */ | ||||
|  | ||||
|         return view('reports.budget', compact('subTitle', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param ReportHelperInterface $helper | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function index(ReportHelperInterface $helper) | ||||
|     { | ||||
|         $start         = Session::get('first'); | ||||
|         $months        = $helper->listOfMonths($start); | ||||
|         $years         = $helper->listOfYears($start); | ||||
|         $title         = 'Reports'; | ||||
|         $mainTitleIcon = 'fa-line-chart'; | ||||
|  | ||||
|         return view('reports.index', compact('years', 'months', 'title', 'mainTitleIcon')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $year | ||||
|      * @param string  $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1', ReportQueryInterface $query) | ||||
|     { | ||||
|  | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid date'); | ||||
|         } | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         $journals = $query->balancedTransactionsList($account, $start, $end); | ||||
|  | ||||
|         return view('reports.modal-journal-list', compact('journals')); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account              $account | ||||
|      * @param string               $year | ||||
|      * @param string               $month | ||||
|      * @param ReportQueryInterface $query | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1', ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid date'); | ||||
|         } | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|         $set = $query->getTransactionsWithoutBudget($account, $start, $end); | ||||
|  | ||||
|         $journals = $set->filter( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 $count = $journal->transactiongroups()->where('relation', 'balance')->count(); | ||||
|                 if ($count == 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return view('reports.modal-journal-list', compact('journals')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $year | ||||
|      * @param string  $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function modalNoBudget(Account $account, $year = '2014', $month = '1', ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid date'); | ||||
|         } | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|         $journals = $query->getTransactionsWithoutBudget($account, $start, $end); | ||||
|  | ||||
|         return view('reports.modal-journal-list', compact('journals')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function month($year = '2014', $month = '1', ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid date.'); | ||||
|         } | ||||
|         $date         = new Carbon($year . '-' . $month . '-01'); | ||||
|         $subTitle     = 'Report for ' . $date->format('F Y'); | ||||
|         $subTitleIcon = 'fa-calendar'; | ||||
|         $displaySum   = true; // to show sums in report. | ||||
|  | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|  | ||||
|  | ||||
|         /** | ||||
|          * | ||||
|          * get income for month (date) | ||||
|          * | ||||
|          */ | ||||
|  | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         /** | ||||
|          * Start getIncomeForMonth DONE | ||||
|          */ | ||||
|         $income = $query->incomeByPeriod($start, $end, $showSharedReports); | ||||
|         /** | ||||
|          * End getIncomeForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getExpenseGroupedForMonth DONE | ||||
|          */ | ||||
|         $set      = $query->journalsByExpenseAccount($start, $end, $showSharedReports); | ||||
|         $expenses = Steam::makeArray($set); | ||||
|         $expenses = Steam::sortArray($expenses); | ||||
|         $expenses = Steam::limitArray($expenses, 10); | ||||
|         /** | ||||
|          * End getExpenseGroupedForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getBudgetsForMonth DONE | ||||
|          */ | ||||
|         $set                  = Auth::user()->budgets() | ||||
|                                     ->leftJoin( | ||||
|                                         'budget_limits', function (JoinClause $join) use ($date) { | ||||
|                                         $join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d')); | ||||
|                                     } | ||||
|                                     ) | ||||
|                                     ->get(['budgets.*', 'budget_limits.amount as amount']); | ||||
|         $budgets              = Steam::makeArray($set); | ||||
|         $amountSet            = $query->journalsByBudget($start, $end, $showSharedReports); | ||||
|         $amounts              = Steam::makeArray($amountSet); | ||||
|         $budgets              = Steam::mergeArrays($budgets, $amounts); | ||||
|         $budgets[0]['spent']  = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0; | ||||
|         $budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0; | ||||
|         $budgets[0]['name']   = 'No budget'; | ||||
|  | ||||
|         // find transactions to shared expense accounts, which are without a budget by default: | ||||
|         if ($showSharedReports === false) { | ||||
|             $transfers = $query->sharedExpenses($start, $end); | ||||
|             foreach ($transfers as $transfer) { | ||||
|                 $budgets[0]['spent'] += floatval($transfer->amount) * -1; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * End getBudgetsForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getCategoriesForMonth DONE | ||||
|          */ | ||||
|         // all categories. | ||||
|         $result     = $query->journalsByCategory($start, $end); | ||||
|         $categories = Steam::makeArray($result); | ||||
|  | ||||
|         // all transfers | ||||
|         if ($showSharedReports === false) { | ||||
|             $result    = $query->sharedExpensesByCategory($start, $end); | ||||
|             $transfers = Steam::makeArray($result); | ||||
|             $merged    = Steam::mergeArrays($categories, $transfers); | ||||
|         } else { | ||||
|             $merged = $categories; | ||||
|         } | ||||
|  | ||||
|         // sort. | ||||
|         $sorted = Steam::sortNegativeArray($merged); | ||||
|  | ||||
|         // limit to $limit: | ||||
|         $categories = Steam::limitArray($sorted, 10); | ||||
|         /** | ||||
|          * End getCategoriesForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getAccountsForMonth | ||||
|          */ | ||||
|         $list     = $query->accountList($showSharedReports); | ||||
|         $accounts = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($list as $account) { | ||||
|             $id = intval($account->id); | ||||
|             /** @noinspection PhpParamsInspection */ | ||||
|             $accounts[$id] = [ | ||||
|                 'name'         => $account->name, | ||||
|                 'startBalance' => Steam::balance($account, $start), | ||||
|                 'endBalance'   => Steam::balance($account, $end) | ||||
|             ]; | ||||
|  | ||||
|             $accounts[$id]['difference'] = $accounts[$id]['endBalance'] - $accounts[$id]['startBalance']; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * End getAccountsForMonth | ||||
|          */ | ||||
|  | ||||
|  | ||||
|         return view( | ||||
|             'reports.month', | ||||
|             compact( | ||||
|                 'income', 'expenses', 'budgets', 'accounts', 'categories', | ||||
|                 'date', 'subTitle', 'displaySum', 'subTitleIcon' | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function year($year, ReportHelperInterface $helper, ReportQueryInterface $query) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return view('error')->with('message', 'Invalid date.'); | ||||
|         } | ||||
|         /** @var Preference $pref */ | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|         $date              = new Carbon('01-01-' . $year); | ||||
|         $end               = clone $date; | ||||
|         $end->endOfYear(); | ||||
|         $title           = 'Reports'; | ||||
|         $subTitle        = $year; | ||||
|         $subTitleIcon    = 'fa-bar-chart'; | ||||
|         $mainTitleIcon   = 'fa-line-chart'; | ||||
|         $balances        = $helper->yearBalanceReport($date, $showSharedReports); | ||||
|         $groupedIncomes  = $query->journalsByRevenueAccount($date, $end, $showSharedReports); | ||||
|         $groupedExpenses = $query->journalsByExpenseAccount($date, $end, $showSharedReports); | ||||
|  | ||||
|         //$groupedExpenses = $helper-> expensesGroupedByAccount($date, $end, 15); | ||||
|  | ||||
|         return view( | ||||
|             'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										42
									
								
								app/Http/Controllers/SearchController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/Http/Controllers/SearchController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Support\Search\SearchInterface; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class SearchController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class SearchController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Results always come in the form of an array [results, count, fullCount] | ||||
|      */ | ||||
|     public function index(SearchInterface $searcher) | ||||
|     { | ||||
|  | ||||
|         $subTitle = null; | ||||
|         $rawQuery = null; | ||||
|         $result   = []; | ||||
|         if (!is_null(Input::get('q')) && strlen(Input::get('q')) > 0) { | ||||
|             $rawQuery = trim(Input::get('q')); | ||||
|             $words    = explode(' ', $rawQuery); | ||||
|             $subTitle = 'Results for "' . e($rawQuery) . '"'; | ||||
|  | ||||
|             $transactions = $searcher->searchTransactions($words); | ||||
|             $accounts     = $searcher->searchAccounts($words); | ||||
|             $categories   = $searcher->searchCategories($words); | ||||
|             $budgets      = $searcher->searchBudgets($words); | ||||
|             $tags         = $searcher->searchTags($words); | ||||
|             $result       = ['transactions' => $transactions, 'accounts' => $accounts, 'categories' => $categories, 'budgets' => $budgets, 'tags' => $tags]; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return view('search.index')->with('title', 'Search')->with('subTitle', $subTitle)->with( | ||||
|             'mainTitleIcon', 'fa-search' | ||||
|         )->with('query', $rawQuery)->with('result', $result); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										357
									
								
								app/Http/Controllers/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								app/Http/Controllers/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,357 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use ExpandedForm; | ||||
| use FireflyIII\Events\JournalCreated; | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\JournalFormRequest; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use View; | ||||
| use Response; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class TransactionController extends Controller | ||||
| { | ||||
|     /** | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         View::share('title', 'Transactions'); | ||||
|         View::share('mainTitleIcon', 'fa-repeat'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the view helping the user to create a new transaction journal. | ||||
|      * | ||||
|      * @param string $what | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function create($what = 'deposit') | ||||
|     { | ||||
|         $accounts   = ExpandedForm::makeSelectList( | ||||
|             Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->orderBy('name', 'ASC')->where( | ||||
|                 'active', 1 | ||||
|             )->orderBy('name', 'DESC')->get(['accounts.*']) | ||||
|         ); | ||||
|         $budgets    = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0] = '(no budget)'; | ||||
|         $piggies    = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $piggies[0] = '(no piggy bank)'; | ||||
|         $preFilled  = Session::has('preFilled') ? Session::get('preFilled') : []; | ||||
|         $respondTo  = ['account_id', 'account_from_id']; | ||||
|         $subTitle   = 'Add a new ' . e($what); | ||||
|  | ||||
|         foreach ($respondTo as $r) { | ||||
|             if (!is_null(Input::get($r))) { | ||||
|                 $preFilled[$r] = Input::get($r); | ||||
|             } | ||||
|         } | ||||
|         Session::put('preFilled', $preFilled); | ||||
|  | ||||
|         asort($piggies); | ||||
|  | ||||
|  | ||||
|         return view('transactions.create', compact('accounts', 'budgets', 'what', 'piggies', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the form that allows a user to delete a transaction journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(TransactionJournal $journal) | ||||
|     { | ||||
|         $type     = strtolower($journal->transactionType->type); | ||||
|         $subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"'; | ||||
|  | ||||
|         return View::make('transactions.delete', compact('journal', 'subTitle')); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $transactionJournal | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(TransactionJournal $transactionJournal) | ||||
|     { | ||||
|         $type   = $transactionJournal->transactionType->type; | ||||
|         $return = 'withdrawal'; | ||||
|  | ||||
|         Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.'); | ||||
|  | ||||
|         $transactionJournal->delete(); | ||||
|  | ||||
|         switch ($type) { | ||||
|             case 'Deposit': | ||||
|                 $return = 'deposit'; | ||||
|                 break; | ||||
|             case 'Transfer': | ||||
|                 $return = 'transfers'; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('transactions.index', $return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the view to edit a transaction. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository) | ||||
|     { | ||||
|         $what         = strtolower($journal->transactiontype->type); | ||||
|         $accounts     = ExpandedForm::makeSelectList( | ||||
|             Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->where('active', 1)->orderBy( | ||||
|                 'name', 'DESC' | ||||
|             )->get(['accounts.*']) | ||||
|         ); | ||||
|         $budgets      = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0]   = '(no budget)'; | ||||
|         $transactions = $journal->transactions()->orderBy('amount', 'DESC')->get(); | ||||
|         $piggies      = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $piggies[0]   = '(no piggy bank)'; | ||||
|         $preFilled    = [ | ||||
|             'date'          => $journal->date->format('Y-m-d'), | ||||
|             'category'      => '', | ||||
|             'budget_id'     => 0, | ||||
|             'piggy_bank_id' => 0 | ||||
|         ]; | ||||
|  | ||||
|         $category = $journal->categories()->first(); | ||||
|         if (!is_null($category)) { | ||||
|             $preFilled['category'] = $category->name; | ||||
|         } | ||||
|  | ||||
|         $budget = $journal->budgets()->first(); | ||||
|         if (!is_null($budget)) { | ||||
|             $preFilled['budget_id'] = $budget->id; | ||||
|         } | ||||
|  | ||||
|         if ($journal->piggyBankEvents()->count() > 0) { | ||||
|             $preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id; | ||||
|         } | ||||
|  | ||||
|         $preFilled['amount'] = 0; | ||||
|         /** @var Transaction $t */ | ||||
|         foreach ($transactions as $t) { | ||||
|             if (floatval($t->amount) > 0) { | ||||
|                 $preFilled['amount'] = floatval($t->amount); | ||||
|             } | ||||
|         } | ||||
|         $preFilled['account_id']      = $repository->getAssetAccount($journal); | ||||
|         $preFilled['expense_account'] = $transactions[0]->account->name; | ||||
|         $preFilled['revenue_account'] = $transactions[1]->account->name; | ||||
|         $preFilled['account_from_id'] = $transactions[1]->account->id; | ||||
|         $preFilled['account_to_id']   = $transactions[0]->account->id; | ||||
|  | ||||
|  | ||||
|         return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $what | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index($what) | ||||
|     { | ||||
|         switch ($what) { | ||||
|             case 'expenses': | ||||
|             case 'withdrawal': | ||||
|                 $subTitleIcon = 'fa-long-arrow-left'; | ||||
|                 $subTitle     = 'Expenses'; | ||||
|                 $types        = ['Withdrawal']; | ||||
|                 break; | ||||
|             case 'revenue': | ||||
|             case 'deposit': | ||||
|                 $subTitleIcon = 'fa-long-arrow-right'; | ||||
|                 $subTitle     = 'Revenue, income and deposits'; | ||||
|                 $types        = ['Deposit']; | ||||
|                 break; | ||||
|             case 'transfer': | ||||
|             case 'transfers': | ||||
|                 $subTitleIcon = 'fa-exchange'; | ||||
|                 $subTitle     = 'Transfers'; | ||||
|                 $types        = ['Transfer']; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         $page   = intval(\Input::get('page')); | ||||
|         $offset = $page > 0 ? ($page - 1) * 50 : 0; | ||||
|  | ||||
|         $set      = Auth::user()-> | ||||
|         transactionJournals()-> | ||||
|         transactionTypes($types)-> | ||||
|         withRelevantData()->take(50)->offset($offset) | ||||
|             ->orderBy('date', 'DESC') | ||||
|             ->orderBy('order','ASC') | ||||
|             ->orderBy('id','DESC') | ||||
|             ->get( | ||||
|             ['transaction_journals.*'] | ||||
|         ); | ||||
|         $count    = Auth::user()->transactionJournals()->transactionTypes($types)->count(); | ||||
|         $journals = new LengthAwarePaginator($set, $count, 50, $page); | ||||
|         $journals->setPath('transactions/' . $what); | ||||
|  | ||||
|         return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reorder transactions (which all must have the same date) | ||||
|      */ | ||||
|     public function reorder() | ||||
|     { | ||||
|         $ids = Input::get('items'); | ||||
|         if (count($ids) > 0) { | ||||
|             $order = 0; | ||||
|             foreach ($ids as $id) { | ||||
|                 $journal = Auth::user()->transactionjournals()->where('id', $id)->where('date', Input::get('date'))->first(); | ||||
|                 if($journal) { | ||||
|                     $journal->order = $order; | ||||
|                     $order++; | ||||
|                     $journal->save(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return Response::json(true); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function show(TransactionJournal $journal) | ||||
|     { | ||||
|         $journal->transactions->each( | ||||
|             function (Transaction $t) use ($journal) { | ||||
|                 $t->before = floatval( | ||||
|                     $t->account->transactions()->leftJoin( | ||||
|                         'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                     ) | ||||
|                         ->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d')) | ||||
|                         ->where('transaction_journals.order','>=',$journal->order) | ||||
|                         ->where('transaction_journals.id', '!=', $journal->id) | ||||
|                         ->sum('transactions.amount') | ||||
|                 ); | ||||
|                 $t->after  = $t->before + $t->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return view('transactions.show', compact('journal'))->with( | ||||
|             'subTitle', e($journal->transactiontype->type) . ' "' . e($journal->description) . '"' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param JournalFormRequest         $request | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(JournalFormRequest $request, JournalRepositoryInterface $repository) | ||||
|     { | ||||
|         $journalData = [ | ||||
|             'what'               => $request->get('what'), | ||||
|             'description'        => $request->get('description'), | ||||
|             'account_id'         => intval($request->get('account_id')), | ||||
|             'account_from_id'    => intval($request->get('account_from_id')), | ||||
|             'account_to_id'      => intval($request->get('account_to_id')), | ||||
|             'expense_account'    => $request->get('expense_account'), | ||||
|             'revenue_account'    => $request->get('revenue_account'), | ||||
|             'amount'             => floatval($request->get('amount')), | ||||
|             'user'               => Auth::user()->id, | ||||
|             'amount_currency_id' => intval($request->get('amount_currency_id')), | ||||
|             'date'               => new Carbon($request->get('date')), | ||||
|             'budget_id'          => intval($request->get('budget_id')), | ||||
|             'category'           => $request->get('category'), | ||||
|         ]; | ||||
|  | ||||
|         $journal = $repository->store($journalData); | ||||
|  | ||||
|         event(new JournalSaved($journal)); | ||||
|         event(new JournalCreated($journal, intval($request->get('piggy_bank_id')))); | ||||
|  | ||||
|         if (intval($request->get('reminder_id')) > 0) { | ||||
|             $reminder         = Auth::user()->reminders()->find($request->get('reminder_id')); | ||||
|             $reminder->active = 0; | ||||
|             $reminder->save(); | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'New transaction "' . $journal->description . '" stored!'); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             return Redirect::route('transactions.create', $request->input('what'))->withInput(); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('transactions.index', $request->input('what')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function update(TransactionJournal $journal, JournalFormRequest $request, JournalRepositoryInterface $repository) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         $journalData = [ | ||||
|             'what'               => $request->get('what'), | ||||
|             'description'        => $request->get('description'), | ||||
|             'account_id'         => intval($request->get('account_id')), | ||||
|             'account_from_id'    => intval($request->get('account_from_id')), | ||||
|             'account_to_id'      => intval($request->get('account_to_id')), | ||||
|             'expense_account'    => $request->get('expense_account'), | ||||
|             'revenue_account'    => $request->get('revenue_account'), | ||||
|             'amount'             => floatval($request->get('amount')), | ||||
|             'user'               => Auth::user()->id, | ||||
|             'amount_currency_id' => intval($request->get('amount_currency_id')), | ||||
|             'date'               => new Carbon($request->get('date')), | ||||
|             'budget_id'          => intval($request->get('budget_id')), | ||||
|             'category'           => $request->get('category'), | ||||
|         ]; | ||||
|  | ||||
|         $repository->update($journal, $journalData); | ||||
|  | ||||
|         event(new JournalSaved($journal)); | ||||
|         // update, get events by date and sort DESC | ||||
|  | ||||
|         Session::flash('success', 'Transaction "' . e($journalData['description']) . '" updated.'); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             return Redirect::route('transactions.edit', $journal->id); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return Redirect::route('transactions.index', $journalData['what']); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Http/Kernel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Http/Kernel.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php namespace FireflyIII\Http; | ||||
|  | ||||
| use Illuminate\Foundation\Http\Kernel as HttpKernel; | ||||
|  | ||||
| /** | ||||
|  * Class Kernel | ||||
|  * | ||||
|  * @package FireflyIII\Http | ||||
|  */ | ||||
| class Kernel extends HttpKernel | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The application's global HTTP middleware stack. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $middleware | ||||
|         = [ | ||||
|             'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode', | ||||
|             'Illuminate\Cookie\Middleware\EncryptCookies', | ||||
|             'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse', | ||||
|             'Illuminate\Session\Middleware\StartSession', | ||||
|             'Illuminate\View\Middleware\ShareErrorsFromSession', | ||||
|             'FireflyIII\Http\Middleware\ReplaceTestVars', | ||||
|             'FireflyIII\Http\Middleware\VerifyCsrfToken', | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * The application's route middleware. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $routeMiddleware | ||||
|         = [ | ||||
|             'auth'       => 'FireflyIII\Http\Middleware\Authenticate', | ||||
|             'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth', | ||||
|             'guest'      => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated', | ||||
|             'range'      => 'FireflyIII\Http\Middleware\Range', | ||||
|             'reminders'  => 'FireflyIII\Http\Middleware\Reminders', | ||||
|             'piggybanks' => 'FireflyIII\Http\Middleware\PiggyBanks', | ||||
|  | ||||
|         ]; | ||||
|  | ||||
| } | ||||
							
								
								
									
										53
									
								
								app/Http/Middleware/Authenticate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								app/Http/Middleware/Authenticate.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| <?php namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use Closure; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
|  | ||||
| /** | ||||
|  * Class Authenticate | ||||
|  * | ||||
|  * @package FireflyIII\Http\Middleware | ||||
|  */ | ||||
| class Authenticate | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The Guard implementation. | ||||
|      * | ||||
|      * @var Guard | ||||
|      */ | ||||
|     protected $auth; | ||||
|  | ||||
|     /** | ||||
|      * Create a new filter instance. | ||||
|      * | ||||
|      * @param  Guard $auth | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth) | ||||
|     { | ||||
|         $this->auth = $auth; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $next | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         if ($this->auth->guest()) { | ||||
|             if ($request->ajax()) { | ||||
|                 return response('Unauthorized.', 401); | ||||
|             } else { | ||||
|                 return redirect()->guest('auth/login'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										141
									
								
								app/Http/Middleware/PiggyBanks.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								app/Http/Middleware/PiggyBanks.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Closure; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Session; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBanks | ||||
|  * | ||||
|  * @package FireflyIII\Http\Middleware | ||||
|  */ | ||||
| class PiggyBanks | ||||
| { | ||||
|     /** | ||||
|      * The Guard implementation. | ||||
|      * | ||||
|      * @var Guard | ||||
|      */ | ||||
|     protected $auth; | ||||
|  | ||||
|     /** | ||||
|      * Create a new filter instance. | ||||
|      * | ||||
|      * @param  Guard $auth | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth) | ||||
|     { | ||||
|         $this->auth = $auth; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $next | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         if ($this->auth->check() && !$request->isXmlHttpRequest()) { | ||||
|             // get piggy banks without a repetition: | ||||
|             /** @var Collection $set */ | ||||
|             $set = $this->auth->user()->piggybanks() | ||||
|                               ->leftJoin('piggy_bank_repetitions', 'piggy_banks.id', '=', 'piggy_bank_repetitions.piggy_bank_id') | ||||
|                               ->where('piggy_banks.repeats', 0) | ||||
|                               ->whereNull('piggy_bank_repetitions.id') | ||||
|                               ->get(['piggy_banks.id', 'piggy_banks.startdate', 'piggy_banks.targetdate']); | ||||
|             if ($set->count() > 0) { | ||||
|                 /** @var PiggyBank $partialPiggy */ | ||||
|                 foreach ($set as $partialPiggy) { | ||||
|                     $repetition = new PiggyBankRepetition; | ||||
|                     $repetition->piggyBank()->associate($partialPiggy); | ||||
|                     $repetition->startdate     = is_null($partialPiggy->startdate) ? null : $partialPiggy->startdate; | ||||
|                     $repetition->targetdate    = is_null($partialPiggy->targetdate) ? null : $partialPiggy->targetdate; | ||||
|                     $repetition->currentamount = 0; | ||||
|                     $repetition->save(); | ||||
|                 } | ||||
|             } | ||||
|             unset($partialPiggy, $set, $repetition); | ||||
|  | ||||
|             // get repeating piggy banks without a repetition for current time frame. | ||||
|             /** @var Collection $set */ | ||||
|             $set = $this->auth->user()->piggybanks()->leftJoin( | ||||
|                 'piggy_bank_repetitions', function (JoinClause $join) { | ||||
|                 $join->on('piggy_bank_repetitions.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|                      ->where('piggy_bank_repetitions.targetdate', '>=', Session::get('start')->format('Y-m-d')) | ||||
|                      ->where('piggy_bank_repetitions.startdate', '<=', Session::get('end')->format('Y-m-d')); | ||||
|             } | ||||
|             ) | ||||
|                               ->where('repeats', 1) | ||||
|                               ->whereNull('piggy_bank_repetitions.id') | ||||
|                               ->get(['piggy_banks.*']); | ||||
|  | ||||
|             // these piggy banks are missing a repetition. start looping and create them! | ||||
|             if ($set->count() > 0) { | ||||
|                 /** @var PiggyBank $piggyBank */ | ||||
|                 foreach ($set as $piggyBank) { | ||||
|                     $start = clone $piggyBank->startdate; | ||||
|                     $end   = clone $piggyBank->targetdate; | ||||
|                     $max   = clone $piggyBank->targetdate; | ||||
|                     $index = 0; | ||||
|  | ||||
|                     // first loop: start date to target date. | ||||
|                     // then, continue looping until end is > today | ||||
|                     while ($start <= $max) { | ||||
|                         // first loop fixes this date. or should fix it. | ||||
|                         $max = new Carbon; | ||||
|  | ||||
|                         echo '[#'.$piggyBank->id.', from: '.$start->format('Y-m-d.').' to '.$end->format('Y-m-d.').']'; | ||||
|                         // create stuff. Or at least, try: | ||||
|                         $repetition = $piggyBank->piggyBankRepetitions()->onDates($start, $end)->first(); | ||||
|                         if(!$repetition) { | ||||
|                             $repetition = new PiggyBankRepetition; | ||||
|                             $repetition->piggyBank()->associate($piggyBank); | ||||
|                             $repetition->startdate     = $start; | ||||
|                             $repetition->targetdate    = $end; | ||||
|                             $repetition->currentamount = 0; | ||||
|                             // it might exist, catch: | ||||
|                             $repetition->save(); | ||||
|                         } | ||||
|  | ||||
|                         // start where end 'ended': | ||||
|                         $start = clone $end; | ||||
|                         // move end. | ||||
|                         $end = Navigation::addPeriod($end, $piggyBank->rep_length, 0); | ||||
|  | ||||
|                     } | ||||
|  | ||||
|  | ||||
|                     // first repetition: from original start to original target. | ||||
|                     $repetition = new PiggyBankRepetition; | ||||
|                     $repetition->piggyBank()->associate($piggyBank); | ||||
|                     $repetition->startdate     = is_null($piggyBank->startdate) ? null : $piggyBank->startdate; | ||||
|                     $repetition->targetdate    = is_null($piggyBank->targetdate) ? null : $piggyBank->targetdate; | ||||
|                     $repetition->currentamount = 0; | ||||
|                     // it might exist, catch: | ||||
|                     //$repetition->save(); | ||||
|  | ||||
|                     // then, loop from original target up to now. | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										87
									
								
								app/Http/Middleware/Range.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								app/Http/Middleware/Range.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Closure; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class SessionFilter | ||||
|  * | ||||
|  * @package FireflyIII\Http\Middleware | ||||
|  */ | ||||
| class Range | ||||
| { | ||||
|     /** | ||||
|      * The Guard implementation. | ||||
|      * | ||||
|      * @var Guard | ||||
|      */ | ||||
|     protected $auth; | ||||
|  | ||||
|     /** | ||||
|      * Create a new filter instance. | ||||
|      * | ||||
|      * @param  Guard $auth | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth) | ||||
|     { | ||||
|         $this->auth = $auth; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $theNext | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $theNext) | ||||
|     { | ||||
|         if ($this->auth->check()) { | ||||
|  | ||||
|             // ignore preference. set the range to be the current month: | ||||
|             if (!Session::has('start') && !Session::has('end')) { | ||||
|  | ||||
|                 /** @var \FireflyIII\Models\Preference $viewRange */ | ||||
|                 $viewRange = Preferences::get('viewRange', '1M'); | ||||
|                 $start     = Session::has('start') ? Session::get('start') : new Carbon; | ||||
|                 $start     = Navigation::updateStartDate($viewRange->data, $start); | ||||
|                 $end       = Navigation::updateEndDate($viewRange->data, $start); | ||||
|  | ||||
|                 Session::put('start', $start); | ||||
|                 Session::put('end', $end); | ||||
|             } | ||||
|             if (!Session::has('first')) { | ||||
|                 $journal = $this->auth->user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); | ||||
|                 if ($journal) { | ||||
|                     Session::put('first', $journal->date); | ||||
|                 } else { | ||||
|                     Session::put('first', Carbon::now()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // set current / next / prev month. | ||||
|             $current = Carbon::now()->format('F Y'); | ||||
|             $next    = Carbon::now()->endOfMonth()->addDay()->format('F Y'); | ||||
|             $prev    = Carbon::now()->startOfMonth()->subDay()->format('F Y'); | ||||
|             View::share('currentMonthName', $current); | ||||
|             View::share('previousMonthName', $prev); | ||||
|             View::share('nextMonthName', $next); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $theNext($request); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										50
									
								
								app/Http/Middleware/RedirectIfAuthenticated.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								app/Http/Middleware/RedirectIfAuthenticated.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| <?php namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use Closure; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Http\RedirectResponse; | ||||
|  | ||||
| /** | ||||
|  * Class RedirectIfAuthenticated | ||||
|  * | ||||
|  * @package FireflyIII\Http\Middleware | ||||
|  */ | ||||
| class RedirectIfAuthenticated | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The Guard implementation. | ||||
|      * | ||||
|      * @var Guard | ||||
|      */ | ||||
|     protected $auth; | ||||
|  | ||||
|     /** | ||||
|      * Create a new filter instance. | ||||
|      * | ||||
|      * @param  Guard $auth | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth) | ||||
|     { | ||||
|         $this->auth = $auth; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $next | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         if ($this->auth->check()) { | ||||
|             return new RedirectResponse(url('/')); | ||||
|         } | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										90
									
								
								app/Http/Middleware/Reminders.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								app/Http/Middleware/Reminders.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use App; | ||||
| use Carbon\Carbon; | ||||
| use Closure; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class Reminders | ||||
|  * | ||||
|  * @package FireflyIII\Http\Middleware | ||||
|  */ | ||||
| class Reminders | ||||
| { | ||||
|     /** | ||||
|      * The Guard implementation. | ||||
|      * | ||||
|      * @var Guard | ||||
|      */ | ||||
|     protected $auth; | ||||
|  | ||||
|     /** | ||||
|      * Create a new filter instance. | ||||
|      * | ||||
|      * @param  Guard $auth | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth) | ||||
|     { | ||||
|         $this->auth = $auth; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $next | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         if ($this->auth->check() && !$request->isXmlHttpRequest()) { | ||||
|             // do reminders stuff. | ||||
|             $piggyBanks = $this->auth->user()->piggyBanks()->where('remind_me', 1)->get(); | ||||
|             $today      = new Carbon; | ||||
|             /** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */ | ||||
|             $helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface'); | ||||
|  | ||||
|             /** @var PiggyBank $piggyBank */ | ||||
|             foreach ($piggyBanks as $piggyBank) { | ||||
|                 $ranges = $helper->getReminderRanges($piggyBank); | ||||
|  | ||||
|                 foreach ($ranges as $range) { | ||||
|                     if ($today < $range['end'] && $today > $range['start']) { | ||||
|                         // create a reminder here! | ||||
|                         $helper->createReminder($piggyBank, $range['start'], $range['end']); | ||||
|                         // stop looping, we're done. | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|             // delete invalid reminders | ||||
|             $set = $this->auth->user()->reminders()->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->get( | ||||
|                 ['reminders.id'] | ||||
|             ); | ||||
|             foreach ($set as $reminder) { | ||||
|                 $reminder->delete(); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // get and list active reminders: | ||||
|             $reminders = $this->auth->user()->reminders()->today()->get(); | ||||
|             $reminders->each( | ||||
|                 function (Reminder $reminder) use ($helper) { | ||||
|                     $reminder->description = $helper->getReminderText($reminder); | ||||
|                 } | ||||
|             ); | ||||
|             View::share('reminders', $reminders); | ||||
|         } | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										56
									
								
								app/Http/Middleware/ReplaceTestVars.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/Http/Middleware/ReplaceTestVars.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use Closure; | ||||
| use Illuminate\Contracts\Foundation\Application; | ||||
| use Illuminate\Contracts\Routing\Middleware; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class ReplaceTestVars | ||||
|  * | ||||
|  * @package App\Http\Middleware | ||||
|  */ | ||||
| class ReplaceTestVars implements Middleware | ||||
| { | ||||
|     /** | ||||
|      * The application implementation. | ||||
|      * | ||||
|      * @var Application | ||||
|      */ | ||||
|     protected $app; | ||||
|  | ||||
|     /** | ||||
|      * Create a new filter instance. | ||||
|      * | ||||
|      * @param Application $app | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Application $app) | ||||
|     { | ||||
|         $this->app = $app; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param \Illuminate\Http\Request $request | ||||
|      * @param \Closure                 $next | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         if ('testing' === $this->app->environment() && $request->has('_token')) { | ||||
|             $input           = $request->all(); | ||||
|             $input['_token'] = $request->session()->token(); | ||||
|             // we need to update _token value to make sure we get the POST / PUT tests passed. | ||||
|             Log::debug('Input token replaced ('.$input['_token'].').'); | ||||
|             $request->replace($input); | ||||
|         } | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										27
									
								
								app/Http/Middleware/VerifyCsrfToken.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/Http/Middleware/VerifyCsrfToken.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| <?php namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use Closure; | ||||
| use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; | ||||
|  | ||||
| /** | ||||
|  * Class VerifyCsrfToken | ||||
|  * | ||||
|  * @package FireflyIII\Http\Middleware | ||||
|  */ | ||||
| class VerifyCsrfToken extends BaseVerifier | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Handle an incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $next | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle($request, Closure $next) | ||||
|     { | ||||
|         return parent::handle($request, $next); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										49
									
								
								app/Http/Requests/AccountFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/Http/Requests/AccountFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use FireflyIII\Models\Account; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class AccountFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class AccountFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         $accountRoles = join(',', array_keys(Config::get('firefly.accountRoles'))); | ||||
|         $types        = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier'))); | ||||
|  | ||||
|         $nameRule = 'required|between:1,100|uniqueAccountForUser'; | ||||
|         if (Account::find(Input::get('id'))) { | ||||
|             $nameRule = 'required|between:1,100|belongsToUser:accounts|uniqueForUser:'.Input::get('id'); | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'name'                => $nameRule, | ||||
|             'openingBalance'      => 'numeric', | ||||
|             'openingBalanceDate'  => 'date', | ||||
|             'accountRole'         => 'in:' . $accountRoles, | ||||
|             'active'              => 'boolean', | ||||
|             'balance_currency_id' => 'exists:transaction_currencies,id', | ||||
|             'what'                => 'in:' . $types | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										49
									
								
								app/Http/Requests/BillFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/Http/Requests/BillFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class BillFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class BillFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         $nameRule = 'required|between:1,255|uniqueForUser:bills,name'; | ||||
|         if (intval(Input::get('id')) > 0) { | ||||
|             $nameRule = 'required|between:1,255'; | ||||
|         } | ||||
|  | ||||
|         $rules = [ | ||||
|             'name'               => $nameRule, | ||||
|             'match'              => 'required|between:1,255', | ||||
|             'amount_min'         => 'required|numeric|min:0.01', | ||||
|             'amount_max'         => 'required|numeric|min:0.01', | ||||
|             'amount_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'date'               => 'required|date', | ||||
|             'repeat_freq'        => 'required|in:weekly,monthly,quarterly,half-year,yearly', | ||||
|             'skip'               => 'required|between:0,31', | ||||
|             'automatch'          => 'in:1', | ||||
|             'active'             => 'in:1', | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Http/Requests/BudgetFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Http/Requests/BudgetFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class BudgetFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|  | ||||
|         $nameRule = 'required|between:1,100|uniqueForUser:budgets,name'; | ||||
|         if (Budget::find(Input::get('id'))) { | ||||
|             $nameRule = 'required|between:1,100'; | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'name' => $nameRule, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Http/Requests/CategoryFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Http/Requests/CategoryFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class CategoryFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|  | ||||
|         $nameRule = 'required|between:1,100|uniqueForUser:categories,name'; | ||||
|         if (Category::find(Input::get('id'))) { | ||||
|             $nameRule = 'required|between:1,100'; | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'name' => $nameRule, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Http/Requests/CurrencyFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Http/Requests/CurrencyFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class BillFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class CurrencyFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|  | ||||
|         $rules = [ | ||||
|             'code'   => 'required|min:3|max:3|unique:transaction_currencies,code', | ||||
|             'name'   => 'required|max:48|min:1|unique:transaction_currencies,name', | ||||
|             'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol', | ||||
|         ]; | ||||
|         if (intval(Input::get('id')) > 0) { | ||||
|             $rules = [ | ||||
|                 'code'   => 'required|min:3|max:3', | ||||
|                 'name'   => 'required|max:48|min:1', | ||||
|                 'symbol' => 'required|min:1|max:8', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										73
									
								
								app/Http/Requests/JournalFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								app/Http/Requests/JournalFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
|  * Class JournalFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class JournalFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         // can we switch on the "what"? | ||||
|         $what = Input::get('what'); | ||||
|  | ||||
|         $rules = [ | ||||
|             'description'        => 'required|min:1,max:255', | ||||
|             'what'               => 'required|in:withdrawal,deposit,transfer|exists:transaction_types,type', | ||||
|             'amount'             => 'numeric|required|min:0.01', | ||||
|             'date'               => 'required|date', | ||||
|             'reminder_id'        => 'numeric|exists:reminders,id', | ||||
|             'amount_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|         switch ($what) { | ||||
|             case 'withdrawal': | ||||
|                 $rules['account_id']      = 'required|exists:accounts,id|belongsToUser:accounts'; | ||||
|                 $rules['expense_account'] = 'between:1,255'; | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
|                 if (intval(Input::get('budget_id')) != 0) { | ||||
|                     $rules['budget_id'] = 'exists:budgets,id|belongsToUser:budgets'; | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 break; | ||||
|             case 'deposit': | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
|                 $rules['account_id']      = 'required|exists:accounts,id|belongsToUser:accounts'; | ||||
|                 $rules['revenue_account'] = 'between:1,255'; | ||||
|                 break; | ||||
|             case 'transfer': | ||||
|                 $rules['account_from_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:account_to_id'; | ||||
|                 $rules['account_to_id']   = 'required|exists:accounts,id|belongsToUser:accounts|different:account_from_id'; | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
|                 break; | ||||
|             default: | ||||
|                 die('Cannot handle ' . $what); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										69
									
								
								app/Http/Requests/PiggyBankFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								app/Http/Requests/PiggyBankFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Input; | ||||
| use Navigation; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class PiggyBankFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|  | ||||
|         $nameRule       = 'required|between:1,255|uniquePiggyBankForUser:piggy_banks,name'; | ||||
|         $targetDateRule = 'date'; | ||||
|         if (intval(Input::get('id'))) { | ||||
|             $nameRule = 'required|between:1,255'; | ||||
|         } | ||||
|  | ||||
|         if (intval(Input::get('repeats')) == 1) { | ||||
|             $targetDateRule = 'required|date|after:' . date('Y-m-d'); | ||||
|             // switch on rep_every, make sure it's not too far away. | ||||
|             if (!is_null(Input::get('rep_length'))) { | ||||
|                 $end = Navigation::addPeriod(new Carbon, Input::get('rep_length'), 0); | ||||
|                 $targetDateRule .= '|before:' . $end->format('Y-m-d'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $rules = [ | ||||
|             'repeats'            => 'required|boolean', | ||||
|             'name'               => $nameRule, | ||||
|             'account_id'         => 'required|belongsToUser:accounts', | ||||
|             'targetamount'       => 'required|min:0.01', | ||||
|             'amount_currency_id' => 'exists:transaction_currencies,id', | ||||
|             'startdate'          => 'date', | ||||
|             'targetdate'         => $targetDateRule, | ||||
|             'rep_length'         => 'in:day,week,quarter,month,year', | ||||
|             'rep_every'          => 'integer|min:0|max:31', | ||||
|             'rep_times'          => 'integer|min:0|max:99', | ||||
|             'reminder'           => 'in:day,week,quarter,month,year', | ||||
|             'reminder_skip'      => 'integer|min:0|max:99', | ||||
|             'remind_me'          => 'boolean|piggyBankReminder', | ||||
|             'order'              => 'integer|min:1', | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Http/Requests/ProfileFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Http/Requests/ProfileFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class ProfileFormRequest | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class ProfileFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         return [ | ||||
|             'current_password'               => 'required', | ||||
|             'new_password'              => 'required|confirmed', | ||||
|             'new_password_confirmation' => 'required', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										15
									
								
								app/Http/Requests/Request.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/Http/Requests/Request.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| <?php namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class Request | ||||
|  * | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| abstract class Request extends FormRequest | ||||
| { | ||||
|  | ||||
|     // | ||||
|  | ||||
| } | ||||
							
								
								
									
										352
									
								
								app/Http/breadcrumbs.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								app/Http/breadcrumbs.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,352 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use DaveJamesMiller\Breadcrumbs\Generator; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
|  | ||||
| /* | ||||
|  * Back home. | ||||
|  */ | ||||
| Breadcrumbs::register( | ||||
|     'home', | ||||
|     function (Generator $breadcrumbs) { | ||||
|  | ||||
|         $breadcrumbs->push('Home', route('index')); | ||||
|     } | ||||
| ); | ||||
|  | ||||
| // accounts | ||||
| Breadcrumbs::register( | ||||
|     'accounts.index', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'accounts.show', function (Generator $breadcrumbs, Account $account) { | ||||
|     switch ($account->accountType->type) { | ||||
|         default: | ||||
|             throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"'); | ||||
|             break; | ||||
|         case 'Default account': | ||||
|         case 'Asset account': | ||||
|             $what = 'asset'; | ||||
|             break; | ||||
|         case 'Cash account': | ||||
|             $what = 'cash'; | ||||
|             break; | ||||
|         case 'Expense account': | ||||
|         case 'Beneficiary account': | ||||
|             $what = 'expense'; | ||||
|             break; | ||||
|         case 'Revenue account': | ||||
|             $what = 'revenue'; | ||||
|             break; | ||||
|     } | ||||
|     $breadcrumbs->parent('accounts.index', $what); | ||||
|     $breadcrumbs->push(e($account->name), route('accounts.show', $account->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'accounts.delete', function (Generator $breadcrumbs, Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.edit', function (Generator $breadcrumbs, Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // budgets. | ||||
| Breadcrumbs::register( | ||||
|     'budgets.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Budgets', route('budgets.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push('Create new budget', route('budgets.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.edit', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.delete', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push(e($budget->name), route('budgets.show', $budget->id)); | ||||
|     if (!is_null($repetition) && !is_null($repetition->id)) { | ||||
|         $breadcrumbs->push( | ||||
|             Navigation::periodShow($repetition->startdate, $repetition->budgetlimit->repeat_freq), route('budgets.show', $budget->id, $repetition->id) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| ); | ||||
|  | ||||
| // categories | ||||
| Breadcrumbs::register( | ||||
|     'categories.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Categories', route('categories.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push('Create new category', route('categories.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.edit', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.delete', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.show', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push(e($category->name), route('categories.show', $category->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
|  | ||||
| // piggy banks | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Piggy banks', route('piggy-banks.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('piggy-banks.index'); | ||||
|     $breadcrumbs->push('Create new piggy bank', route('piggy-banks.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.show', $piggyBank); | ||||
|     $breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggy-banks.edit', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.show', $piggyBank); | ||||
|     $breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggy-banks.delete', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.index'); | ||||
|     $breadcrumbs->push(e($piggyBank->name), route('piggy-banks.show', $piggyBank->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // preferences | ||||
| Breadcrumbs::register( | ||||
|     'preferences', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Preferences', route('preferences')); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // profile | ||||
| Breadcrumbs::register( | ||||
|     'profile', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Profile', route('profile')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'change-password', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push('Change your password', route('change-password')); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // bills | ||||
| Breadcrumbs::register( | ||||
|     'bills.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Bills', route('bills.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push('Create new bill', route('bills.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.edit', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.delete', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.show', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push(e($bill->name), route('bills.show', $bill->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // reminders | ||||
| Breadcrumbs::register( | ||||
|     'reminders.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Reminders', route('reminders.index')); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // reminders | ||||
| Breadcrumbs::register( | ||||
|     'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) { | ||||
|     $breadcrumbs->parent('reminders.index'); | ||||
|     $breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
|  | ||||
| // reports | ||||
| Breadcrumbs::register( | ||||
|     'reports.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Reports', route('reports.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.year', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push($date->format('Y'), route('reports.year', $date->format('Y'))); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.month', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.budget', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // search | ||||
| Breadcrumbs::register( | ||||
|     'search', function (Generator $breadcrumbs, $query) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Search for "' . e($query) . '"', route('search')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // transactions | ||||
| Breadcrumbs::register( | ||||
|     'transactions.index', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|  | ||||
|     switch ($what) { | ||||
|         case 'expenses': | ||||
|         case 'withdrawal': | ||||
|             $subTitle = 'Expenses'; | ||||
|             break; | ||||
|         case 'revenue': | ||||
|         case 'deposit': | ||||
|             $subTitle = 'Revenue, income and deposits'; | ||||
|             break; | ||||
|         case 'transfer': | ||||
|         case 'transfers': | ||||
|             $subTitle = 'Transfers'; | ||||
|             break; | ||||
|         case 'opening balance': | ||||
|             $subTitle = 'Opening balances'; | ||||
|             break; | ||||
|         default: | ||||
|             throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs'); | ||||
|     } | ||||
|  | ||||
|     $breadcrumbs->push($subTitle, route('transactions.index', $what)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.create', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('transactions.index', $what); | ||||
|     $breadcrumbs->push('Create new ' . e($what), route('transactions.create', $what)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|  | ||||
|     $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type)); | ||||
|     $breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
							
								
								
									
										353
									
								
								app/Http/routes.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								app/Http/routes.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,353 @@ | ||||
| <?php | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
|  | ||||
|  | ||||
| // models | ||||
| Route::bind( | ||||
|     'account', | ||||
|     function ($value, $route) { | ||||
|         if (Auth::check()) { | ||||
|             $account = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') | ||||
|                               ->where('account_types.editable', 1) | ||||
|                               ->where('accounts.id', $value) | ||||
|                               ->where('user_id', Auth::user()->id) | ||||
|                               ->first(['accounts.*']); | ||||
|             if ($account) { | ||||
|                 return $account; | ||||
|             } | ||||
|         } | ||||
|         App::abort(404); | ||||
|     } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'tjSecond', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return TransactionJournal:: | ||||
|         where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'tj', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return TransactionJournal:: | ||||
|         where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'currency', function ($value, $route) { | ||||
|     return TransactionCurrency::find($value); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'bill', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return Bill::where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'budget', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return Budget::where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'reminder', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'limitrepetition', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return LimitRepetition::where('limit_repetitions.id', $value) | ||||
|                               ->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id') | ||||
|                               ->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') | ||||
|                               ->where('budgets.user_id', Auth::user()->id) | ||||
|                               ->first(['limit_repetitions.*']); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'piggyBank', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return PiggyBank:: | ||||
|         where('piggy_banks.id', $value) | ||||
|                         ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') | ||||
|                         ->where('accounts.user_id', Auth::user()->id) | ||||
|                         ->where('repeats', 0)->first(['piggy_banks.*']); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'category', function ($value, $route) { | ||||
|     if (Auth::check()) { | ||||
|         return Category::where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
| } | ||||
| ); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Auth\AuthController | ||||
|  */ | ||||
| Route::get('/register', ['uses' => 'Auth\AuthController@getRegister', 'as' => 'register']); | ||||
|  | ||||
| Route::controllers( | ||||
|     [ | ||||
|         'auth' => 'Auth\AuthController', | ||||
|         'password' => 'Auth\PasswordController', | ||||
|     ] | ||||
| ); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Home Controller | ||||
|  */ | ||||
| Route::group( | ||||
|     ['middleware' => ['auth', 'range', 'reminders','piggybanks']], function () { | ||||
|     Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']); | ||||
|     Route::get('/home', ['uses' => 'HomeController@index', 'as' => 'home']); | ||||
|     Route::post('/daterange', ['uses' => 'HomeController@dateRange', 'as' => 'daterange']); | ||||
|     Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']); | ||||
|     /** | ||||
|      * Account Controller | ||||
|      */ | ||||
|     Route::get('/accounts/{what}', ['uses' => 'AccountController@index', 'as' => 'accounts.index'])->where('what', 'revenue|asset|expense'); | ||||
|     Route::get('/accounts/create/{what}', ['uses' => 'AccountController@create', 'as' => 'accounts.create'])->where('what', 'revenue|asset|expense'); | ||||
|     Route::get('/accounts/edit/{account}', ['uses' => 'AccountController@edit', 'as' => 'accounts.edit']); | ||||
|     Route::get('/accounts/delete/{account}', ['uses' => 'AccountController@delete', 'as' => 'accounts.delete']); | ||||
|     Route::get('/accounts/show/{account}/{view?}', ['uses' => 'AccountController@show', 'as' => 'accounts.show']); | ||||
|  | ||||
|     Route::post('/accounts/store', ['uses' => 'AccountController@store', 'as' => 'accounts.store']); | ||||
|     Route::post('/accounts/update/{account}', ['uses' => 'AccountController@update', 'as' => 'accounts.update']); | ||||
|     Route::post('/accounts/destroy/{account}', ['uses' => 'AccountController@destroy', 'as' => 'accounts.destroy']); | ||||
|  | ||||
|     /** | ||||
|      * Bills Controller | ||||
|      */ | ||||
|     Route::get('/bills', ['uses' => 'BillController@index', 'as' => 'bills.index']); | ||||
|     Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching. | ||||
|     Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']); | ||||
|     Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']); | ||||
|     Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']); | ||||
|     Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']); | ||||
|  | ||||
|     Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']); | ||||
|     Route::post('/bills/update/{bill}', ['uses' => 'BillController@update', 'as' => 'bills.update']); | ||||
|     Route::post('/bills/destroy/{bill}', ['uses' => 'BillController@destroy', 'as' => 'bills.destroy']); | ||||
|  | ||||
|     /** | ||||
|      * Budget Controller | ||||
|      */ | ||||
|     Route::get('/budgets', ['uses' => 'BudgetController@index', 'as' => 'budgets.index']); | ||||
|     Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']); # extra. | ||||
|     Route::get('/budgets/create', ['uses' => 'BudgetController@create', 'as' => 'budgets.create']); | ||||
|     Route::get('/budgets/edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']); | ||||
|     Route::get('/budgets/delete/{budget}', ['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']); | ||||
|     Route::get('/budgets/show/{budget}/{limitrepetition?}', ['uses' => 'BudgetController@show', 'as' => 'budgets.show']); | ||||
|     Route::get('/budgets/list/noBudget', ['uses' => 'BudgetController@noBudget', 'as' => 'budgets.noBudget']); | ||||
|     Route::post('/budgets/income', ['uses' => 'BudgetController@postUpdateIncome', 'as' => 'budgets.postIncome']); | ||||
|     Route::post('/budgets/store', ['uses' => 'BudgetController@store', 'as' => 'budgets.store']); | ||||
|     Route::post('/budgets/update/{budget}', ['uses' => 'BudgetController@update', 'as' => 'budgets.update']); | ||||
|     Route::post('/budgets/destroy/{budget}', ['uses' => 'BudgetController@destroy', 'as' => 'budgets.destroy']); | ||||
|     Route::post('budgets/amount/{budget}', ['uses' => 'BudgetController@amount']); | ||||
|  | ||||
|     /** | ||||
|      * Category Controller | ||||
|      */ | ||||
|     Route::get('/categories', ['uses' => 'CategoryController@index', 'as' => 'categories.index']); | ||||
|     Route::get('/categories/create', ['uses' => 'CategoryController@create', 'as' => 'categories.create']); | ||||
|     Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']); | ||||
|     Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']); | ||||
|     Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']); | ||||
|     Route::get('/categories/list/noCategory', ['uses' => 'CategoryController@noCategory', 'as' => 'categories.noCategory']); | ||||
|     Route::post('/categories/store', ['uses' => 'CategoryController@store', 'as' => 'categories.store']); | ||||
|     Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']); | ||||
|     Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']); | ||||
|  | ||||
|     /** | ||||
|      * Currency Controller | ||||
|      */ | ||||
|     Route::get('/currency', ['uses' => 'CurrencyController@index', 'as' => 'currency.index']); | ||||
|     Route::get('/currency/create', ['uses' => 'CurrencyController@create', 'as' => 'currency.create']); | ||||
|     Route::get('/currency/edit/{currency}', ['uses' => 'CurrencyController@edit', 'as' => 'currency.edit']); | ||||
|     Route::get('/currency/delete/{currency}', ['uses' => 'CurrencyController@delete', 'as' => 'currency.delete']); | ||||
|     Route::get('/currency/default/{currency}', ['uses' => 'CurrencyController@defaultCurrency', 'as' => 'currency.default']); | ||||
|     Route::post('/currency/store', ['uses' => 'CurrencyController@store', 'as' => 'currency.store']); | ||||
|     Route::post('/currency/update/{currency}', ['uses' => 'CurrencyController@update', 'as' => 'currency.update']); | ||||
|     Route::post('/currency/destroy/{currency}', ['uses' => 'CurrencyController@destroy', 'as' => 'currency.destroy']); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Google Chart Controller | ||||
|      */ | ||||
|     Route::get('/chart/home/account', ['uses' => 'GoogleChartController@allAccountsBalanceChart']); | ||||
|     Route::get('/chart/home/budgets', ['uses' => 'GoogleChartController@allBudgetsHomeChart']); | ||||
|     Route::get('/chart/home/categories', ['uses' => 'GoogleChartController@allCategoriesHomeChart']); | ||||
|     Route::get('/chart/home/bills', ['uses' => 'GoogleChartController@billsOverview']); | ||||
|     Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']); | ||||
|     Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']); | ||||
|     Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending']); | ||||
|     Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']); | ||||
|     Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']); | ||||
|     Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']); | ||||
|     Route::get('/chart/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']); | ||||
|     Route::get('/chart/piggy-history/{piggyBank}', ['uses' => 'GoogleChartController@piggyBankHistory']); | ||||
|     Route::get('/chart/category/{category}/period', ['uses' => 'GoogleChartController@categoryPeriodChart']); | ||||
|     Route::get('/chart/category/{category}/overview', ['uses' => 'GoogleChartController@categoryOverviewChart']); | ||||
|  | ||||
|     /** | ||||
|      * Help Controller | ||||
|      */ | ||||
|     Route::get('/help/{route}', ['uses' => 'HelpController@show', 'as' => 'help.show']); | ||||
|  | ||||
|     /** | ||||
|      * JSON Controller | ||||
|      */ | ||||
|     Route::get('/json/expense-accounts', ['uses' => 'JsonController@expenseAccounts', 'as' => 'json.expense-accounts']); | ||||
|     Route::get('/json/revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'json.revenue-accounts']); | ||||
|     Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']); | ||||
|     Route::get('/json/box', ['uses' => 'JsonController@box', 'as' => 'json.box']); | ||||
|     Route::get('/json/show-shared-reports', 'JsonController@showSharedReports'); | ||||
|     Route::get('/json/transaction-journals/{what}', 'JsonController@transactionJournals'); | ||||
|     Route::get('/json/show-shared-reports/set', 'JsonController@setSharedReports'); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Piggy Bank Controller | ||||
|      */ | ||||
|     Route::get('/piggy-banks', ['uses' => 'PiggyBankController@index', 'as' => 'piggy-banks.index']); | ||||
|     Route::get('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add', 'as' => 'piggy-banks.addMoney']); # add money | ||||
|     Route::get('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@remove', 'as' => 'piggy-banks.removeMoney']); #remove money | ||||
|     Route::get('/piggy-banks/create', ['uses' => 'PiggyBankController@create', 'as' => 'piggy-banks.create']); | ||||
|     Route::get('/piggy-banks/edit/{piggyBank}', ['uses' => 'PiggyBankController@edit', 'as' => 'piggy-banks.edit']); | ||||
|     Route::get('/piggy-banks/delete/{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'piggy-banks.delete']); | ||||
|     Route::get('/piggy-banks/show/{piggyBank}', ['uses' => 'PiggyBankController@show', 'as' => 'piggy-banks.show']); | ||||
|     Route::post('/piggy-banks/store', ['uses' => 'PiggyBankController@store', 'as' => 'piggy-banks.store']); | ||||
|     Route::post('/piggy-banks/update/{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'piggy-banks.update']); | ||||
|     Route::post('/piggy-banks/destroy/{piggyBank}', ['uses' => 'PiggyBankController@destroy', 'as' => 'piggy-banks.destroy']); | ||||
|     Route::post('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'piggy-banks.add']); # add money | ||||
|     Route::post('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'piggy-banks.remove']); # remove money. | ||||
|     Route::post('/piggy-banks/sort', ['uses' => 'PiggyBankController@order', 'as' => 'piggy-banks.order']); | ||||
|  | ||||
|     /** | ||||
|      * Preferences Controller | ||||
|      */ | ||||
|     Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']); | ||||
|     Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']); | ||||
|  | ||||
|     /** | ||||
|      * Profile Controller | ||||
|      */ | ||||
|     Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']); | ||||
|     Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'change-password']); | ||||
|     Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']); | ||||
|  | ||||
|     /** | ||||
|      * Related transactions controller | ||||
|      */ | ||||
|     Route::get('/related/alreadyRelated/{tj}', ['uses' => 'RelatedController@alreadyRelated', 'as' => 'related.alreadyRelated']); | ||||
|     Route::post('/related/relate/{tj}/{tjSecond}', ['uses' => 'RelatedController@relate', 'as' => 'related.relate']); | ||||
|     Route::post('/related/removeRelation/{tj}/{tjSecond}', ['uses' => 'RelatedController@removeRelation', 'as' => 'related.removeRelation']); | ||||
|     Route::get('/related/remove/{tj}/{tjSecond}', ['uses' => 'RelatedController@getRemoveRelation', 'as' => 'related.getRemoveRelation']); | ||||
|     Route::get('/related/related/{tj}', ['uses' => 'RelatedController@related', 'as' => 'related.related']); | ||||
|     Route::post('/related/search/{tj}', ['uses' => 'RelatedController@search', 'as' => 'related.search']); | ||||
|  | ||||
|     /** | ||||
|      * Reminder Controller | ||||
|      */ | ||||
|     Route::get('/reminders', ['uses' => 'ReminderController@index', 'as' => 'reminders.index']); | ||||
|     Route::get('/reminder/dismiss/{reminder}', ['uses' => 'ReminderController@dismiss', 'as' => 'reminders.dismiss']); | ||||
|     Route::get('/reminder/act/{reminder}', ['uses' => 'ReminderController@act', 'as' => 'reminders.act']); | ||||
|     Route::get('/reminder/{reminder}', ['uses' => 'ReminderController@show', 'as' => 'reminders.show']); | ||||
|  | ||||
|     /** | ||||
|      * Report Controller | ||||
|      */ | ||||
|     Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']); | ||||
|     Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year']); | ||||
|     Route::get('/reports/{year}/{month}', ['uses' => 'ReportController@month', 'as' => 'reports.month']); | ||||
|     Route::get('/reports/budget/{year}/{month}', ['uses' => 'ReportController@budget', 'as' => 'reports.budget']); | ||||
|  | ||||
|     // pop ups for budget report: | ||||
|     Route::get('/reports/modal/{account}/{year}/{month}/no-budget', ['uses' => 'ReportController@modalNoBudget', 'as' => 'reports.no-budget']); | ||||
|     Route::get( | ||||
|         '/reports/modal/{account}/{year}/{month}/balanced-transfers', | ||||
|         ['uses' => 'ReportController@modalBalancedTransfers', 'as' => 'reports.balanced-transfers'] | ||||
|     ); | ||||
|     Route::get( | ||||
|         '/reports/modal/{account}/{year}/{month}/left-unbalanced', ['uses' => 'ReportController@modalLeftUnbalanced', 'as' => 'reports.left-unbalanced'] | ||||
|     ); | ||||
|  | ||||
|     /** | ||||
|      * Search Controller | ||||
|      */ | ||||
|     Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']); | ||||
|  | ||||
|     /** | ||||
|      * Transaction Controller | ||||
|      */ | ||||
|     Route::get('/transactions/{what}', ['uses' => 'TransactionController@index', 'as' => 'transactions.index'])->where( | ||||
|         ['what' => 'expenses|revenue|withdrawal|deposit|transfer|transfers'] | ||||
|     ); | ||||
|     Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where( | ||||
|         ['what' => 'expenses|revenue|withdrawal|deposit|transfer|transfers'] | ||||
|     ); | ||||
|     Route::get('/transaction/edit/{tj}', ['uses' => 'TransactionController@edit', 'as' => 'transactions.edit']); | ||||
|     Route::get('/transaction/delete/{tj}', ['uses' => 'TransactionController@delete', 'as' => 'transactions.delete']); | ||||
|     Route::get('/transaction/show/{tj}', ['uses' => 'TransactionController@show', 'as' => 'transactions.show']); | ||||
|     // transaction controller: | ||||
|     Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store'])->where( | ||||
|         ['what' => 'expenses|revenue|withdrawal|deposit|transfer|transfers'] | ||||
|     ); | ||||
|     Route::post('/transaction/update/{tj}', ['uses' => 'TransactionController@update', 'as' => 'transactions.update']); | ||||
|     Route::post('/transaction/destroy/{tj}', ['uses' => 'TransactionController@destroy', 'as' => 'transactions.destroy']); | ||||
|     Route::post('/transaction/reorder', ['uses' => 'TransactionController@reorder', 'as' => 'transactions.reorder']); | ||||
|  | ||||
|     /** | ||||
|      * Auth\Auth Controller | ||||
|      */ | ||||
|     Route::get('/logout', ['uses' => 'Auth\AuthController@getLogout', 'as' => 'logout']); | ||||
|  | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
							
								
								
									
										121
									
								
								app/Models/Account.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								app/Models/Account.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
| use Crypt; | ||||
| /** | ||||
|  * Class Account | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Account extends Model | ||||
| { | ||||
|     use SoftDeletes, ValidatingTrait; | ||||
|  | ||||
|     protected $rules | ||||
|         = [ | ||||
|             'user_id'         => 'required|exists:users,id', | ||||
|             'account_type_id' => 'required|exists:account_types,id', | ||||
|             'name'            => 'required|between:1,1024|uniqueAccountForUser', | ||||
|             'active'          => 'required|boolean' | ||||
|         ]; | ||||
|  | ||||
|     protected $fillable = ['user_id', 'account_type_id', 'name', 'active']; | ||||
|  | ||||
|     /** | ||||
|      * @param $fieldName | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getMeta($fieldName) | ||||
|     { | ||||
|         foreach ($this->accountMeta as $meta) { | ||||
|             if ($meta->name == $fieldName) { | ||||
|                 return $meta->data; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getNameAttribute($value) | ||||
|     { | ||||
|         if ($this->encrypted) { | ||||
|             return Crypt::decrypt($value); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreStart | ||||
|         return $value; | ||||
|         // @codeCoverageIgnoreEnd | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function accountMeta() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\AccountMeta'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function accountType() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\AccountType'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param array           $types | ||||
|      */ | ||||
|     public function scopeAccountTypeIn(EloquentBuilder $query, array $types) | ||||
|     { | ||||
|         if (is_null($this->joinedAccountTypes)) { | ||||
|             $query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id'); | ||||
|             $this->joinedAccountTypes = true; | ||||
|         } | ||||
|         $query->whereIn('account_types.type', $types); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function transactions() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\Transaction'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function piggyBanks() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\PiggyBank'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										59
									
								
								app/Models/AccountMeta.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								app/Models/AccountMeta.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class AccountMeta | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class AccountMeta extends Model | ||||
| { | ||||
|  | ||||
|     use ValidatingTrait; | ||||
|     protected $fillable = ['account_id', 'name', 'data']; | ||||
|     protected $rules | ||||
|                      = [ | ||||
|             'account_id' => 'required|exists:accounts,id', | ||||
|             'name'       => 'required|between:1,100', | ||||
|             'data'       => 'required' | ||||
|         ]; | ||||
|     protected $table = 'account_meta'; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function account() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\Account'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getDataAttribute($value) | ||||
|     { | ||||
|         return json_decode($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setDataAttribute($value) | ||||
|     { | ||||
|         $this->attributes['data'] = json_encode($value); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Models/AccountType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Models/AccountType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class AccountType | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class AccountType extends Model | ||||
| { | ||||
|  | ||||
|     // | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function accounts() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\Account'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at']; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Models/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Models/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Bill extends Model | ||||
| { | ||||
|  | ||||
|     protected $fillable = ['name', 'match', 'amount_min','user_id', 'amount_max', 'date', 'repeat_freq', 'skip', 'automatch', 'active',]; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'date']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function transactionjournals() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\TransactionJournal'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										59
									
								
								app/Models/Budget.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								app/Models/Budget.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Budget | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Budget extends Model | ||||
| { | ||||
|  | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     protected $fillable = ['user_id', 'name']; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function budgetlimits() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\BudgetLimit'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough | ||||
|      */ | ||||
|     public function limitrepetitions() | ||||
|     { | ||||
|         return $this->hasManyThrough('FireflyIII\Models\LimitRepetition', 'FireflyIII\Models\BudgetLimit', 'budget_id'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function transactionjournals() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'budget_transaction_journal', 'budget_id'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										37
									
								
								app/Models/BudgetLimit.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Models/BudgetLimit.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimit | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class BudgetLimit extends Model | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function budget() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\Budget'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'startdate']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function limitrepetitions() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\LimitRepetition'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										41
									
								
								app/Models/Category.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Models/Category.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Category | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Category extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     protected $fillable = ['user_id', 'name']; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function transactionjournals() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'category_transaction_journal', 'category_id'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										24
									
								
								app/Models/Component.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Models/Component.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Component | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Component extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     protected $fillable = ['user_id', 'name','class']; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Models/LimitRepetition.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Models/LimitRepetition.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class LimitRepetition | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class LimitRepetition extends Model | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function budgetLimit() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\BudgetLimit'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'startdate', 'enddate']; | ||||
|     } | ||||
|  | ||||
|     public function spentInRepetition() | ||||
|     { | ||||
|         $sum = \DB::table('transactions') | ||||
|                   ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                   ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                   ->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id') | ||||
|                   ->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                   ->where('transaction_journals.date', '>=', $this->startdate->format('Y-m-d')) | ||||
|                   ->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d')) | ||||
|                   ->where('transactions.amount', '>', 0) | ||||
|                   ->where('limit_repetitions.id', '=', $this->id) | ||||
|                   ->sum('transactions.amount'); | ||||
|  | ||||
|         return floatval($sum); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										95
									
								
								app/Models/PiggyBank.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								app/Models/PiggyBank.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use App; | ||||
| use Log; | ||||
| /** | ||||
|  * Class PiggyBank | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class PiggyBank extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     protected $fillable | ||||
|         = ['repeats', 'name', 'account_id', 'rep_every', 'rep_times', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me', | ||||
|            'rep_length']; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function account() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\Account'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Grabs the PiggyBankRepetition that's currently relevant / active | ||||
|      * | ||||
|      * @returns PiggyBankRepetition | ||||
|      */ | ||||
|     public function currentRelevantRep() | ||||
|     { | ||||
|         if (!is_null($this->currentRep)) { | ||||
|             return $this->currentRep; | ||||
|         } | ||||
|         // repeating piggy banks are no longer supported. | ||||
|         if (intval($this->repeats) === 0) { | ||||
|             $rep              = $this->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']); | ||||
|             $this->currentRep = $rep; | ||||
|  | ||||
|             return $rep; | ||||
|         } else { | ||||
|             Log::error('Tried to work with a piggy bank with a repeats=1 value! (id is '.$this->id.')'); | ||||
|             //App::abort(500); | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function piggyBankRepetitions() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\PiggyBankRepetition'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getRemindMeAttribute($value) | ||||
|     { | ||||
|         return intval($value) == 1; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function piggyBankEvents() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\PiggyBankEvent'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\MorphMany | ||||
|      */ | ||||
|     public function reminders() | ||||
|     { | ||||
|         return $this->morphMany('FireflyIII\Models\Reminder', 'remindersable'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								app/Models/PiggyBankEvent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/Models/PiggyBankEvent.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankEvent | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class PiggyBankEvent extends Model | ||||
| { | ||||
|  | ||||
|     protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'amount']; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'date']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function piggyBank() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\PiggyBank'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function transactionJournal() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\TransactionJournal'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										63
									
								
								app/Models/PiggyBankRepetition.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								app/Models/PiggyBankRepetition.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Carbon\Carbon; | ||||
| /** | ||||
|  * Class PiggyBankRepetition | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class PiggyBankRepetition extends Model | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'startdate', 'targetdate']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function piggyBank() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\PiggyBank'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function scopeRelevantOnDate(EloquentBuilder $query, Carbon $date) | ||||
|     { | ||||
|         return $query->where( | ||||
|             function($q) use ($date) { | ||||
|                 $q->where('startdate', '<=', $date->format('Y-m-d 00:00:00')); | ||||
|                 $q->orWhereNull('startdate'); | ||||
|             }) | ||||
|  | ||||
|             ->where(function($q) use ($date) { | ||||
|  | ||||
|                 $q->where('targetdate', '>=', $date->format('Y-m-d 00:00:00')); | ||||
|                 $q->orWhereNull('targetdate'); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $start | ||||
|      * @param Carbon          $target | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $target) | ||||
|     { | ||||
|         return $query->where('startdate',$start->format('Y-m-d'))->where('targetdate',$target->format('Y-m-d')); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										49
									
								
								app/Models/Preference.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/Models/Preference.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class Preference | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Preference extends Model | ||||
| { | ||||
|  | ||||
|     protected $fillable = ['user_id', 'data', 'name']; | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getDataAttribute($value) | ||||
|     { | ||||
|         return json_decode($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setDataAttribute($value) | ||||
|     { | ||||
|         $this->attributes['data'] = json_encode($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										100
									
								
								app/Models/Reminder.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								app/Models/Reminder.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class Reminder | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Reminder extends Model | ||||
| { | ||||
|  | ||||
|  | ||||
|     protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type',]; | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getActiveAttribute($value) | ||||
|     { | ||||
|         return intval($value) == 1; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'startdate', 'enddate']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getMetadataAttribute($value) | ||||
|     { | ||||
|         return json_decode($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function getNotnowAttribute($value) | ||||
|     { | ||||
|         return intval($value) == 1; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\MorphTo | ||||
|      */ | ||||
|     public function remindersable() | ||||
|     { | ||||
|         return $this->morphTo(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $start | ||||
|      * @param Carbon          $end | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00')); | ||||
|     } | ||||
|  | ||||
|     public function scopeToday(EloquentBuilder $query) | ||||
|     { | ||||
|         $today = new Carbon; | ||||
|  | ||||
|         return $query->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))->where('active', 1) | ||||
|                      ->where('notnow', 0); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setMetadataAttribute($value) | ||||
|     { | ||||
|         $this->attributes['metadata'] = json_encode($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										48
									
								
								app/Models/Transaction.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/Models/Transaction.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class Transaction | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class Transaction extends Model | ||||
| { | ||||
|  | ||||
|     protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount']; | ||||
|     protected $rules | ||||
|                         = [ | ||||
|             'account_id'             => 'required|exists:accounts,id', | ||||
|             'transaction_journal_id' => 'required|exists:transaction_journals,id', | ||||
|             'description'            => 'between:1,255', | ||||
|             'amount'                 => 'required|numeric' | ||||
|         ]; | ||||
|     use SoftDeletes, ValidatingTrait; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function account() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\Account'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function transactionJournal() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\TransactionJournal'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										33
									
								
								app/Models/TransactionCurrency.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/Models/TransactionCurrency.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionCurrency | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class TransactionCurrency extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|  | ||||
|     protected $fillable = ['name', 'code', 'symbol']; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function transactionJournals() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\TransactionJournal'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								app/Models/TransactionGroup.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/Models/TransactionGroup.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionGroup | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class TransactionGroup extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function transactionjournals() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\TransactionJournal'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										231
									
								
								app/Models/TransactionJournal.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								app/Models/TransactionJournal.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionJournal | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class TransactionJournal extends Model | ||||
| { | ||||
|     use SoftDeletes, ValidatingTrait; | ||||
|  | ||||
|     protected $fillable = ['user_id', 'transaction_type_id', 'bill_id', 'transaction_currency_id', 'description', 'completed', 'date', 'encrypted']; | ||||
|  | ||||
|     protected $rules | ||||
|         = [ | ||||
|             'user_id'                 => 'required|exists:users,id', | ||||
|             'transaction_type_id'     => 'required|exists:transaction_types,id', | ||||
|             'bill_id'                 => 'exists:bills,id', | ||||
|             'transaction_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'description'             => 'required|between:1,1024', | ||||
|             'completed'               => 'required|boolean', | ||||
|             'date'                    => 'required|date', | ||||
|             'encrypted'               => 'required|boolean' | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function bill() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\Bill'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function budgets() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\Budget'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function categories() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\Category'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'date', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getDescriptionAttribute($value) | ||||
|     { | ||||
|         if ($this->encrypted) { | ||||
|             return Crypt::decrypt($value); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreStart | ||||
|         return $value; | ||||
|         // @codeCoverageIgnoreEnd | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function piggyBankEvents() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\PiggyBankEvent'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Account         $account | ||||
|      */ | ||||
|     public function scopeAccountIs(EloquentBuilder $query, Account $account) | ||||
|     { | ||||
|         if (!isset($this->joinedTransactions)) { | ||||
|             $query->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'); | ||||
|             $this->joinedTransactions = true; | ||||
|         } | ||||
|         $query->where('transactions.account_id', $account->id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function scopeAfter(EloquentBuilder $query, Carbon $date) | ||||
|     { | ||||
|         return $query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function scopeBefore(EloquentBuilder $query, Carbon $date) | ||||
|     { | ||||
|         return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d 00:00:00')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param                 $amount | ||||
|      */ | ||||
|     public function scopeLessThan(EloquentBuilder $query, $amount) | ||||
|     { | ||||
|         if (is_null($this->joinedTransactions)) { | ||||
|             $query->leftJoin( | ||||
|                 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|             ); | ||||
|             $this->joinedTransactions = true; | ||||
|         } | ||||
|  | ||||
|         $query->where('transactions.amount', '<=', $amount); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function scopeOnDate(EloquentBuilder $query, Carbon $date) | ||||
|     { | ||||
|         return $query->where('date', '=', $date->format('Y-m-d')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param array           $types | ||||
|      */ | ||||
|     public function scopeTransactionTypes(EloquentBuilder $query, array $types) | ||||
|     { | ||||
|         if (is_null($this->joinedTransactionTypes)) { | ||||
|             $query->leftJoin( | ||||
|                 'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' | ||||
|             ); | ||||
|             $this->joinedTransactionTypes = true; | ||||
|         } | ||||
|         $query->whereIn('transaction_types.type', $types); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Automatically includes the 'with' parameters to get relevant related | ||||
|      * objects. | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      */ | ||||
|     public function scopeWithRelevantData(EloquentBuilder $query) | ||||
|     { | ||||
|         $query->with( | ||||
|             ['transactions' => function (HasMany $q) { | ||||
|                 $q->orderBy('amount', 'ASC'); | ||||
|             }, 'transactiontype', 'transactioncurrency', 'budgets', 'categories', 'transactions.account.accounttype', 'bill', 'budgets', 'categories'] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setDescriptionAttribute($value) | ||||
|     { | ||||
|         $this->attributes['description'] = \Crypt::encrypt($value); | ||||
|         $this->attributes['encrypted']   = true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function transactionCurrency() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\TransactionCurrency'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function transactionType() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\Models\TransactionType'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function transactiongroups() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\TransactionGroup'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function transactions() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\Transaction'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										21
									
								
								app/Models/TransactionRelation.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/Models/TransactionRelation.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionRelation | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class TransactionRelation extends Model | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at']; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										30
									
								
								app/Models/TransactionType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/Models/TransactionType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionType | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class TransactionType extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|     public function transactionJournals() | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\TransactionJournal'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Providers/AppServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Providers/AppServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php namespace FireflyIII\Providers; | ||||
|  | ||||
| use Illuminate\Support\ServiceProvider; | ||||
|  | ||||
| /** | ||||
|  * Class AppServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class AppServiceProvider extends ServiceProvider | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Bootstrap any application services. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function boot() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register any application services. | ||||
|      * | ||||
|      * This service provider is a great spot to register your various container | ||||
|      * bindings with the application. As you can see, we are registering our | ||||
|      * "Registrar" implementation here. You can add your own bindings too! | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|         $this->app->bind( | ||||
|             'Illuminate\Contracts\Auth\Registrar', | ||||
|             'FireflyIII\Services\Registrar' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										42
									
								
								app/Providers/BusServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/Providers/BusServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <?php namespace FireflyIII\Providers; | ||||
|  | ||||
| use Illuminate\Bus\Dispatcher; | ||||
| use Illuminate\Support\ServiceProvider; | ||||
|  | ||||
| /** | ||||
|  * Class BusServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class BusServiceProvider extends ServiceProvider | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Bootstrap any application services. | ||||
|      * | ||||
|      * @param  \Illuminate\Bus\Dispatcher $dispatcher | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function boot(Dispatcher $dispatcher) | ||||
|     { | ||||
|         $dispatcher->mapUsing( | ||||
|             function ($command) { | ||||
|                 return Dispatcher::simpleMapping( | ||||
|                     $command, 'FireflyIII\Commands', 'FireflyIII\Handlers\Commands' | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register any application services. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										31
									
								
								app/Providers/ConfigServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/Providers/ConfigServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| <?php namespace FireflyIII\Providers; | ||||
|  | ||||
| use Illuminate\Support\ServiceProvider; | ||||
|  | ||||
| /** | ||||
|  * Class ConfigServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class ConfigServiceProvider extends ServiceProvider | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Overwrite any vendor / package configuration. | ||||
|      * | ||||
|      * This service provider is intended to provide a convenient location for you | ||||
|      * to overwrite any "vendor" or package configuration that you may want to | ||||
|      * modify before the application handles the incoming request / command. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|         config( | ||||
|             [ | ||||
|                 // | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										132
									
								
								app/Providers/EventServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								app/Providers/EventServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| <?php namespace FireflyIII\Providers; | ||||
|  | ||||
| use App; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Support\Facades\Navigation; | ||||
| use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; | ||||
| use Illuminate\Database\QueryException; | ||||
| use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class EventServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class EventServiceProvider extends ServiceProvider | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The event handler mappings for the application. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $listen | ||||
|         = [ | ||||
|             'FireflyIII\Events\JournalSaved' => [ | ||||
|                 'FireflyIII\Handlers\Events\RescanJournal', | ||||
|                 'FireflyIII\Handlers\Events\UpdateJournalConnection', | ||||
|  | ||||
|             ], | ||||
|             'FireflyIII\Events\JournalCreated' => [ | ||||
|                 'FireflyIII\Handlers\Events\ConnectJournalToPiggyBank', | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * Register any other events for your application. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\Events\Dispatcher $events | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function boot(DispatcherContract $events) | ||||
|     { | ||||
|         parent::boot($events); | ||||
|  | ||||
|         TransactionJournal::deleted( | ||||
|             function (TransactionJournal $journal) { | ||||
|  | ||||
|                 /** @var Transaction $transaction */ | ||||
|                 foreach ($journal->transactions()->get() as $transaction) { | ||||
|                     $transaction->delete(); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|  | ||||
|         Account::deleted( | ||||
|             function (Account $account) { | ||||
|  | ||||
|                 /** @var Transaction $transaction */ | ||||
|                 foreach ($account->transactions()->get() as $transaction) { | ||||
|                     $journal = $transaction->transactionJournal()->first(); | ||||
|                     $journal->delete(); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         // move this routine to a filter | ||||
|         // in case of repeated piggy banks and/or other problems. | ||||
|         PiggyBank::created( | ||||
|             function (PiggyBank $piggyBank) { | ||||
|                 $repetition = new PiggyBankRepetition; | ||||
|                 $repetition->piggyBank()->associate($piggyBank); | ||||
|                 $repetition->startdate     = is_null($piggyBank->startdate) ? null : $piggyBank->startdate; | ||||
|                 $repetition->targetdate    = is_null($piggyBank->targetdate) ? null : $piggyBank->targetdate; | ||||
|                 $repetition->currentamount = 0; | ||||
|                 $repetition->save(); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         BudgetLimit::saved( | ||||
|             function (BudgetLimit $budgetLimit) { | ||||
|  | ||||
|                 $end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0); | ||||
|                 $end->subDay(); | ||||
|  | ||||
|                 $set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d')) | ||||
|                                    ->get(); | ||||
|                 /* | ||||
|                  * Create new LimitRepetition: | ||||
|                  */ | ||||
|                 if ($set->count() == 0) { | ||||
|  | ||||
|                     $repetition            = new LimitRepetition; | ||||
|                     $repetition->startdate = $budgetLimit->startdate; | ||||
|                     $repetition->enddate   = $end; | ||||
|                     $repetition->amount    = $budgetLimit->amount; | ||||
|                     $repetition->budgetLimit()->associate($budgetLimit); | ||||
|  | ||||
|                     try { | ||||
|                         $repetition->save(); | ||||
|                     } catch (QueryException $e) { | ||||
|                         \Log::error('Trying to save new LimitRepetition failed!'); | ||||
|                         \Log::error($e->getMessage()); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if ($set->count() == 1) { | ||||
|                         /* | ||||
|                          * Update existing one. | ||||
|                          */ | ||||
|                         $repetition         = $set->first(); | ||||
|                         $repetition->amount = $budgetLimit->amount; | ||||
|                         $repetition->save(); | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										74
									
								
								app/Providers/FireflyServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/Providers/FireflyServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Providers; | ||||
|  | ||||
| use FireflyIII\Support\Amount; | ||||
| use FireflyIII\Support\ExpandedForm; | ||||
| use FireflyIII\Support\Navigation; | ||||
| use FireflyIII\Support\Preferences; | ||||
| use FireflyIII\Support\Steam; | ||||
| use FireflyIII\Validation\FireflyValidator; | ||||
| use Illuminate\Support\ServiceProvider; | ||||
| use Validator; | ||||
|  | ||||
| /** | ||||
|  * Class FireflyServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class FireflyServiceProvider extends ServiceProvider | ||||
| { | ||||
|     public function boot() | ||||
|     { | ||||
|         Validator::resolver( | ||||
|             function ($translator, $data, $rules, $messages) { | ||||
|                 return new FireflyValidator($translator, $data, $rules, $messages); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function register() | ||||
|     { | ||||
|         $this->app->bind( | ||||
|             'preferences', function () { | ||||
|             return new Preferences; | ||||
|         } | ||||
|         ); | ||||
|         $this->app->bind( | ||||
|             'navigation', function () { | ||||
|             return new Navigation; | ||||
|         } | ||||
|         ); | ||||
|         $this->app->bind( | ||||
|             'amount', function () { | ||||
|             return new Amount; | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         $this->app->bind( | ||||
|             'steam', function () { | ||||
|             return new Steam; | ||||
|         } | ||||
|         ); | ||||
|         $this->app->bind( | ||||
|             'expandedform', function () { | ||||
|             return new ExpandedForm; | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         $this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Budget\BudgetRepositoryInterface', 'FireflyIII\Repositories\Budget\BudgetRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Category\CategoryRepositoryInterface', 'FireflyIII\Repositories\Category\CategoryRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository'); | ||||
|         $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); | ||||
|  | ||||
|  | ||||
|         $this->app->bind('FireflyIII\Helpers\Reminders\ReminderHelperInterface', 'FireflyIII\Helpers\Reminders\ReminderHelper'); | ||||
|         $this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper'); | ||||
|         $this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										70
									
								
								app/Providers/RouteServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/Providers/RouteServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| <?php namespace FireflyIII\Providers; | ||||
|  | ||||
| use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Routing\Router; | ||||
|  | ||||
| /** | ||||
|  * Class RouteServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class RouteServiceProvider extends ServiceProvider | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This namespace is applied to the controller routes in your routes file. | ||||
|      * | ||||
|      * In addition, it is set as the URL generator's root namespace. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $namespace = 'FireflyIII\Http\Controllers'; | ||||
|  | ||||
|     /** | ||||
|      * Define your route model bindings, pattern filters, etc. | ||||
|      * | ||||
|      * @param  \Illuminate\Routing\Router $router | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function boot(Router $router) | ||||
|     { | ||||
|         parent::boot($router); | ||||
|  | ||||
|         $router->before( | ||||
|             function (Request $request) { | ||||
|  | ||||
|                 // put IP in session if not already there. | ||||
|  | ||||
|                 $reminders = []; | ||||
|  | ||||
|                 if ($request->user()) { | ||||
|                     //Filter::setSessionDateRange(); | ||||
|                     //Reminders::updateReminders(); | ||||
|                     //Steam::removeEmptyBudgetLimits(); | ||||
|                     //$reminders = Reminders::getReminders(); | ||||
|                 } | ||||
|                 //                View::share('reminders', $reminders); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Define the routes for the application. | ||||
|      * | ||||
|      * @param  \Illuminate\Routing\Router $router | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function map(Router $router) | ||||
|     { | ||||
|         $router->group( | ||||
|             ['namespace' => $this->namespace], function ($router) { | ||||
|             /** @noinspection PhpIncludeInspection */ | ||||
|             require app_path('Http/routes.php'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Providers/TestingServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Providers/TestingServiceProvider.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Providers; | ||||
|  | ||||
|  | ||||
| use Illuminate\Support\ServiceProvider; | ||||
|  | ||||
| /** | ||||
|  * Class TestingServiceProvider | ||||
|  * | ||||
|  * @package FireflyIII\Providers | ||||
|  */ | ||||
| class TestingServiceProvider extends ServiceProvider | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Register the service provider. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|         if ($this->app->environment() == 'testing') { | ||||
|             $this->app['config']['session.driver'] = 'native'; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										456
									
								
								app/Repositories/Account/AccountRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										456
									
								
								app/Repositories/Account/AccountRepository.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,456 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Account; | ||||
|  | ||||
| use App; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountMeta; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class AccountRepository | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Account | ||||
|  */ | ||||
| class AccountRepository implements AccountRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countAssetAccounts() | ||||
|     { | ||||
|         return Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->count(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Account $account) | ||||
|     { | ||||
|         $account->delete(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Preference $preference | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getFrontpageAccounts(Preference $preference) | ||||
|     { | ||||
|         if ($preference->data == []) { | ||||
|             $accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|         } else { | ||||
|             $accounts = Auth::user()->accounts()->whereIn('id', $preference->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|         } | ||||
|  | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is used on the front page where (in turn) its viewed journals-tiny.php which (in turn) | ||||
|      * is almost the only place where formatJournal is used. Aka, we can use some custom querying to get some specific. | ||||
|      * fields using left joins. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return Auth::user() | ||||
|                    ->transactionjournals() | ||||
|                    ->with(['transactions']) | ||||
|                    ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                    ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id) | ||||
|                    ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id') | ||||
|                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                    ->before($end) | ||||
|                    ->after($start) | ||||
|                    ->orderBy('transaction_journals.date', 'DESC') | ||||
|                    ->orderBy('transaction_journals.id', 'DESC') | ||||
|                    ->take(10) | ||||
|                    ->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param int     $page | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getJournals(Account $account, $page) | ||||
|     { | ||||
|         $offset = ($page - 1) * 50; | ||||
|         $query  = Auth::user() | ||||
|                       ->transactionJournals() | ||||
|                       ->withRelevantData() | ||||
|                       ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                       ->where('transactions.account_id', $account->id) | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.order','ASC') | ||||
|             ->orderBy('transaction_journals.id','DESC'); | ||||
|  | ||||
|         $query->before(Session::get('end', Carbon::now()->endOfMonth())); | ||||
|         $query->after(Session::get('start', Carbon::now()->startOfMonth())); | ||||
|         $count     = $query->count(); | ||||
|         $set       = $query->take(50)->offset($offset)->get(['transaction_journals.*']); | ||||
|         $paginator = new LengthAwarePaginator($set, $count, 50, $page); | ||||
|  | ||||
|         return $paginator; | ||||
|  | ||||
|         //return Paginator::make($items, $count, 50); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get savings accounts and the balance difference in the period. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getSavingsAccounts() | ||||
|     { | ||||
|         $accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC') | ||||
|                         ->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id') | ||||
|                         ->where('account_meta.name', 'accountRole') | ||||
|                         ->where('account_meta.data', '"savingAsset"') | ||||
|                         ->get(['accounts.*']); | ||||
|         $start    = clone Session::get('start'); | ||||
|         $end      = clone Session::get('end'); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($start, $end) { | ||||
|                 $account->startBalance = Steam::balance($account, $start); | ||||
|                 $account->endBalance   = Steam::balance($account, $end); | ||||
|  | ||||
|                 // diff (negative when lost, positive when gained) | ||||
|                 $diff = $account->endBalance - $account->startBalance; | ||||
|  | ||||
|                 if ($diff < 0 && $account->startBalance > 0) { | ||||
|                     // percentage lost compared to start. | ||||
|                     $pct = (($diff * -1) / $account->startBalance) * 100; | ||||
|                 } else { | ||||
|                     if ($diff >= 0 && $account->startBalance > 0) { | ||||
|                         $pct = ($diff / $account->startBalance) * 100; | ||||
|                     } else { | ||||
|                         $pct = 100; | ||||
|                     } | ||||
|                 } | ||||
|                 $pct                 = $pct > 100 ? 100 : $pct; | ||||
|                 $account->difference = $diff; | ||||
|                 $account->percentage = round($pct); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function leftOnAccount(Account $account) | ||||
|     { | ||||
|         $balance = \Steam::balance($account); | ||||
|         /** @var PiggyBank $p */ | ||||
|         foreach ($account->piggybanks()->get() as $p) { | ||||
|             $balance -= $p->currentRelevantRep()->currentamount; | ||||
|         } | ||||
|  | ||||
|         return $balance; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return TransactionJournal|null | ||||
|      */ | ||||
|     public function openingBalanceTransaction(Account $account) | ||||
|     { | ||||
|         return TransactionJournal::accountIs($account) | ||||
|                                  ->orderBy('transaction_journals.date', 'ASC') | ||||
|                                  ->orderBy('created_at', 'ASC') | ||||
|                                  ->first(['transaction_journals.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Account; | ||||
|      */ | ||||
|     public function store(array $data) | ||||
|     { | ||||
|         $newAccount = $this->_store($data); | ||||
|         $this->_storeMetadata($newAccount, $data); | ||||
|  | ||||
|  | ||||
|         // continue with the opposing account: | ||||
|         if ($data['openingBalance'] != 0) { | ||||
|             $type         = $data['openingBalance'] < 0 ? 'expense' : 'revenue'; | ||||
|             $opposingData = [ | ||||
|                 'user'        => $data['user'], | ||||
|                 'accountType' => $type, | ||||
|                 'name'        => $data['name'] . ' initial balance', | ||||
|                 'active'      => false, | ||||
|             ]; | ||||
|             $opposing     = $this->_store($opposingData); | ||||
|             $this->_storeInitialBalance($newAccount, $opposing, $data); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $newAccount; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      */ | ||||
|     public function update(Account $account, array $data) | ||||
|     { | ||||
|         // update the account: | ||||
|         $account->name   = $data['name']; | ||||
|         $account->active = $data['active'] == '1' ? true : false; | ||||
|         $account->save(); | ||||
|  | ||||
|         // update meta data: | ||||
|         $this->_updateMetadata($account, $data); | ||||
|  | ||||
|         $openingBalance = $this->openingBalanceTransaction($account); | ||||
|  | ||||
|         // if has openingbalance? | ||||
|         if ($data['openingBalance'] != 0) { | ||||
|             // if opening balance, do an update: | ||||
|             if ($openingBalance) { | ||||
|                 // update existing opening balance. | ||||
|                 $this->_updateInitialBalance($account, $openingBalance, $data); | ||||
|             } else { | ||||
|                 // create new opening balance. | ||||
|                 $type         = $data['openingBalance'] < 0 ? 'expense' : 'revenue'; | ||||
|                 $opposingData = [ | ||||
|                     'user'        => $data['user'], | ||||
|                     'accountType' => $type, | ||||
|                     'name'        => $data['name'] . ' initial balance', | ||||
|                     'active'      => false, | ||||
|                 ]; | ||||
|                 $opposing     = $this->_store($opposingData); | ||||
|                 $this->_storeInitialBalance($account, $opposing, $data); | ||||
|             } | ||||
|  | ||||
|         } else { | ||||
|             // opening balance is zero, should we delete it? | ||||
|             if ($openingBalance) { | ||||
|                 // delete existing opening balance. | ||||
|                 $openingBalance->delete(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Account | ||||
|      */ | ||||
|     protected function _store(array $data) | ||||
|     { | ||||
|         $type        = Config::get('firefly.accountTypeByIdentifier.' . $data['accountType']); | ||||
|         $accountType = AccountType::whereType($type)->first(); | ||||
|         $newAccount  = new Account( | ||||
|             [ | ||||
|                 'user_id'         => $data['user'], | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $data['name'], | ||||
|                 'active'          => $data['active'] === true ? true : false, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         if (!$newAccount->isValid()) { | ||||
|             // does the account already exist? | ||||
|             $existingAccount = Account::where('user_id', $data['user'])->where('account_type_id', $accountType->id)->where('name', $data['name'])->first(); | ||||
|             if (!$existingAccount) { | ||||
|                 Log::error('Account create error: ' . $newAccount->getErrors()->toJson()); | ||||
|                 App::abort(500); | ||||
|  | ||||
|             } | ||||
|             $newAccount = $existingAccount; | ||||
|         } | ||||
|         $newAccount->save(); | ||||
|  | ||||
|         return $newAccount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      */ | ||||
|     protected function _storeMetadata(Account $account, array $data) | ||||
|     { | ||||
|         $metaData = new AccountMeta( | ||||
|             [ | ||||
|                 'account_id' => $account->id, | ||||
|                 'name'       => 'accountRole', | ||||
|                 'data'       => $data['accountRole'] | ||||
|             ] | ||||
|         ); | ||||
|         if (!$metaData->isValid()) { | ||||
|             App::abort(500); | ||||
|         } | ||||
|         $metaData->save(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Account $opposing | ||||
|      * @param array   $data | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     protected function _storeInitialBalance(Account $account, Account $opposing, array $data) | ||||
|     { | ||||
|         $type            = $data['openingBalance'] < 0 ? 'Withdrawal' : 'Deposit'; | ||||
|         $transactionType = TransactionType::whereType($type)->first(); | ||||
|  | ||||
|         $journal = new TransactionJournal( | ||||
|             [ | ||||
|                 'user_id'                 => $data['user'], | ||||
|                 'transaction_type_id'     => $transactionType->id, | ||||
|                 'bill_id'                 => null, | ||||
|                 'transaction_currency_id' => $data['openingBalanceCurrency'], | ||||
|                 'description'             => 'Initial balance for "' . $account->name . '"', | ||||
|                 'completed'               => true, | ||||
|                 'date'                    => $data['openingBalanceDate'], | ||||
|                 'encrypted'               => true | ||||
|             ] | ||||
|         ); | ||||
|         if (!$journal->isValid()) { | ||||
|             App::abort(500); | ||||
|         } | ||||
|         $journal->save(); | ||||
|  | ||||
|  | ||||
|         if ($data['openingBalance'] < 0) { | ||||
|             $firstAccount  = $opposing; | ||||
|             $secondAccount = $account; | ||||
|             $firstAmount   = $data['openingBalance'] * -1; | ||||
|             $secondAmount  = $data['openingBalance']; | ||||
|         } else { | ||||
|             $firstAccount  = $account; | ||||
|             $secondAccount = $opposing; | ||||
|             $firstAmount   = $data['openingBalance']; | ||||
|             $secondAmount  = $data['openingBalance'] * -1; | ||||
|         } | ||||
|  | ||||
|         // first transaction: from | ||||
|         $one = new Transaction( | ||||
|             [ | ||||
|                 'account_id'             => $firstAccount->id, | ||||
|                 'transaction_journal_id' => $journal->id, | ||||
|                 'amount'                 => $firstAmount | ||||
|             ] | ||||
|         ); | ||||
|         if (!$one->isValid()) { | ||||
|             App::abort(500); | ||||
|         } | ||||
|         $one->save(); | ||||
|  | ||||
|         // second transaction: to | ||||
|         $two = new Transaction( | ||||
|             [ | ||||
|                 'account_id'             => $secondAccount->id, | ||||
|                 'transaction_journal_id' => $journal->id, | ||||
|                 'amount'                 => $secondAmount | ||||
|             ] | ||||
|         ); | ||||
|         if (!$two->isValid()) { | ||||
|             App::abort(500); | ||||
|         } | ||||
|         $two->save(); | ||||
|  | ||||
|         return $journal; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      */ | ||||
|     protected function _updateMetadata(Account $account, array $data) | ||||
|     { | ||||
|         $metaEntries = $account->accountMeta()->get(); | ||||
|         $updated     = false; | ||||
|  | ||||
|         /** @var AccountMeta $entry */ | ||||
|         foreach ($metaEntries as $entry) { | ||||
|             if ($entry->name == 'accountRole') { | ||||
|                 $entry->data = $data['accountRole']; | ||||
|                 $updated     = true; | ||||
|                 $entry->save(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($updated === false) { | ||||
|             $metaData = new AccountMeta( | ||||
|                 [ | ||||
|                     'account_id' => $account->id, | ||||
|                     'name'       => 'accountRole', | ||||
|                     'data'       => $data['accountRole'] | ||||
|                 ] | ||||
|             ); | ||||
|             if (!$metaData->isValid()) { | ||||
|                 App::abort(500); | ||||
|             } | ||||
|             $metaData->save(); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account            $account | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param array              $data | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     protected function _updateInitialBalance(Account $account, TransactionJournal $journal, array $data) | ||||
|     { | ||||
|         $journal->date = $data['openingBalanceDate']; | ||||
|  | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             if ($account->id == $transaction->account_id) { | ||||
|                 $transaction->amount = $data['openingBalance']; | ||||
|                 $transaction->save(); | ||||
|             } | ||||
|             if ($account->id != $transaction->account_id) { | ||||
|                 $transaction->amount = $data['openingBalance'] * -1; | ||||
|                 $transaction->save(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										88
									
								
								app/Repositories/Account/AccountRepositoryInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								app/Repositories/Account/AccountRepositoryInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Account; | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\Preference; | ||||
| use Illuminate\Support\Collection; | ||||
| use Carbon\Carbon; | ||||
| /** | ||||
|  * Interface AccountRepositoryInterface | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Account | ||||
|  */ | ||||
| interface AccountRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Account $account); | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countAssetAccounts(); | ||||
|  | ||||
|     /** | ||||
|      * @param Preference $preference | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getFrontpageAccounts(Preference $preference); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $range | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getJournals(Account $account, $page); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return TransactionJournal|null | ||||
|      */ | ||||
|     public function openingBalanceTransaction(Account $account); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function store(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      * | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function update(Account $account, array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function leftOnAccount(Account $account); | ||||
|  | ||||
|     /** | ||||
|      * Get savings accounts and the balance difference in the period. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getSavingsAccounts(); | ||||
| } | ||||
							
								
								
									
										241
									
								
								app/Repositories/Bill/BillRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								app/Repositories/Bill/BillRepository.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,241 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Bill; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Log; | ||||
| use Navigation; | ||||
|  | ||||
| /** | ||||
|  * Class BillRepository | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Bill | ||||
|  */ | ||||
| class BillRepository implements BillRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) | ||||
|      * and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and | ||||
|      * you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill. | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getRanges(Bill $bill, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $startOfBill = $bill->date; | ||||
|         $startOfBill = Navigation::startOfPeriod($startOfBill, $bill->repeat_freq); | ||||
|  | ||||
|  | ||||
|         // all periods of this bill up until the current period: | ||||
|         $billStarts = []; | ||||
|         while ($startOfBill < $end) { | ||||
|  | ||||
|             $endOfBill = Navigation::endOfPeriod($startOfBill, $bill->repeat_freq); | ||||
|  | ||||
|             $billStarts[] = [ | ||||
|                 'start' => clone $startOfBill, | ||||
|                 'end'   => clone $endOfBill, | ||||
|             ]; | ||||
|             // actually the next one: | ||||
|             $startOfBill = Navigation::addPeriod($startOfBill, $bill->repeat_freq, $bill->skip); | ||||
|  | ||||
|         } | ||||
|         // for each | ||||
|         $validRanges = []; | ||||
|         foreach ($billStarts as $dateEntry) { | ||||
|             if ($dateEntry['end'] > $start && $dateEntry['start'] < $end) { | ||||
|                 // count transactions for bill in this range (not relevant yet!): | ||||
|                 //                $count = $bill->transactionjournals()->before($dateEntry['end'])->after($dateEntry['start'])->count(); | ||||
|                 //                if ($count == 0) { | ||||
|                 $validRanges[] = $dateEntry; | ||||
|                 //                } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $validRanges; | ||||
|         //        echo $bill->name; | ||||
|         //        var_dump($validRanges); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function nextExpectedMatch(Bill $bill) | ||||
|     { | ||||
|  | ||||
|         $finalDate = null; | ||||
|         if ($bill->active == 0) { | ||||
|             return $finalDate; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * $today is the start of the next period, to make sure FF3 won't miss anything | ||||
|          * when the current period has a transaction journal. | ||||
|          */ | ||||
|         $today = Navigation::addPeriod(new Carbon, $bill->repeat_freq, 0); | ||||
|  | ||||
|         $skip  = $bill->skip + 1; | ||||
|         $start = Navigation::startOfPeriod(new Carbon, $bill->repeat_freq); | ||||
|         /* | ||||
|          * go back exactly one month/week/etc because FF3 does not care about 'next' | ||||
|          * bills if they're too far into the past. | ||||
|          */ | ||||
|  | ||||
|         $counter = 0; | ||||
|         while ($start <= $today) { | ||||
|             if (($counter % $skip) == 0) { | ||||
|                 // do something. | ||||
|                 $end          = Navigation::endOfPeriod(clone $start, $bill->repeat_freq); | ||||
|                 $journalCount = $bill->transactionjournals()->before($end)->after($start)->count(); | ||||
|                 if ($journalCount == 0) { | ||||
|                     $finalDate = clone $start; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // add period for next round! | ||||
|             $start = Navigation::addPeriod($start, $bill->repeat_freq, 0); | ||||
|             $counter++; | ||||
|         } | ||||
|  | ||||
|         return $finalDate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill               $bill | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function scan(Bill $bill, TransactionJournal $journal) | ||||
|     { | ||||
|         /* | ||||
|          * Match words. | ||||
|          */ | ||||
|         $wordMatch   = false; | ||||
|         $matches     = explode(',', $bill->match); | ||||
|         $description = strtolower($journal->description); | ||||
|         Log::debug('Now scanning ' . $description); | ||||
|  | ||||
|         /* | ||||
|          * Attach expense account to description for more narrow matching. | ||||
|          */ | ||||
|         if (count($journal->transactions) < 2) { | ||||
|             $transactions = $journal->transactions()->get(); | ||||
|         } else { | ||||
|             $transactions = $journal->transactions; | ||||
|         } | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             /** @var Account $account */ | ||||
|             $account = $transaction->account()->first(); | ||||
|             /** @var AccountType $type */ | ||||
|             $type = $account->accountType()->first(); | ||||
|             if ($type->type == 'Expense account' || $type->type == 'Beneficiary account') { | ||||
|                 $description .= ' ' . strtolower($account->name); | ||||
|             } | ||||
|         } | ||||
|         Log::debug('Final description: ' . $description); | ||||
|         Log::debug('Matches searched: ' . join(':', $matches)); | ||||
|  | ||||
|         $count = 0; | ||||
|         foreach ($matches as $word) { | ||||
|             if (!(strpos($description, strtolower($word)) === false)) { | ||||
|                 $count++; | ||||
|             } | ||||
|         } | ||||
|         if ($count >= count($matches)) { | ||||
|             $wordMatch = true; | ||||
|             Log::debug('word match is true'); | ||||
|         } else { | ||||
|             Log::debug('Count: ' . $count . ', count(matches): ' . count($matches)); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Match amount. | ||||
|          */ | ||||
|  | ||||
|         $amountMatch = false; | ||||
|         if (count($transactions) > 1) { | ||||
|  | ||||
|             $amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount)); | ||||
|             $min    = floatval($bill->amount_min); | ||||
|             $max    = floatval($bill->amount_max); | ||||
|             if ($amount >= $min && $amount <= $max) { | ||||
|                 $amountMatch = true; | ||||
|                 Log::debug('Amount match is true!'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * If both, update! | ||||
|          */ | ||||
|         if ($wordMatch && $amountMatch) { | ||||
|             Log::debug('TOTAL match is true!'); | ||||
|             $journal->bill()->associate($bill); | ||||
|             $journal->save(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function store(array $data) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         $bill = Bill::create( | ||||
|             [ | ||||
|                 'name'        => $data['name'], | ||||
|                 'match'       => $data['match'], | ||||
|                 'amount_min'  => $data['amount_min'], | ||||
|                 'user_id'     => $data['user'], | ||||
|                 'amount_max'  => $data['amount_max'], | ||||
|                 'date'        => $data['date'], | ||||
|                 'repeat_freq' => $data['repeat_freq'], | ||||
|                 'skip'        => $data['skip'], | ||||
|                 'automatch'   => $data['automatch'], | ||||
|                 'active'      => $data['active'], | ||||
|  | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill  $bill | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Bill|static | ||||
|      */ | ||||
|     public function update(Bill $bill, array $data) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         $bill->name        = $data['name']; | ||||
|         $bill->match       = $data['match']; | ||||
|         $bill->amount_min  = $data['amount_min']; | ||||
|         $bill->amount_max  = $data['amount_max']; | ||||
|         $bill->date        = $data['date']; | ||||
|         $bill->repeat_freq = $data['repeat_freq']; | ||||
|         $bill->skip        = $data['skip']; | ||||
|         $bill->automatch   = $data['automatch']; | ||||
|         $bill->active      = $data['active']; | ||||
|         $bill->save(); | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										59
									
								
								app/Repositories/Bill/BillRepositoryInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								app/Repositories/Bill/BillRepositoryInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Bill; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
|  | ||||
| /** | ||||
|  * Interface BillRepositoryInterface | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Bill | ||||
|  */ | ||||
| interface BillRepositoryInterface { | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     public function nextExpectedMatch(Bill $bill); | ||||
|  | ||||
|     /** | ||||
|      * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) | ||||
|      * and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and | ||||
|      * you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill. | ||||
|      * | ||||
|      * @param Bill $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getRanges(Bill $bill, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function store(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Bill  $bill | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function update(Bill $bill, array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Bill               $bill | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function scan(Bill $bill, TransactionJournal $journal); | ||||
|  | ||||
| } | ||||
							
								
								
									
										145
									
								
								app/Repositories/Budget/BudgetRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								app/Repositories/Budget/BudgetRepository.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Budget; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetRepository | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Budget | ||||
|  */ | ||||
| class BudgetRepository implements BudgetRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Budget $budget) | ||||
|     { | ||||
|         $budget->delete(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns all the transaction journals for a limit, possibly limited by a limit repetition. | ||||
|      * | ||||
|      * @param Budget          $budget | ||||
|      * @param LimitRepetition $repetition | ||||
|      * @param int             $take | ||||
|      * | ||||
|      * @return \Illuminate\Pagination\Paginator | ||||
|      */ | ||||
|     public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50) | ||||
|     { | ||||
|         $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $take : 0; | ||||
|  | ||||
|  | ||||
|         $setQuery   = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset) | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.order','ASC') | ||||
|             ->orderBy('transaction_journals.id','DESC'); | ||||
|         $countQuery = $budget->transactionJournals(); | ||||
|  | ||||
|  | ||||
|         if (!is_null($repetition->id)) { | ||||
|             $setQuery->after($repetition->startdate)->before($repetition->enddate); | ||||
|             $countQuery->after($repetition->startdate)->before($repetition->enddate); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $set   = $setQuery->get(['transaction_journals.*']); | ||||
|         $count = $countQuery->count(); | ||||
|         return new LengthAwarePaginator($set, $count, $take, $offset); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentInMonth(Budget $budget, Carbon $date) | ||||
|     { | ||||
|         $end = clone $date; | ||||
|         $date->startOfMonth(); | ||||
|         $end->endOfMonth(); | ||||
|         $sum = floatval($budget->transactionjournals()->before($end)->after($date)->lessThan(0)->sum('amount')) * -1; | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Budget | ||||
|      */ | ||||
|     public function store(array $data) | ||||
|     { | ||||
|         $newBudget = new Budget( | ||||
|             [ | ||||
|                 'user_id' => $data['user'], | ||||
|                 'name'    => $data['name'], | ||||
|             ] | ||||
|         ); | ||||
|         $newBudget->save(); | ||||
|  | ||||
|         return $newBudget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param array  $data | ||||
|      * | ||||
|      * @return Budget | ||||
|      */ | ||||
|     public function update(Budget $budget, array $data) | ||||
|     { | ||||
|         // update the account: | ||||
|         $budget->name = $data['name']; | ||||
|         $budget->save(); | ||||
|  | ||||
|         return $budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * @param        $amount | ||||
|      * | ||||
|      * @return LimitRepetition|null | ||||
|      */ | ||||
|     public function updateLimitAmount(Budget $budget, Carbon $date, $amount) | ||||
|     { | ||||
|         /** @var BudgetLimit $limit */ | ||||
|         $limit = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); | ||||
|         if (!$limit) { | ||||
|             // create one! | ||||
|             $limit = new BudgetLimit; | ||||
|             $limit->budget()->associate($budget); | ||||
|             $limit->startdate   = $date; | ||||
|             $limit->amount      = $amount; | ||||
|             $limit->repeat_freq = 'monthly'; | ||||
|             $limit->repeats     = 0; | ||||
|             $limit->save(); | ||||
|         } else { | ||||
|             if ($amount > 0) { | ||||
|                 $limit->amount = $amount; | ||||
|                 $limit->save(); | ||||
|             } else { | ||||
|                 $limit->delete(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $limit; | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user