mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 18:54:58 +00:00 
			
		
		
		
	Compare commits
	
		
			1154 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 5f299b895b | ||
|  | 4e1bb5fbac | ||
|  | 47ccc513ad | ||
|  | cce1a01936 | ||
|  | 6f2b1a6a76 | ||
|  | 8526907f50 | ||
|  | bc192a8e54 | ||
|  | 9ff6f8fc52 | ||
|  | 6573bd6b4b | ||
|  | 9dc3f614af | ||
|  | 3888b8cceb | ||
|  | 294df4a2b3 | ||
|  | 265dd37212 | ||
|  | eb7c79ad27 | ||
|  | de111c7100 | ||
|  | e892c9a824 | ||
|  | 5eb0e18cae | ||
|  | 27cabb398e | ||
|  | 64dbb14241 | ||
|  | bb4e2be9eb | ||
|  | 7d1de0da17 | ||
|  | bf16c9a42b | ||
|  | 1a7b1ce499 | ||
|  | efc9bc71a7 | ||
|  | fc5b315af0 | ||
|  | 7a4a78628d | ||
|  | d16fb30a62 | ||
|  | 2d177e660e | ||
|  | 2f131dc170 | ||
|  | 94810e371a | ||
|  | 59731878f6 | ||
|  | 54ede8aa18 | ||
|  | b415b6b043 | ||
|  | 70c922cdc5 | ||
|  | 068fc32cb2 | ||
|  | 3dcdacc3b8 | ||
|  | a6594358d8 | ||
|  | f98921da46 | ||
|  | 25747fbcf2 | ||
|  | aac5c2b13c | ||
|  | cc810a5b6f | ||
|  | 1b3592d959 | ||
|  | d75614e9a7 | ||
|  | 08703e282f | ||
|  | 2904baf44e | ||
|  | f99e46bf75 | ||
|  | 9f87890ead | ||
|  | 638184cf66 | ||
|  | 03babfe75c | ||
|  | 238ed3c788 | ||
|  | 6a9d931ba3 | ||
|  | a3d2a9e00b | ||
|  | 39b88e8207 | ||
|  | 449c6dfde5 | ||
|  | 7cc47ca0b1 | ||
|  | 95f4a83f41 | ||
|  | 35154dc7a3 | ||
|  | 0fd0d7d080 | ||
|  | 658265c938 | ||
|  | 38fe9e7e1c | ||
|  | 77056dcf8d | ||
|  | 026683a8e1 | ||
|  | 6ab6dd6ac3 | ||
|  | 83de3482ce | ||
|  | 919a35aed3 | ||
|  | ad3defb071 | ||
|  | 9c929ecd1b | ||
|  | f79c9f7cf1 | ||
|  | 8e75c345d9 | ||
|  | 44886d9aad | ||
|  | c2d444347d | ||
|  | 5cb497596d | ||
|  | 1857469d2f | ||
|  | ea71b4843d | ||
|  | 97727e2e3d | ||
|  | f81e7da8bb | ||
|  | 8e827bf83b | ||
|  | 9e1fa284ca | ||
|  | 3bf800be6e | ||
|  | 635b9f9dba | ||
|  | 52a0d7cf7b | ||
|  | a34516932b | ||
|  | 929a2a30a2 | ||
|  | ffa88eeb08 | ||
|  | 51b45b4ed4 | ||
|  | f263844793 | ||
|  | 18c46df9aa | ||
|  | 15846e157b | ||
|  | bc59f2db0d | ||
|  | cd2be8c1a4 | ||
|  | f958115c50 | ||
|  | e7d677bfb6 | ||
|  | 3e80ffc52b | ||
|  | d0c7a5c076 | ||
|  | f3f4e6b354 | ||
|  | 5a45b25614 | ||
|  | 0b5ee1edfc | ||
|  | da3dc599f9 | ||
|  | f013b435ab | ||
|  | 5f6975a113 | ||
|  | c5dee29e4b | ||
|  | 633ee02f13 | ||
|  | 6b750c909a | ||
|  | 5f8b6640a9 | ||
|  | dd42d8437c | ||
|  | 67a178591d | ||
|  | f5e5659c1f | ||
|  | 8b0f0fb615 | ||
|  | 209116e766 | ||
|  | 79392ab656 | ||
|  | 3ca1207231 | ||
|  | cec1b147f2 | ||
|  | 46cfcfa3e7 | ||
|  | b833e8dfa2 | ||
|  | 77b843efd8 | ||
|  | db72ad7c60 | ||
|  | eadc630fcb | ||
|  | 170c1793cc | ||
|  | 9f7c6c2d0c | ||
|  | 72d054c55c | ||
|  | 524edfe7c2 | ||
|  | c25c5623d2 | ||
|  | 4f38b77ef6 | ||
|  | 5862803434 | ||
|  | 5b3beded39 | ||
|  | c61fb7a598 | ||
|  | 33d9148029 | ||
|  | 63969f5a33 | ||
|  | edde18aeef | ||
|  | 657116d361 | ||
|  | e16269daa8 | ||
|  | c07591ff5c | ||
|  | 75a478ad54 | ||
|  | 8dae8b1a7f | ||
|  | 15fd8cf486 | ||
|  | 55333156ac | ||
|  | 8cdcba3231 | ||
|  | 8bab9e84e2 | ||
|  | 2faae83912 | ||
|  | 5a61a11a61 | ||
|  | a6d71988f2 | ||
|  | 7069e242ae | ||
|  | 56ee830558 | ||
|  | 6dd12729e6 | ||
|  | 14a48303cb | ||
|  | 72cf6c9c0f | ||
|  | 144ee6b8ca | ||
|  | 8967d86da6 | ||
|  | 18c6edbb5d | ||
|  | 53de3c4717 | ||
|  | ad577e4e81 | ||
|  | 44811a3e7c | ||
|  | 1ab3f05b3a | ||
|  | 5e76488ae7 | ||
|  | 32771fe7e1 | ||
|  | 9b40cc6881 | ||
|  | 2e35260bbb | ||
|  | a067704277 | ||
|  | de281818ac | ||
|  | c49bfad38d | ||
|  | c1ba591b26 | ||
|  | 719af38a61 | ||
|  | ac61dfae6b | ||
|  | 813fb679a7 | ||
|  | e7562781f7 | ||
|  | 56d36b7f53 | ||
|  | 53b3f7f821 | ||
|  | 08a53156bd | ||
|  | 8985cd6309 | ||
|  | 3833da7410 | ||
|  | 4210cd10db | ||
|  | a7bd1c6892 | ||
|  | 52b0111afa | ||
|  | 7921d128e4 | ||
|  | d7e838701a | ||
|  | 289bcb22aa | ||
|  | 3fe57b7983 | ||
|  | 32e92c2a16 | ||
|  | 1b3d208540 | ||
|  | 6a8bf0aa62 | ||
|  | 56715556ed | ||
|  | 838330b909 | ||
|  | 69553b138b | ||
|  | 36d7a02994 | ||
|  | 301528e2d2 | ||
|  | 0303b45707 | ||
|  | ba722e8ed5 | ||
|  | 289e5a5442 | ||
|  | fdad96e2bc | ||
|  | af994e4dae | ||
|  | 006d68e279 | ||
|  | 29dc122ad3 | ||
|  | cf4a8c6204 | ||
|  | 3c73fe92bf | ||
|  | 6637590797 | ||
|  | b8bab11acd | ||
|  | a2f600feac | ||
|  | 80dd62ef0a | ||
|  | 827b1c9cd8 | ||
|  | 2e4fcf803d | ||
|  | d00d95fc6f | ||
|  | 3e3ab9bd25 | ||
|  | 6eecc7722d | ||
|  | ada4aaf69a | ||
|  | 93244c1f78 | ||
|  | be056cea6b | ||
|  | 659ca8be14 | ||
|  | ea9af8366d | ||
|  | 80edd47d36 | ||
|  | d7746b3649 | ||
|  | c4c4fbc34c | ||
|  | 59f57c96e9 | ||
|  | a2f852fecf | ||
|  | ad114ed329 | ||
|  | c4c3d0f07f | ||
|  | 6cf8102de5 | ||
|  | e7e4aa2218 | ||
|  | 6d84f4b6c1 | ||
|  | ce3e9ffd11 | ||
|  | 3ada260e0e | ||
|  | 8fdd0cb795 | ||
|  | 913e05a2e6 | ||
|  | fa1f703ef6 | ||
|  | 4004c53e1b | ||
|  | 4838670649 | ||
|  | a985e09282 | ||
|  | 9bd1503cb4 | ||
|  | a2ccbf7844 | ||
|  | 61bbe8a905 | ||
|  | 59bc5d22d1 | ||
|  | 1423d5b314 | ||
|  | 152d0eb1d0 | ||
|  | 6426d1df06 | ||
|  | 9284eb3fe9 | ||
|  | afdae8bc1e | ||
|  | 2a7085e593 | ||
|  | 2408fb3ed4 | ||
|  | 8316afb176 | ||
|  | e59fd098a3 | ||
|  | e044199693 | ||
|  | 8f8e29fc22 | ||
|  | 8de5384158 | ||
|  | 216c659335 | ||
|  | 041ca8a5d3 | ||
|  | fe4f1b306d | ||
|  | a0972d99fb | ||
|  | e332bfef7c | ||
|  | cba5e226d8 | ||
|  | 5aff0c4943 | ||
|  | cb49c00f4d | ||
|  | e26d797d57 | ||
|  | 938581527e | ||
|  | c38ae09735 | ||
|  | 28c3cfe084 | ||
|  | 4a2823bcba | ||
|  | 18eba02026 | ||
|  | d4690ce580 | ||
|  | a785c450b1 | ||
|  | 7480dc4a19 | ||
|  | ad01891a67 | ||
|  | 67fe35d564 | ||
|  | 7f19b6957a | ||
|  | 0a54caf202 | ||
|  | 4b4c1c7f8f | ||
|  | d071f3947e | ||
|  | b3d99cd210 | ||
|  | 90e696f82c | ||
|  | 958fcd1cfa | ||
|  | 8f57c7dcb3 | ||
|  | 77262f52a4 | ||
|  | 16bfbc8a12 | ||
|  | 1fd375b875 | ||
|  | 46131ad39d | ||
|  | 0b5c5b2ae9 | ||
|  | 55be174037 | ||
|  | a17b7025f1 | ||
|  | 170cf7fd77 | ||
|  | 23cdb4d326 | ||
|  | cbbe529572 | ||
|  | 0b382426e9 | ||
|  | 1cbbf9baa4 | ||
|  | 8d41ff7b79 | ||
|  | e3b6057bf8 | ||
|  | 66a4042cad | ||
|  | 56c08d8302 | ||
|  | d4e759754d | ||
|  | a96e171cbf | ||
|  | bd4a8c8397 | ||
|  | 04f71b3b43 | ||
|  | d124de51db | ||
|  | d87d12a0f5 | ||
|  | f2b08346d0 | ||
|  | d3682a6727 | ||
|  | 371bbd9508 | ||
|  | a8a28f442f | ||
|  | 65ddd8a736 | ||
|  | 8bb27de233 | ||
|  | 37e2f097ba | ||
|  | 1966d87ce6 | ||
|  | 7b8c86e1e3 | ||
|  | de634da513 | ||
|  | 96836e2d6c | ||
|  | 8a9d576f61 | ||
|  | 791d12fbb4 | ||
|  | d1329be2fa | ||
|  | 3ed6561702 | ||
|  | 7a0587f433 | ||
|  | 0fe682bfe6 | ||
|  | 0f685e8789 | ||
|  | 420771c233 | ||
|  | 5e3e9271ca | ||
|  | 1e603c0833 | ||
|  | 03e1673e92 | ||
|  | 9f992f003d | ||
|  | f50244a41f | ||
|  | 8b9607f9b5 | ||
|  | af107ad5e8 | ||
|  | 8926d62165 | ||
|  | 45344ee347 | ||
|  | baf9ebab15 | ||
|  | b7dab817f2 | ||
|  | fb2fa54480 | ||
|  | 2c966a1234 | ||
|  | 143ea69c0d | ||
|  | 8a02ead013 | ||
|  | 930d5ab941 | ||
|  | e54a56d3a8 | ||
|  | f5216c0d85 | ||
|  | ebc77540b9 | ||
|  | 28d2583c10 | ||
|  | b0988a7b00 | ||
|  | 2c4920db2d | ||
|  | 8321663815 | ||
|  | ac0280d460 | ||
|  | ba6f4268f0 | ||
|  | 0bd18f94ac | ||
|  | 66fb63661f | ||
|  | d9b16beb0a | ||
|  | 6a01a9bdfd | ||
|  | b81b34a706 | ||
|  | 3750a00b5f | ||
|  | 05ddcc169d | ||
|  | f571a5f1bd | ||
|  | 48b786adea | ||
|  | d691fa9b4d | ||
|  | da50f9e419 | ||
|  | 103de5e18a | ||
|  | dac6efd98b | ||
|  | 46aa7f81b2 | ||
|  | 0683c7cd67 | ||
|  | 50d7aa7b6a | ||
|  | b781215d0a | ||
|  | 866bc2f3bd | ||
|  | 49d4705014 | ||
|  | 9163fcfccb | ||
|  | 7e10641461 | ||
|  | cdc0e3cfd8 | ||
|  | 466e81d56a | ||
|  | 5953f691d1 | ||
|  | e2790ca6c1 | ||
|  | 66dbd48b76 | ||
|  | 73cfbbd2ba | ||
|  | 38bc38bf26 | ||
|  | e12d13c838 | ||
|  | fcc3af6136 | ||
|  | 491298e1cb | ||
|  | 72b5895217 | ||
|  | 0a8f4017bd | ||
|  | cb985f5897 | ||
|  | 968ec0853f | ||
|  | 0bde72d3df | ||
|  | 45293fbd42 | ||
|  | 72997065f0 | ||
|  | a838dc163d | ||
|  | 3d15a4ca6d | ||
|  | 51c7d4fb1b | ||
|  | fa586dba7e | ||
|  | 8ad40389f2 | ||
|  | b3333cc2d3 | ||
|  | 3699a7ba9a | ||
|  | 204e521ba4 | ||
|  | c9bab3e5c3 | ||
|  | 3d00e20238 | ||
|  | c3958ed3c4 | ||
|  | e5b88be5fa | ||
|  | 425552988a | ||
|  | a81dd8abe5 | ||
|  | bac8154a5b | ||
|  | 737d15fa0e | ||
|  | 5f2317af7f | ||
|  | 2bd1f783e5 | ||
|  | d6c0c9f963 | ||
|  | 21b6ad7a41 | ||
|  | a65d609fdc | ||
|  | 04e676b936 | ||
|  | be8eaaffdf | ||
|  | 28c753523f | ||
|  | 7fbd0b2ffc | ||
|  | 7ffb48a87a | ||
|  | d485270e1f | ||
|  | 5fd688b266 | ||
|  | 3716668e0c | ||
|  | ae7fd18c34 | ||
|  | 4f59b1d32f | ||
|  | 90cb3279df | ||
|  | cf0c7ef6b2 | ||
|  | 47c23781d9 | ||
|  | e258c050f7 | ||
|  | 57801b2f34 | ||
|  | 710e9c9423 | ||
|  | deefef83bd | ||
|  | 51e30aed66 | ||
|  | 8d109a3cfe | ||
|  | 3424e019b5 | ||
|  | c6b4bceb67 | ||
|  | afb4155015 | ||
|  | 8d99baf38a | ||
|  | b91cb60328 | ||
|  | c0d62237fc | ||
|  | 223ea80860 | ||
|  | 5a77bef494 | ||
|  | 80c0efe821 | ||
|  | 8044d89557 | ||
|  | 4f0ed97410 | ||
|  | af7952f204 | ||
|  | d8dcae856b | ||
|  | 7296796ed9 | ||
|  | a2c2bb4948 | ||
|  | 72ebfdc20e | ||
|  | 16b95ea78a | ||
|  | c04f08dfd8 | ||
|  | a30793e818 | ||
|  | e39e1eaf21 | ||
|  | ab22d2cbaa | ||
|  | 96ddbe7227 | ||
|  | 4d09235aef | ||
|  | 136b8975e3 | ||
|  | e21b1eca17 | ||
|  | 244b90b1d4 | ||
|  | b318f3f940 | ||
|  | e211c9812e | ||
|  | eef28d96f4 | ||
|  | c8227e09ee | ||
|  | 3e05fd91d9 | ||
|  | 450baba56a | ||
|  | 17a8c4918c | ||
|  | 0e2419d61a | ||
|  | 79b1a2ca6d | ||
|  | 2213c68155 | ||
|  | 2492b1fa96 | ||
|  | 6c6598dac5 | ||
|  | a137112e66 | ||
|  | 8642ae8180 | ||
|  | 894c4dc5a7 | ||
|  | d96063ea6e | ||
|  | c3dc193f3e | ||
|  | 3c2952009e | ||
|  | f4ade470df | ||
|  | 2e33b43389 | ||
|  | 92799699bc | ||
|  | 7ab0508167 | ||
|  | 3c65c28936 | ||
|  | 43892da07e | ||
|  | 7c436920a4 | ||
|  | 89d565e63b | ||
|  | 150b6fe5b6 | ||
|  | 0e77574c26 | ||
|  | df23863443 | ||
|  | 581bf11b21 | ||
|  | d602d4b429 | ||
|  | d1d4a52934 | ||
|  | 375d113769 | ||
|  | 9b83974bff | ||
|  | 3c68c99bd5 | ||
|  | ec4b37c596 | ||
|  | ba9601d21c | ||
|  | 50c13fd469 | ||
|  | 7af072b8fc | ||
|  | faa128d41e | ||
|  | 868fe46932 | ||
|  | e9e4307ce5 | ||
|  | 774d4844a9 | ||
|  | 586c53e670 | ||
|  | 68e073fbff | ||
|  | 8101dc37b1 | ||
|  | 63f16c458d | ||
|  | 821e007e95 | ||
|  | 1656a2f11a | ||
|  | 4dbc135dce | ||
|  | fc886f6bc1 | ||
|  | f93e480466 | ||
|  | fe807e23f8 | ||
|  | ecf61c31f1 | ||
|  | 4feff18af5 | ||
|  | a07c52e0d8 | ||
|  | 7bb07d7f55 | ||
|  | f12dfc8a14 | ||
|  | be030f15c4 | ||
|  | f5fb6c063b | ||
|  | fb722f06b9 | ||
|  | c0ea19e15e | ||
|  | cdeb1ad87c | ||
|  | 0dbe4e94fa | ||
|  | b5e2e8aa1d | ||
|  | 9502010248 | ||
|  | fea0557b47 | ||
|  | ed4fcc9011 | ||
|  | ed12ea7cfb | ||
|  | 73e526645e | ||
|  | 72aeafb2b5 | ||
|  | cc1af60cb4 | ||
|  | 359fab315f | ||
|  | 6a9574bab9 | ||
|  | 83d6158483 | ||
|  | 63ef89b6cc | ||
|  | b0beab4cd3 | ||
|  | a34782575f | ||
|  | 142bdc9430 | ||
|  | 14b79cb0a4 | ||
|  | ce5beeaf2c | ||
|  | 31114a2ca5 | ||
|  | 32528094ad | ||
|  | 0a2a01c44c | ||
|  | c1888dc3ac | ||
|  | 4d76afbe01 | ||
|  | 76d7a97f93 | ||
|  | 8b1366b20a | ||
|  | e0f9685578 | ||
|  | 5235657954 | ||
|  | a15fbc8094 | ||
|  | 546f1d9c50 | ||
|  | 74231f552a | ||
|  | b250a10e3c | ||
|  | a9f1b31dd6 | ||
|  | 7fe393acaf | ||
|  | 04faba4db5 | ||
|  | 91bba40c20 | ||
|  | 79e39f7de8 | ||
|  | 9c09353559 | ||
|  | 50752a5bfe | ||
|  | d59879db7d | ||
|  | aab125da27 | ||
|  | 74fc731f96 | ||
|  | bd0050fec2 | ||
|  | aa5e313b92 | ||
|  | e89d613b7e | ||
|  | 8757929ead | ||
|  | e0a9b19802 | ||
|  | 308da6dc6e | ||
|  | b6960fb0e5 | ||
|  | 137208c3fd | ||
|  | d7a9a62a1d | ||
|  | 075315bdaa | ||
|  | 3948fcd614 | ||
|  | 8e61e129ab | ||
|  | 20cffd0502 | ||
|  | 5df09dab09 | ||
|  | 7446b911e5 | ||
|  | f15267c1ab | ||
|  | 9c9fc2b5dc | ||
|  | 28f601b54b | ||
|  | 18b8a05014 | ||
|  | 910c995ed8 | ||
|  | 498468aa2c | ||
|  | 637aebcb34 | ||
|  | 9afd5cb277 | ||
|  | bc525e7272 | ||
|  | a80180780d | ||
|  | 0d73086c37 | ||
|  | 02ae39238d | ||
|  | 43d6b51d42 | ||
|  | 84566310de | ||
|  | 6a6ec9fbe4 | ||
|  | 84a7f825d7 | ||
|  | 0372c1aaf1 | ||
|  | c9fff197f7 | ||
|  | 6900392e43 | ||
|  | c00bcd78cc | ||
|  | b2b82124e6 | ||
|  | 3de57c668f | ||
|  | 43669648ce | ||
|  | 3b73b416d5 | ||
|  | 5153591c8f | ||
|  | 3172bc90da | ||
|  | 76a1b2cd51 | ||
|  | bdf7eee72f | ||
|  | 2d4b148b2c | ||
|  | d67db74ca2 | ||
|  | 516725456f | ||
|  | 001d72a484 | ||
|  | c555e28988 | ||
|  | af13d1943f | ||
|  | 52df2edc8f | ||
|  | cd08484a13 | ||
|  | f38d38f139 | ||
|  | 93b6c68938 | ||
|  | a4cc25175a | ||
|  | 3fb14b4708 | ||
|  | 6bdb6db330 | ||
|  | d05c165ace | ||
|  | ab53cdb896 | ||
|  | c1f142af78 | ||
|  | 6e261abb73 | ||
|  | 39af9e4414 | ||
|  | 5b50abb2c7 | ||
|  | 13bda0a264 | ||
|  | 1658c666ab | ||
|  | 170aebfe54 | ||
|  | c4ef379d0e | ||
|  | 18b038d8ff | ||
|  | 12ee5da872 | ||
|  | 601f9f86bb | ||
|  | d7329a5915 | ||
|  | 9e7b730002 | ||
|  | 2d59d845bc | ||
|  | c2645894e0 | ||
|  | 3751106317 | ||
|  | 60bb639351 | ||
|  | 74c50930bd | ||
|  | 9105104303 | ||
|  | 540dde135e | ||
|  | f8936210cf | ||
|  | 1dc6d8de40 | ||
|  | 1069db3c13 | ||
|  | 65122f0144 | ||
|  | d2c018f7da | ||
|  | 46493c2af6 | ||
|  | c303e03f76 | ||
|  | d8b65f62e7 | ||
|  | 854368a8f3 | ||
|  | 7653a34aea | ||
|  | ee50b58e00 | ||
|  | 1eb60ab100 | ||
|  | 4a20eef351 | ||
|  | 26c9b2c353 | ||
|  | 16374bce9b | ||
|  | 86011d4ea2 | ||
|  | fcb8b02da9 | ||
|  | 571165c2bb | ||
|  | c842113610 | ||
|  | 974a8b3b70 | ||
|  | 2e20c99ada | ||
|  | aa88ff6f2c | ||
|  | 5e6aa63d03 | ||
|  | ad6700c114 | ||
|  | f08c6efb00 | ||
|  | cc807ec132 | ||
|  | 24e7c68243 | ||
|  | ab25edd37a | ||
|  | be47fde6c2 | ||
|  | 1ffa8c5e72 | ||
|  | d855ccb8a7 | ||
|  | d88919474b | ||
|  | e139664301 | ||
|  | 5adf5f6e3f | ||
|  | aef2075c8e | ||
|  | 922b2962a3 | ||
|  | b4a401700e | ||
|  | e9601bb9c1 | ||
|  | 58af3dc6ea | ||
|  | 074295df61 | ||
|  | ec349b31c7 | ||
|  | 5ae236e016 | ||
|  | d7c5897aba | ||
|  | 5252e7efe7 | ||
|  | fc7d65629a | ||
|  | f28fdf8252 | ||
|  | 5d07c4a949 | ||
|  | fdd9eaab4b | ||
|  | e0d863a46f | ||
|  | 3aacb6f5f3 | ||
|  | 428e331b3e | ||
|  | 847e05e9a7 | ||
|  | 087eb5dbe6 | ||
|  | f15932b2ac | ||
|  | d3a4c3795d | ||
|  | b15d55e1d9 | ||
|  | 4f5889cc5b | ||
|  | bf2a104a4e | ||
|  | 0c6dd5cd16 | ||
|  | 5efb06a7aa | ||
|  | b13acef272 | ||
|  | cfa67d6c0f | ||
|  | e70444f19a | ||
|  | 0258982e60 | ||
|  | 70eed5cb5e | ||
|  | a650fa51f7 | ||
|  | cb205580d8 | ||
|  | f9329aac00 | ||
|  | 745f4a7523 | ||
|  | 60254dafd7 | ||
|  | a8d60388ba | ||
|  | 83ec60254c | ||
|  | c15c45f765 | ||
|  | cbe52b5089 | ||
|  | e4e2921f3e | ||
|  | 4673170531 | ||
|  | 2c2ed26c38 | ||
|  | 94be5244fe | ||
|  | f137a08493 | ||
|  | 48624d0a34 | ||
|  | 4cceb3ddaa | ||
|  | f728395603 | ||
|  | 3e82d43807 | ||
|  | 2194c4e0a9 | ||
|  | c581080f3f | ||
|  | f6b1ec27e5 | ||
|  | 368b183230 | ||
|  | 9028ad36ad | ||
|  | 6cc041cd39 | ||
|  | 63ff01e78d | ||
|  | 9e5484937e | ||
|  | b8ed489b14 | ||
|  | 765152d04b | ||
|  | 14934367d8 | ||
|  | 04164500c8 | ||
|  | 5160f2c298 | ||
|  | 124c9303b9 | ||
|  | cd27f0ad69 | ||
|  | a7555bcce3 | ||
|  | 6b5c4fd3f4 | ||
|  | cc55e2acee | ||
|  | 1511f75a80 | ||
|  | f01bbefc1f | ||
|  | 1d1eb5ffa8 | ||
|  | a465cb2191 | ||
|  | 42d13e02ef | ||
|  | d00786c43f | ||
|  | 4b47f99829 | ||
|  | 35aaf40003 | ||
|  | cc5b4a1e02 | ||
|  | 7079521e8c | ||
|  | b5025560a5 | ||
|  | 3f4bdd7f0e | ||
|  | e94bb9b549 | ||
|  | 1ddaacbef5 | ||
|  | e8b40518e0 | ||
|  | 0f88cbb41b | ||
|  | 780d137b76 | ||
|  | ad8a9717d1 | ||
|  | 9d6ea6b2f6 | ||
|  | 7559383089 | ||
|  | f84381c927 | ||
|  | cb0122a43f | ||
|  | 6776b20989 | ||
|  | e98d556022 | ||
|  | 5bf18b69d7 | ||
|  | ea17f045a7 | ||
|  | 526f565ea7 | ||
|  | 4aff9d6e73 | ||
|  | bf516d4d21 | ||
|  | ae92e409d9 | ||
|  | 4d017dc8a9 | ||
|  | 707f4e2965 | ||
|  | 1c3bffdc50 | ||
|  | e54ddcb8b0 | ||
|  | ddefb0debc | ||
|  | 92d8dde90d | ||
|  | 1bb0508ddf | ||
|  | a280a326b9 | ||
|  | 683e9b7c2c | ||
|  | a44e5da421 | ||
|  | 8cd2c90ad7 | ||
|  | 5e57a390a2 | ||
|  | 620848272e | ||
|  | 1e86794416 | ||
|  | e36717259b | ||
|  | 75b9238b90 | ||
|  | ce5b20027e | ||
|  | 0de1242c83 | ||
|  | 8bd445ab19 | ||
|  | fdef0de163 | ||
|  | b1b03a4325 | ||
|  | 0587d96474 | ||
|  | c2241567e4 | ||
|  | 7ac24ba418 | ||
|  | c933ffec66 | ||
|  | e587d934b1 | ||
|  | f354e90656 | ||
|  | 1b0bc7ec6e | ||
|  | ee1acb9c00 | ||
|  | 06862a2812 | ||
|  | 5fa87e18db | ||
|  | 77989e2720 | ||
|  | 3a1102fa4e | ||
|  | 8a9974ce53 | ||
|  | 4be8f1ca03 | ||
|  | 1ec2970ee3 | ||
|  | 81b3a22606 | ||
|  | f81a475cc9 | ||
|  | d7ee03d4f9 | ||
|  | c1c06410c2 | ||
|  | 657d16bb60 | ||
|  | e65a4c1010 | ||
|  | e23d3f5661 | ||
|  | e13611f7af | ||
|  | 596cd09489 | ||
|  | 0be5b27d34 | ||
|  | a27471ae55 | ||
|  | e27e3622a8 | ||
|  | e95273b72b | ||
|  | 583d4f3249 | ||
|  | d6967c4516 | ||
|  | 40b3097374 | ||
|  | 1a1f127993 | ||
|  | a0f34a7ce1 | ||
|  | db020db34b | ||
|  | 681167bc1b | ||
|  | 40e49ffc37 | ||
|  | 834b1afb38 | ||
|  | 62d5a1da87 | ||
|  | 8d8308e557 | ||
|  | e1aa63487a | ||
|  | b7fbe110d4 | ||
|  | 58859eb35a | ||
|  | 4b7e1ae1c6 | ||
|  | 3a06a6ac07 | ||
|  | db0f269dc8 | ||
|  | 3cabe6ca5a | ||
|  | d483005219 | ||
|  | fea9bc4e7e | ||
|  | d579992c98 | ||
|  | ad1c61d959 | ||
|  | bb1da31830 | ||
|  | a50949e554 | ||
|  | 14dce8a10b | ||
|  | 1240c8f685 | ||
|  | cc7c2e952c | ||
|  | 409ec2e086 | ||
|  | a7f6848e53 | ||
|  | 4b0b79199d | ||
|  | d1d6c48d9b | ||
|  | 21631780bb | ||
|  | b935e32340 | ||
|  | 72dd064932 | ||
|  | 2e75446665 | ||
|  | be17e4481e | ||
|  | 616c849b1f | ||
|  | 71947c097f | ||
|  | 546787802d | ||
|  | 294d0e388a | ||
|  | 193a1b0325 | ||
|  | 12743217a2 | ||
|  | b252b9da66 | ||
|  | cdef9c3c7e | ||
|  | 71dcebb744 | ||
|  | 25f248c60a | ||
|  | d5cbc17831 | ||
|  | 7a10217511 | ||
|  | 7559efab77 | ||
|  | 8254efbd03 | ||
|  | 4ae24225a5 | ||
|  | 67d9154563 | ||
|  | ad0319c188 | ||
|  | eb650ea3ec | ||
|  | 7eba33e805 | ||
|  | e1cb9d387e | ||
|  | 2ace7c3ca0 | ||
|  | 58014f0592 | ||
|  | 1d4938bb09 | ||
|  | bbf4007c3e | ||
|  | 4d5124fb4c | ||
|  | 14a7cd05b1 | ||
|  | 946be80eef | ||
|  | 9ad8b1a980 | ||
|  | f733216fcb | ||
|  | ffc6139e21 | ||
|  | 571cac6644 | ||
|  | 2738ac5a5c | ||
|  | 7dfde51b84 | ||
|  | 2d2f18e538 | ||
|  | 3af0dd2e3b | ||
|  | 349e077802 | ||
|  | 812aae358f | ||
|  | c3c59d0627 | ||
|  | 89518b412d | ||
|  | f43b026162 | ||
|  | b806c70f52 | ||
|  | 10bff3c0b8 | ||
|  | 65c12fd0b2 | ||
|  | 50f71c4130 | ||
|  | 8e401a53dc | ||
|  | 64a289a47c | ||
|  | 8f2c37061b | ||
|  | 39f2de6b90 | ||
|  | 855ba8d4f3 | ||
|  | 74f098e718 | ||
|  | 56c8a84691 | ||
|  | 8bbf319032 | ||
|  | afbca4ae65 | ||
|  | 0ef6d2f91a | ||
|  | fbe4435599 | ||
|  | 34be565dd1 | ||
|  | af838e4ed1 | ||
|  | 60fe8ce011 | ||
|  | 8ece341467 | ||
|  | dfa6bdbcb8 | ||
|  | fb2481ebaa | ||
|  | 4874c116cf | ||
|  | e19c44efbd | ||
|  | 4b687b9bdc | ||
|  | 6af79ef601 | ||
|  | 352b996ad2 | ||
|  | 4a93bb35f8 | ||
|  | 8e1f493daf | ||
|  | 59ee153375 | ||
|  | 60f7f1fc16 | ||
|  | b7433683d8 | ||
|  | 42799b9273 | ||
|  | 860a0f790e | ||
|  | 8daccbfbb4 | ||
|  | 285b77dcb7 | ||
|  | 6e48827d3f | ||
|  | f0c20cc706 | ||
|  | 8916c0a3de | ||
|  | 7193a77840 | ||
|  | 61930b5b51 | ||
|  | 11a494cacf | ||
|  | 17f9bf0339 | ||
|  | 3d9755ca8c | ||
|  | b5cf2d03e6 | ||
|  | e3b35b8f35 | ||
|  | 1c1fe672bd | ||
|  | 6c71f68ed8 | ||
|  | 8f2f912cdf | ||
|  | bf6ea16acb | ||
|  | 288546c2b9 | ||
|  | 724db6c34c | ||
|  | 067c451c1d | ||
|  | 11e3696191 | ||
|  | 41e20664de | ||
|  | d8de90d6f3 | ||
|  | b01e8299d3 | ||
|  | 1ec11e3e2e | ||
|  | 422f429725 | ||
|  | 5c55fa5fbb | ||
|  | 80d845fdf2 | ||
|  | 601fe68346 | ||
|  | 9e050fb059 | ||
|  | 99d4adf5e6 | ||
|  | 85f8d1e8e9 | ||
|  | 8334d3d99f | ||
|  | cff08d19eb | ||
|  | 2d86390bc1 | ||
|  | 7a20835571 | ||
|  | ff3c9676b5 | ||
|  | 055f97dab1 | ||
|  | 8a867e71a1 | ||
|  | b8275b4734 | ||
|  | 36b951b146 | ||
|  | c5a5f17643 | ||
|  | 16b909c4df | ||
|  | 92b7648e03 | ||
|  | ca46ebe3b2 | ||
|  | 676e48254a | ||
|  | b15b55227d | ||
|  | 3c3b723913 | ||
|  | f05002c729 | ||
|  | 1c2cbd5b40 | ||
|  | 54c6ca9f45 | ||
|  | c10efbb170 | ||
|  | a496ad5814 | ||
|  | 50cf7f6a3b | ||
|  | f946f10afd | ||
|  | eecb4db34c | ||
|  | 1f865d3ea4 | ||
|  | 623bb4b350 | ||
|  | dc8ad673a6 | ||
|  | 4914ad821e | ||
|  | f099cbadc3 | ||
|  | 42cda384c8 | ||
|  | 23c91b9990 | ||
|  | ff0379182e | ||
|  | e08a23948f | ||
|  | bd56de6d36 | ||
|  | 42970aea80 | ||
|  | 003a05ee8d | ||
|  | ffb11b01a6 | ||
|  | e426f5d5da | ||
|  | 6989f61e1b | ||
|  | 0e6677ccb3 | ||
|  | 8f104d555a | ||
|  | b1d3158db1 | ||
|  | 7645005d5a | ||
|  | 411f77fd29 | ||
|  | 568ab26db1 | ||
|  | 29652108f0 | ||
|  | f07e4dc711 | ||
|  | 8a2ac457c2 | ||
|  | 9e54eecfaa | ||
|  | 95ef691077 | ||
|  | 7a0ad5a587 | ||
|  | 42b49d0e4b | ||
|  | 9217c2f003 | ||
|  | fbdf66998d | ||
|  | deda9d3c54 | ||
|  | a5d78f20ae | ||
|  | 5ed09e3f38 | ||
|  | 3e9774cd66 | ||
|  | 54387c8fdf | ||
|  | 7eec949a13 | ||
|  | 4113c4ff40 | ||
|  | 1bf0968bfe | ||
|  | 374b90fb00 | ||
|  | 064e60e9d5 | ||
|  | b637455970 | ||
|  | 68158937d1 | ||
|  | adb1356b7a | ||
|  | d880ccb8e0 | ||
|  | 050fb1d1ef | ||
|  | 6580752bde | ||
|  | c9df265c9b | ||
|  | 098e5bc162 | ||
|  | 4b2dcc74d4 | ||
|  | a9254c5c9a | ||
|  | 7ce57e6ccb | ||
|  | 0fcb32a66f | ||
|  | 9946535f01 | ||
|  | 2b17396d6b | ||
|  | b01d5bc237 | ||
|  | b123860304 | ||
|  | 033f5b67db | ||
|  | 6280448dfb | ||
|  | 01cd3333e4 | ||
|  | 63050907b9 | ||
|  | beedf7d780 | ||
|  | 6b8194261f | ||
|  | dbb1c4d534 | ||
|  | e6263f9ff5 | ||
|  | 6ca119c4db | ||
|  | c483a1ab3a | ||
|  | 2e7edd033c | ||
|  | c576902501 | ||
|  | 66c2951594 | ||
|  | b812881cdb | ||
|  | cdeac2c6db | ||
|  | bca2ddd529 | ||
|  | e7285c6499 | ||
|  | bdff275672 | ||
|  | bec58a1ee6 | ||
|  | f64616748c | ||
|  | 512ce15973 | ||
|  | ed8b301574 | ||
|  | d22a6c019c | ||
|  | a0cb1b9d9e | ||
|  | a5294c62ea | ||
|  | e155d3311c | ||
|  | 0a372b0daf | ||
|  | 69143399d1 | ||
|  | 3270d3bf96 | ||
|  | 3896a66122 | ||
|  | b94781aef1 | ||
|  | bed1adc367 | ||
|  | ae54497efa | ||
|  | 06b747c221 | ||
|  | f159beee0d | ||
|  | 49d7dea086 | ||
|  | 3e65733dc5 | ||
|  | cc375d58bb | ||
|  | 911c7c662a | ||
|  | aae003be33 | ||
|  | aede03d8b2 | ||
|  | f0f5ada7de | ||
|  | 58365121a3 | ||
|  | d5a154d2e6 | ||
|  | b20f369aef | ||
|  | abb8aa0b29 | ||
|  | 5368a0f1d7 | ||
|  | d3897eece7 | ||
|  | a82b829da9 | ||
|  | 9f5058e81a | ||
|  | 5b19263720 | ||
|  | 9d5a0db0d9 | ||
|  | 4bd8a7014f | ||
|  | 353e96d951 | ||
|  | 149a6f92b0 | ||
|  | d66426c137 | ||
|  | 4fc9966392 | ||
|  | 417766f0db | ||
|  | de9ac97887 | ||
|  | 6be42f112a | ||
|  | 3895ae63c7 | ||
|  | 607d416d54 | ||
|  | 038693dc86 | ||
|  | cc9be13544 | ||
|  | 9c1474087f | ||
|  | 831de2bcf4 | ||
|  | eb687333bb | ||
|  | 5cc7966d54 | ||
|  | d1a34e7a6f | ||
|  | d63d791717 | ||
|  | 015570c741 | ||
|  | 8400ebc9c6 | ||
|  | 9f99e7c0af | ||
|  | 392c1fc399 | ||
|  | d3cea7a89c | ||
|  | 1dcf7407e6 | ||
|  | d543c033a3 | ||
|  | aaa186be5e | ||
|  | 2054b5b3dd | ||
|  | 98ae5b0ca0 | ||
|  | 36c8171d0f | ||
|  | 3603eb94cc | ||
|  | 0e068d4ccf | ||
|  | 199f348ff4 | ||
|  | b22655fb7c | ||
|  | 06cc9618ba | ||
|  | b9019c8c7f | ||
|  | 77e133e67c | ||
|  | 571e7df807 | ||
|  | 22f4d2979a | ||
|  | e46e366694 | ||
|  | 7b4bc23815 | ||
|  | 9ca79f767c | ||
|  | 274dba7408 | ||
|  | 31708ca29e | ||
|  | 671b025588 | ||
|  | a7956e4856 | ||
|  | 355862025a | ||
|  | a2a39ee0f8 | ||
|  | ec8e39c16f | ||
|  | 88f714999e | ||
|  | c0c2aa3be0 | ||
|  | 822044820e | ||
|  | 6ffc182142 | ||
|  | 3d54a78573 | ||
|  | 8ddf7d953a | ||
|  | 8b9e9ad103 | ||
|  | 5737224c40 | ||
|  | ec9aacbcae | ||
|  | 9395454997 | ||
|  | 66198a8d98 | ||
|  | 96ed9a4256 | ||
|  | 10e54b2263 | ||
|  | cf00922ad2 | ||
|  | 84e8e007a5 | ||
|  | d07b2e773b | ||
|  | 506ef7b0b9 | ||
|  | 2cd5dae8e2 | ||
|  | a1cd49c111 | ||
|  | aca2973aef | ||
|  | 0a7a691c95 | ||
|  | 72906a7afd | ||
|  | d1a4a83570 | ||
|  | e0396b29e8 | ||
|  | 536833cfe0 | ||
|  | 317b02d1b9 | ||
|  | 75e279ea0d | ||
|  | dc2ad21f4c | ||
|  | 484d49aae1 | ||
|  | ca39438ad4 | ||
|  | 49a65ebff4 | ||
|  | befdc05084 | ||
|  | 1fbffe761b | 
							
								
								
									
										25
									
								
								.codeclimate.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.codeclimate.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| # Save as .codeclimate.yml (note leading .) in project root directory | ||||
| languages: | ||||
|   JavaScript: true | ||||
|   PHP: true | ||||
| exclude_paths: | ||||
| - "public/packages/maximebf/php-debugbar/debugbar.js" | ||||
| - "public/packages/maximebf/php-debugbar/widgets.js" | ||||
| - "public/packages/maximebf/php-debugbar/openhandler.js" | ||||
| - "public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js" | ||||
| - "public/js/bootstrap3-typeahead.min.js" | ||||
| - "public/js/bootstrap-sortable.js" | ||||
| - "public/js/bootstrap-tagsinput.min.js" | ||||
| - "public/js/bootstrap-tagsinput.min.js.map" | ||||
| - "public/js/daterangepicker.js" | ||||
| - "public/js/jquery-2.1.3.min.js" | ||||
| - "public/js/jquery-2.1.3.min.js.map" | ||||
| - "public/js/jquery-ui.min.js" | ||||
| - "public/js/metisMenu.js" | ||||
| - "public/js/moment.min.js" | ||||
| - "public/js/sb-admin-2.js" | ||||
| - "public/bootstrap/*" | ||||
| - "resources/lang/*" | ||||
| - "tests/*" | ||||
| - "database/*" | ||||
| - "storage/*" | ||||
| @@ -1,3 +1 @@ | ||||
| src_dir: . | ||||
| coverage_clover: storage/coverage/clover.xml | ||||
| json_path: storage/coverage/coveralls-upload.json | ||||
|   | ||||
							
								
								
									
										14
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								.env.example
									
									
									
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| APP_ENV=production | ||||
| APP_DEBUG=false | ||||
| APP_KEY=SomeRandomString | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=localhost | ||||
| @@ -11,8 +12,19 @@ DB_PASSWORD=secret | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
| DEFAULT_CURRENCY=EUR | ||||
| DEFAULT_LANGUAGE=en_US | ||||
|  | ||||
| EMAIL_SMTP= | ||||
| EMAIL_DRIVER=smtp | ||||
| EMAIL_USERNAME= | ||||
| EMAIL_PASSWORD= | ||||
| EMAIL_PRETEND=false | ||||
|  | ||||
| SHOW_INCOMPLETE_TRANSLATIONS=false | ||||
|  | ||||
| ANALYTICS_ID= | ||||
| RUNCLEANUP=true | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| BLOCKED_DOMAINS= | ||||
| @@ -15,3 +15,4 @@ EMAIL_SMTP= | ||||
| EMAIL_USERNAME= | ||||
| EMAIL_PASSWORD= | ||||
| ANALYTICS_ID=ABC | ||||
| EMAIL_PRETEND=true | ||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -5,7 +5,7 @@ Thumbs.db | ||||
| .idea/ | ||||
| tests/_output/* | ||||
| _ide_helper.php | ||||
| /build/logs/clover.xml | ||||
| /build/logs | ||||
| index.html* | ||||
| app/storage/firefly-export* | ||||
| .vagrant | ||||
| @@ -31,3 +31,6 @@ addNewLines.php | ||||
| .phpstorm.meta.php | ||||
| .env.backup | ||||
| .env.local | ||||
|  | ||||
| tests/_output/* | ||||
| tests/_output/* | ||||
|   | ||||
							
								
								
									
										22
									
								
								.jshintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.jshintrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| { | ||||
|   "undef": true, | ||||
|   "unused": false, | ||||
|   "strict": true, | ||||
|   "browser": true, | ||||
|   "jquery": true, | ||||
|   "devel": true, | ||||
|   "globals": [ | ||||
|     "language", | ||||
|     "token", | ||||
|     "currencyCode", | ||||
|     "$", | ||||
|     "token", | ||||
|     "accountID", | ||||
|     "billID", | ||||
|     "currentMonthName", | ||||
|     "previousMonthName", | ||||
|     "nextMonthName", | ||||
|     "everything", | ||||
|     "moment" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										3
									
								
								.scrutinizer.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.scrutinizer.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # .scrutinizer.yml | ||||
| tools: | ||||
|   external_code_coverage: false | ||||
							
								
								
									
										10
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -6,17 +6,13 @@ php: | ||||
|   - 5.5 | ||||
|   - 5.6 | ||||
|  | ||||
| addons: | ||||
|   code_climate: | ||||
|     repo_token: 26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61 | ||||
|  | ||||
| install: | ||||
|   - composer update | ||||
|   - php artisan env | ||||
|   - mv -v .env.testing .env | ||||
|   - touch storage/database/testing.db | ||||
|   - php artisan migrate --env=testing | ||||
|   - php artisan migrate --seed --env=testing | ||||
|  | ||||
| script: | ||||
|   - phpunit | ||||
|  | ||||
| after_script: | ||||
|   - php vendor/bin/coveralls | ||||
|   | ||||
							
								
								
									
										152
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,88 +1,130 @@ | ||||
| Firefly III (v3.4.0.3) | ||||
| =========== | ||||
| # Firefly III | ||||
|  | ||||
| [](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://coveralls.io/r/JC5/firefly-iii?branch=master) | ||||
| [](https://coveralls.io/r/JC5/firefly-iii?branch=develop) | ||||
| [](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) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) | ||||
| [](https://scrutinizer-ci.com/g/JC5/firefly-iii/build-status/master) | ||||
|  | ||||
| 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). | ||||
| ## About | ||||
|  | ||||
| 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. | ||||
| "Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared  | ||||
| household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money. | ||||
|   | ||||
| 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). | ||||
| Personal financial management is pretty difficult, and everybody has their own approach to it. Some people | ||||
| make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase | ||||
| their current cashflow. There are tons of ways to save and earn money. | ||||
|  | ||||
| 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)**. | ||||
| Firefly works on the principle that if you know where you're money is going, you can stop it from going there. | ||||
|  | ||||
| If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/). This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. | ||||
| To get to know Firefly, and to see if it fits you, check out these resources: | ||||
|  | ||||
| - The screenshots below on this very page. | ||||
| - The featurelist below, also on this very page. | ||||
| - The [full description](https://github.com/JC5/firefly-iii/wiki/full-description), which will tell you how Firefly works, | ||||
| and the philosophy behind it. | ||||
|  | ||||
| #### A quick technical overview | ||||
|  | ||||
| Firefly is a system you'll have install yourself on webhosting of your choosing. It needs PHP and MySQL. The current version of Firefly III requires PHP 5.6.4 or | ||||
| higher. Soon, this will be PHP 7.0.0 or higher. | ||||
|  | ||||
|  | ||||
| #### About the name (should you care) | ||||
|  | ||||
| It's III, or 3, because [version 2](https://github.com/JC5/Firefly) and version 1 (not online) preceded it. It has been growing steadily ever since. | ||||
|  | ||||
| ## Current features | ||||
|  | ||||
| - [A double-entry bookkeeping system](https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system); | ||||
| - You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management; | ||||
| - You can manage different types of accounts | ||||
|   - Asset accounts | ||||
|   - Shared asset accounts (household accounts) | ||||
| - You can store, edit and remove [withdrawals, deposits and transfers](https://en.wikipedia.org/wiki/Financial_transaction). This allows you full financial management; | ||||
| - You can manage different types of accounts; | ||||
|   - [Asset](https://en.wikipedia.org/wiki/Asset) accounts | ||||
|   - Shared [asset accounts](https://en.wikipedia.org/wiki/Asset) ([household accounts](https://en.wikipedia.org/wiki/Household)) | ||||
|   - Saving accounts | ||||
|   - Credit cards | ||||
| - It's possible to create, change and manage money using _[budgets](https://en.wikipedia.org/wiki/Envelope_system)_; | ||||
| - 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; | ||||
| - Save towards a goal using [piggy banks](https://en.wikipedia.org/wiki/Piggy_bank); | ||||
| - Predict and anticipate [bills](https://en.wikipedia.org/wiki/Invoice); | ||||
| - View income / expense [reports](https://en.wikipedia.org/wiki/Financial_statement); | ||||
| - Organize expenses using tags; | ||||
| - 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, but does not feature yet: | ||||
|  | ||||
|  | ||||
| - More control over other resources outside of personal finance | ||||
|   - Debts | ||||
| - 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. | ||||
| - Any other features I might not have thought of. | ||||
|  | ||||
| Some stuff has been removed: | ||||
|  | ||||
| - The nesting of budgets, categories and beneficiaries is removed because it was pretty pointless. | ||||
| - Lots of charts because we all love them; | ||||
| - Financial reporting showing you how well you are doing. | ||||
|  | ||||
| ## Screenshots | ||||
|  | ||||
|  | ||||
| _Please note that everything in these screenshots is fictional and may not be realistic._ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Running and installing | ||||
|  | ||||
| If you're still interested 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)**. | ||||
|   | ||||
| If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).  | ||||
| This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. Accounts on the demo sites will stop working after one month. It's a trial. | ||||
|  | ||||
| ## Security | ||||
|  | ||||
| You should always run Firefly III on a site with TLS enabled (https://). Please note that although some parts of the | ||||
| database are encrypted (transaction descriptions, names, etc.) some parts are _not_ (amounts, dates, etc). If you need | ||||
| more security, you must enable transparent database encryption or a comparable technology. Please remember that this | ||||
| is open source software under active development, and it is in no way guaranteed to be safe or secure. | ||||
|  | ||||
| ## Translations | ||||
|  | ||||
| Firefly III is currently available in Dutch and English. Support for other languages is being worked on. I could use | ||||
| your help. Checkout [Crowdin](https://crowdin.com/project/firefly-iii) for more information. | ||||
|  | ||||
| ## Credits | ||||
|  | ||||
| Firefly III uses the following libraries and tools: | ||||
|  | ||||
| * The AdminLTE template by [Almsaseed Studio](https://almsaeedstudio.com/) | ||||
| * The [Google charts](https://developers.google.com/chart/) library. | ||||
| * [Chart.js](http://www.chartjs.org/) | ||||
| * [Bootstrap](http://getbootstrap.com/) | ||||
| * [Laravel](http://laravel.com/) | ||||
| * [Twig](http://twig.sensiolabs.org/) | ||||
| * For development, some of the excellent tools made by [Barry van den Heuvel](https://github.com/barryvdh) | ||||
| * [Bootstrap sortable](https://github.com/drvic10k/bootstrap-sortable) by [Matúš Brliť](https://github.com/drvic10k). | ||||
| * [Date range picker](https://github.com/dangrossman/bootstrap-daterangepicker/) by [Dan Grossman](https://github.com/dangrossman) | ||||
| * The [real favicon generator](http://realfavicongenerator.net/) | ||||
| * Various other open source components (see [composer.json](https://github.com/JC5/firefly-iii/blob/master/composer.json)) | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Current state | ||||
| I have the basics up and running. Test coverage is currently coming, slowly. | ||||
|  | ||||
| Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! | ||||
| Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. Translations are a work in progress. | ||||
|  | ||||
| Questions, ideas, bugs or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! | ||||
|  | ||||
| If you like this tool, feel free to [donate me some beer money](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2ZMV952UUSCLU&lc=NL&item_name=Development%20of%20Firefly¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted). | ||||
|  | ||||
| [](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) | ||||
| [](https://codeclimate.com/github/JC5/firefly-iii) | ||||
| [](http://stillmaintained.com/JC5/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| /** | ||||
|  * Class Command | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Commands | ||||
|  */ | ||||
| abstract class Command | ||||
|   | ||||
| @@ -6,6 +6,7 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel; | ||||
| /** | ||||
|  * Class Kernel | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Console | ||||
|  */ | ||||
| class Kernel extends ConsoleKernel | ||||
| @@ -25,6 +26,8 @@ class Kernel extends ConsoleKernel | ||||
|      * | ||||
|      * @param  \Illuminate\Console\Scheduling\Schedule $schedule | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     protected function schedule(Schedule $schedule) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| /** | ||||
|  * Class Event | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| abstract class Event | ||||
|   | ||||
| @@ -6,6 +6,7 @@ use Illuminate\Queue\SerializesModels; | ||||
| /** | ||||
|  * Class JournalCreated | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| class JournalCreated extends Event | ||||
|   | ||||
| @@ -1,24 +0,0 @@ | ||||
| <?php namespace FireflyIII\Events; | ||||
|  | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class JournalDeleted | ||||
|  * | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| class JournalDeleted extends Event | ||||
| { | ||||
|  | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -6,6 +6,7 @@ use Illuminate\Queue\SerializesModels; | ||||
| /** | ||||
|  * Class JournalSaved | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| class JournalSaved extends Event | ||||
|   | ||||
| @@ -6,6 +6,7 @@ namespace FireflyIII\Exceptions; | ||||
| /** | ||||
|  * Class FireflyException | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Exceptions | ||||
|  */ | ||||
| class FireflyException extends \Exception | ||||
|   | ||||
| @@ -2,10 +2,12 @@ | ||||
|  | ||||
| use Exception; | ||||
| use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; | ||||
| use Symfony\Component\HttpKernel\Exception\HttpException; | ||||
|  | ||||
| /** | ||||
|  * Class Handler | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Exceptions | ||||
|  */ | ||||
| class Handler extends ExceptionHandler | ||||
| @@ -26,12 +28,13 @@ class Handler extends ExceptionHandler | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Exception               $e | ||||
|      * @SuppressWarnings(PHPMD.ShortVariable) | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function render($request, Exception $e) | ||||
|     { | ||||
|         if ($this->isHttpException($e)) { | ||||
|         if ($e instanceof HttpException) { | ||||
|             return $this->renderHttpException($e); | ||||
|         } else { | ||||
|             return parent::render($request, $e); | ||||
| @@ -42,6 +45,7 @@ class Handler extends ExceptionHandler | ||||
|      * Report or log an exception. | ||||
|      * | ||||
|      * This is a great spot to send exceptions to Sentry, Bugsnag, etc. | ||||
|      * @SuppressWarnings(PHPMD.ShortVariable) | ||||
|      * | ||||
|      * @param  \Exception $e | ||||
|      * | ||||
|   | ||||
| @@ -5,6 +5,7 @@ namespace FireflyIII\Exceptions; | ||||
| /** | ||||
|  * Class NotImplementedException | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Exceptions | ||||
|  */ | ||||
| class NotImplementedException extends \Exception | ||||
|   | ||||
| @@ -4,6 +4,7 @@ namespace FireflyIII\Exceptions; | ||||
| /** | ||||
|  * Class ValidationExceptions | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Exception | ||||
|  */ | ||||
| class ValidationException extends \Exception | ||||
|   | ||||
							
								
								
									
										43
									
								
								app/Generator/Chart/Account/AccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Generator/Chart/Account/AccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface AccountChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Account | ||||
|  */ | ||||
| interface AccountChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end); | ||||
| } | ||||
							
								
								
									
										187
									
								
								app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsAccountChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Account | ||||
|  */ | ||||
| class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'  => 1, | ||||
|             'labels' => [], 'datasets' => [[ | ||||
|                                                'label' => trans('firefly.spent'), | ||||
|                                                'data'  => []]]]; | ||||
|  | ||||
|         bcscale(2); | ||||
|         $start->subDay(); | ||||
|         $ids           = $this->getIdsFromCollection($accounts); | ||||
|         $startBalances = Steam::balancesById($ids, $start); | ||||
|         $endBalances   = Steam::balancesById($ids, $end); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($startBalances, $endBalances) { | ||||
|                 $id                  = $account->id; | ||||
|                 $startBalance        = $this->isInArray($startBalances, $id); | ||||
|                 $endBalance          = $this->isInArray($endBalances, $id); | ||||
|                 $diff                = bcsub($endBalance, $startBalance); | ||||
|                 $account->difference = round($diff, 2); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $accounts = $accounts->sortByDesc( | ||||
|             function (Account $account) { | ||||
|                 return $account->difference; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             if ($account->difference > 0) { | ||||
|                 $data['labels'][]              = $account->name; | ||||
|                 $data['datasets'][0]['data'][] = $account->difference; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $array | ||||
|      * @param $entryId | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function isInArray($array, $entryId) | ||||
|     { | ||||
|         if (isset($array[$entryId])) { | ||||
|             return $array[$entryId]; | ||||
|         } | ||||
|  | ||||
|         return '0'; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|         $format  = trans('config.month_and_day'); | ||||
|         $data    = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         $current = clone $start; | ||||
|         while ($current <= $end) { | ||||
|             $data['labels'][] = $current->formatLocalized($format); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $set      = [ | ||||
|                 'label'                => $account->name, | ||||
|                 'fillColor'            => 'rgba(220,220,220,0.2)', | ||||
|                 'strokeColor'          => 'rgba(220,220,220,1)', | ||||
|                 'pointColor'           => 'rgba(220,220,220,1)', | ||||
|                 'pointStrokeColor'     => '#fff', | ||||
|                 'pointHighlightFill'   => '#fff', | ||||
|                 'pointHighlightStroke' => 'rgba(220,220,220,1)', | ||||
|                 'data'                 => [], | ||||
|             ]; | ||||
|             $current  = clone $start; | ||||
|             $range    = Steam::balanceInRange($account, $start, clone $end); | ||||
|             $previous = array_values($range)[0]; | ||||
|             while ($current <= $end) { | ||||
|                 $format  = $current->format('Y-m-d'); | ||||
|                 $balance = isset($range[$format]) ? $range[$format] : $previous; | ||||
|  | ||||
|                 $set['data'][] = $balance; | ||||
|                 $previous      = $balance; | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|             $data['datasets'][] = $set; | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|         $format = trans('config.month_and_day'); | ||||
|  | ||||
|         $data     = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => $account->name, | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $range    = Steam::balanceInRange($account, $start, $end); | ||||
|         $current  = clone $start; | ||||
|         $previous = array_values($range)[0]; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $theDate = $current->format('Y-m-d'); | ||||
|             $balance = isset($range[$theDate]) ? $range[$theDate] : $previous; | ||||
|  | ||||
|             $data['labels'][]              = $current->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = $balance; | ||||
|             $previous                      = $balance; | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $collection | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getIdsFromCollection(Collection $collection) | ||||
|     { | ||||
|         $ids = []; | ||||
|         foreach ($collection as $entry) { | ||||
|             $ids[] = $entry->id; | ||||
|         } | ||||
|  | ||||
|         return array_unique($ids); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Generator/Chart/Bill/BillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Generator/Chart/Bill/BillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Generator\Chart\Bill; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface BillChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Bill | ||||
|  */ | ||||
| interface BillChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param string $paid | ||||
|      * @param string $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage($paid, $unpaid); | ||||
|  | ||||
|     /** | ||||
|      * @param Bill       $bill | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Bill $bill, Collection $entries); | ||||
|  | ||||
| } | ||||
							
								
								
									
										89
									
								
								app/Generator/Chart/Bill/ChartJsBillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								app/Generator/Chart/Bill/ChartJsBillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Bill; | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsBillChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Bill | ||||
|  */ | ||||
| class ChartJsBillChartGenerator implements BillChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param string $paid | ||||
|      * @param string $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage($paid, $unpaid) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $data = [ | ||||
|             [ | ||||
|                 'value'     => round($unpaid, 2), | ||||
|                 'color'     => 'rgba(53, 124, 165,0.7)', | ||||
|                 'highlight' => 'rgba(53, 124, 165,0.9)', | ||||
|                 'label'     => trans('firefly.unpaid'), | ||||
|             ], | ||||
|             [ | ||||
|                 'value'     => round($paid * -1, 2), // paid is negative, must be positive. | ||||
|                 'color'     => 'rgba(0, 141, 76, 0.7)', | ||||
|                 'highlight' => 'rgba(0, 141, 76, 0.9)', | ||||
|                 'label'     => trans('firefly.paid'), | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill       $bill | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Bill $bill, Collection $entries) | ||||
|     { | ||||
|         $format       = trans('config.month'); | ||||
|         $data         = [ | ||||
|             'count'    => 3, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         $minAmount    = []; | ||||
|         $maxAmount    = []; | ||||
|         $actualAmount = []; | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][] = $entry->date->formatLocalized($format); | ||||
|             $minAmount[]      = round($bill->amount_min, 2); | ||||
|             $maxAmount[]      = round($bill->amount_max, 2); | ||||
|             /* | ||||
|              * journalAmount has been collected in BillRepository::getJournals | ||||
|              */ | ||||
|             $actualAmount[] = round(($entry->journalAmount * -1), 2); | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.minAmount'), | ||||
|             'data'  => $minAmount, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.billEntry'), | ||||
|             'data'  => $actualAmount, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.maxAmount'), | ||||
|             'data'  => $maxAmount, | ||||
|         ]; | ||||
|  | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										50
									
								
								app/Generator/Chart/Budget/BudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								app/Generator/Chart/Budget/BudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Budget; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface BudgetChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Budget | ||||
|  */ | ||||
| interface BudgetChartGenerator | ||||
| { | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budget(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budgetLimit(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(Collection $budgets, Collection $entries); | ||||
|  | ||||
| } | ||||
							
								
								
									
										176
									
								
								app/Generator/Chart/Budget/ChartJsBudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								app/Generator/Chart/Budget/ChartJsBudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Budget; | ||||
|  | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsBudgetChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Budget | ||||
|  */ | ||||
| class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * @param string     $dateFormat | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budget(Collection $entries, $dateFormat = 'month') | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data; | ||||
|         $format   = Config::get('firefly.' . $dateFormat . '.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => 'Amount', | ||||
|                     'data'  => [], | ||||
|                 ], | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = $entry[1]; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budgetLimit(Collection $entries) | ||||
|     { | ||||
|         return $this->budget($entries, 'monthAndDay'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $data      = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         $left      = []; | ||||
|         $spent     = []; | ||||
|         $overspent = []; | ||||
|         $filtered  = $entries->filter( | ||||
|             function ($entry) { | ||||
|                 return ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0); | ||||
|             } | ||||
|         ); | ||||
|         foreach ($filtered as $entry) { | ||||
|             $data['labels'][] = $entry[0]; | ||||
|             $left[]           = round($entry[1], 2); | ||||
|             $spent[]          = round($entry[2] * -1, 2); // spent is coming in negative, must be positive | ||||
|             $overspent[]      = round($entry[3] * -1, 2); // same | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.left'), | ||||
|             'data'  => $left, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.spent'), | ||||
|             'data'  => $spent, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.overspent'), | ||||
|             'data'  => $overspent, | ||||
|         ]; | ||||
|  | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(Collection $budgets, Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($budgets as $budget) { | ||||
|             $data['labels'][] = $budget->name; | ||||
|         } | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $array = [ | ||||
|                 'label' => $entry[0]->formatLocalized($format), | ||||
|                 'data'  => [], | ||||
|             ]; | ||||
|             array_shift($entry); | ||||
|             $array['data']      = $entry; | ||||
|             $data['datasets'][] = $array; | ||||
|  | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries) | ||||
|     { | ||||
|         // dataset: | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         // get labels from one of the budgets (assuming there's at least one): | ||||
|         $first = $entries->first(); | ||||
|         foreach ($first['budgeted'] as $year => $noInterest) { | ||||
|             $data['labels'][] = strval($year); | ||||
|         } | ||||
|  | ||||
|         // then, loop all entries and create datasets: | ||||
|         foreach ($entries as $entry) { | ||||
|             $name               = $entry['name']; | ||||
|             $spent              = $entry['spent']; | ||||
|             $budgeted           = $entry['budgeted']; | ||||
|             $data['datasets'][] = ['label' => 'Spent on ' . $name, 'data' => array_values($spent)]; | ||||
|             $data['datasets'][] = ['label' => 'Budgeted for ' . $name, 'data' => array_values($budgeted)]; | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								app/Generator/Chart/Category/CategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/Generator/Chart/Category/CategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Category; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface CategoryChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Category | ||||
|  */ | ||||
| interface CategoryChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInPeriod(Collection $categories, Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function period(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInPeriod(Collection $categories, Collection $entries); | ||||
| } | ||||
							
								
								
									
										194
									
								
								app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Category; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsCategoryChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Category | ||||
|  */ | ||||
| class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $entries) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.earned'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][] = $entry[1]; | ||||
|             $spent            = round($entry[2], 2); | ||||
|             $earned           = round($entry[3], 2); | ||||
|  | ||||
|             $data['datasets'][0]['data'][] = $spent == 0 ? null : $spent * -1; | ||||
|             $data['datasets'][1]['data'][] = $earned == 0 ? null : $earned; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInPeriod(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($categories as $category) { | ||||
|             $data['labels'][] = $category->name; | ||||
|         } | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $date = $entry[0]->formatLocalized($format); | ||||
|             array_shift($entry); | ||||
|             $data['count']++; | ||||
|             $data['datasets'][] = ['label' => $date, 'data' => $entry]; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry->spent != 0) { | ||||
|                 $data['labels'][]              = $entry->name; | ||||
|                 $data['datasets'][0]['data'][] = round(($entry->spent * -1), 2); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries) | ||||
|     { | ||||
|         // dataset: | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         // get labels from one of the categories (assuming there's at least one): | ||||
|         $first = $entries->first(); | ||||
|         foreach ($first['spent'] as $year => $noInterest) { | ||||
|             $data['labels'][] = strval($year); | ||||
|         } | ||||
|  | ||||
|         // then, loop all entries and create datasets: | ||||
|         foreach ($entries as $entry) { | ||||
|             $name   = $entry['name']; | ||||
|             $spent  = $entry['spent']; | ||||
|             $earned = $entry['earned']; | ||||
|             if (array_sum(array_values($spent)) != 0) { | ||||
|                 $data['datasets'][] = ['label' => 'Spent in category ' . $name, 'data' => array_values($spent)]; | ||||
|             } | ||||
|             if (array_sum(array_values($earned)) != 0) { | ||||
|                 $data['datasets'][] = ['label' => 'Earned in category ' . $name, 'data' => array_values($earned)]; | ||||
|             } | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function period(Collection $entries) | ||||
|     { | ||||
|         return $this->all($entries); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInPeriod(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($categories as $category) { | ||||
|             $data['labels'][] = $category->name; | ||||
|         } | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $date = $entry[0]->formatLocalized($format); | ||||
|             array_shift($entry); | ||||
|             $data['count']++; | ||||
|             $data['datasets'][] = ['label' => $date, 'data' => $entry]; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,49 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsPiggyBankChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\PiggyBank | ||||
|  */ | ||||
| class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $set | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function history(Collection $set) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $format = trans('config.month_and_day'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => 'Diff', | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $sum  = '0'; | ||||
|         bcscale(2); | ||||
|         foreach ($set as $entry) { | ||||
|             $date                          = new Carbon($entry->date); | ||||
|             $sum                           = bcadd($sum, $entry->sum); | ||||
|             $data['labels'][]              = $date->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = round($sum, 2); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								app/Generator/Chart/PiggyBank/PiggyBankChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Generator/Chart/PiggyBank/PiggyBankChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface PiggyBankChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\PiggyBank | ||||
|  */ | ||||
| interface PiggyBankChartGenerator | ||||
| { | ||||
|     /** | ||||
|      * @param Collection $set | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function history(Collection $set); | ||||
| } | ||||
							
								
								
									
										144
									
								
								app/Generator/Chart/Report/ChartJsReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								app/Generator/Chart/Report/ChartJsReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsReportChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Report | ||||
|  */ | ||||
| class ChartJsReportChartGenerator implements ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Same as above but other translations. | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOut(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized('%Y'); | ||||
|             $data['datasets'][0]['data'][] = round($entry[1], 2); | ||||
|             $data['datasets'][1]['data'][] = round($entry[2], 2); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOutSummarized($income, $expense, $count) | ||||
|     { | ||||
|         $data                          = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [trans('firefly.sum_of_years'), trans('firefly.average_of_years')], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $data['datasets'][0]['data'][] = round($income, 2); | ||||
|         $data['datasets'][1]['data'][] = round($expense, 2); | ||||
|         $data['datasets'][0]['data'][] = round(($income / $count), 2); | ||||
|         $data['datasets'][1]['data'][] = round(($expense / $count), 2); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOut(Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = round($entry[1], 2); | ||||
|             $data['datasets'][1]['data'][] = round($entry[2], 2); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOutSummarized($income, $expense, $count) | ||||
|     { | ||||
|  | ||||
|         $data                          = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [trans('firefly.sum_of_year'), trans('firefly.average_of_year')], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $data['datasets'][0]['data'][] = round($income, 2); | ||||
|         $data['datasets'][1]['data'][] = round($expense, 2); | ||||
|         $data['datasets'][0]['data'][] = round(($income / $count), 2); | ||||
|         $data['datasets'][1]['data'][] = round(($expense / $count), 2); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										47
									
								
								app/Generator/Chart/Report/ReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/Generator/Chart/Report/ReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ReportChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Report | ||||
|  */ | ||||
| interface ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOut(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOutSummarized($income, $expense, $count); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOut(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOutSummarized($income, $expense, $count); | ||||
|  | ||||
| } | ||||
| @@ -4,9 +4,7 @@ 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 | ||||
| @@ -19,6 +17,8 @@ class ConnectJournalToPiggyBank | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
| @@ -30,67 +30,40 @@ class ConnectJournalToPiggyBank | ||||
|      * | ||||
|      * @param  JournalCreated $event | ||||
|      * | ||||
|      * @return void | ||||
|      * @return boolean | ||||
|      */ | ||||
|     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 = $journal->amount; | ||||
|         Log::debug('Amount: ' . $amount); | ||||
|         if ($amount == 0) { | ||||
|             return; | ||||
|         if (is_null($piggyBank)) { | ||||
|             return false; | ||||
|         } | ||||
|         // 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 false; | ||||
|         } | ||||
|         bcscale(2); | ||||
|  | ||||
|             return; | ||||
|         $amount = $journal->amount_positive; | ||||
|         // if piggy account matches source account, the amount is positive | ||||
|         if ($piggyBank->account_id == $journal->source_account->id) { | ||||
|             $amount = $amount * -1; | ||||
|         } | ||||
|  | ||||
|         Log::debug('Found rep! ' . $repetition->id); | ||||
|  | ||||
|         /* | ||||
|          * Add amount when | ||||
|          */ | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             if ($transaction->account_id == $piggyBank->account_id) { | ||||
|                 if ($transaction->amount < 0) { | ||||
|                     $amount = $amount * -1; | ||||
|                     Log::debug('Transaction is away from piggy, so amount becomes ' . $amount); | ||||
|                 } else { | ||||
|                     Log::debug('Transaction is to from piggy, so amount stays ' . $amount); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $repetition->currentamount += $amount; | ||||
|         $repetition->currentamount = bcadd($repetition->currentamount, $amount); | ||||
|         $repetition->save(); | ||||
|  | ||||
|         PiggyBankEvent::create( | ||||
|             [ | ||||
|                 'piggy_bank_id'          => $piggyBank->id, | ||||
|                 'transaction_journal_id' => $journal->id, | ||||
|                 'date'                   => $journal->date, | ||||
|                 'amount'                 => $amount | ||||
|             ] | ||||
|         ); | ||||
|         PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]); | ||||
|  | ||||
|         return true; | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,35 +0,0 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use FireflyIII\Events\JournalDeleted; | ||||
|  | ||||
| /** | ||||
|  * Class JournalDeletedHandler | ||||
|  * | ||||
|  * @package FireflyIII\Handlers\Events | ||||
|  */ | ||||
| class JournalDeletedHandler | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  JournalDeleted $event | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(JournalDeleted $event) | ||||
|     { | ||||
|         // | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,12 +1,12 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use App; | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RescanJournal | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Handlers\Events | ||||
|  */ | ||||
| class RescanJournal | ||||
| @@ -35,7 +35,7 @@ class RescanJournal | ||||
|         Log::debug('Triggered saved event for journal #' . $journal->id . ' (' . $journal->description . ')'); | ||||
|  | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $list       = $journal->user->bills()->where('active', 1)->where('automatch', 1)->get(); | ||||
|  | ||||
|         Log::debug('Found ' . $list->count() . ' bills to check.'); | ||||
|   | ||||
| @@ -2,10 +2,12 @@ | ||||
|  | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
|  | ||||
| /** | ||||
|  * Class UpdateJournalConnection | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Handlers\Events | ||||
|  */ | ||||
| class UpdateJournalConnection | ||||
| @@ -38,15 +40,21 @@ class UpdateJournalConnection | ||||
|             return; | ||||
|         } | ||||
|         $piggyBank  = $event->piggyBank()->first(); | ||||
|         $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|         $repetition = null; | ||||
|         if ($piggyBank) { | ||||
|             /** @var PiggyBankRepetition $repetition */ | ||||
|             $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|         } | ||||
|  | ||||
|         if (is_null($repetition)) { | ||||
|             return; | ||||
|         } | ||||
|         $amount = $journal->amount; | ||||
|         $diff   = $amount - $event->amount;// update current repetition | ||||
|         bcscale(2); | ||||
|  | ||||
|         $repetition->currentamount += $diff; | ||||
|         $amount = $journal->amount; | ||||
|         $diff   = bcsub($amount, $event->amount); // update current repetition | ||||
|  | ||||
|         $repetition->currentamount = bcadd($repetition->currentamount, $diff); | ||||
|         $repetition->save(); | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										224
									
								
								app/Helpers/Attachments/AttachmentHelper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								app/Helpers/Attachments/AttachmentHelper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Attachments; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Crypt; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use Input; | ||||
| use Symfony\Component\HttpFoundation\File\UploadedFile; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentHelper | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Attachments | ||||
|  */ | ||||
| class AttachmentHelper implements AttachmentHelperInterface | ||||
| { | ||||
|  | ||||
|     /** @var int */ | ||||
|     protected $maxUploadSize; | ||||
|     /** @var array */ | ||||
|     protected $allowedMimes; | ||||
|     /** @var MessageBag */ | ||||
|     public $errors; | ||||
|     /** @var MessageBag */ | ||||
|     public $messages; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->maxUploadSize = Config::get('firefly.maxUploadSize'); | ||||
|         $this->allowedMimes  = Config::get('firefly.allowedMimes'); | ||||
|         $this->errors        = new MessageBag; | ||||
|         $this->messages      = new MessageBag; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getAttachmentLocation(Attachment $attachment) | ||||
|     { | ||||
|         $path = storage_path('upload') . DIRECTORY_SEPARATOR . 'at-' . $attachment->id . '.data'; | ||||
|  | ||||
|         return $path; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Model $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function saveAttachmentsForModel(Model $model) | ||||
|     { | ||||
|         $files = Input::file('attachments'); | ||||
|  | ||||
|         if (is_array($files)) { | ||||
|             foreach ($files as $entry) { | ||||
|                 if (!is_null($entry)) { | ||||
|                     $this->processFile($entry, $model); | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             if (!is_null($files)) { | ||||
|                 $this->processFile($files, $model); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * @param Model        $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function hasFile(UploadedFile $file, Model $model) | ||||
|     { | ||||
|         $md5   = md5_file($file->getRealPath()); | ||||
|         $name  = $file->getClientOriginalName(); | ||||
|         $class = get_class($model); | ||||
|         $count = Auth::user()->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); | ||||
|  | ||||
|         if ($count > 0) { | ||||
|             $msg = trans('validation.file_already_attached', ['name' => $name]); | ||||
|             $this->errors->add('attachments', $msg); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * @param Model        $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validateUpload(UploadedFile $file, Model $model) | ||||
|     { | ||||
|         if (!$this->validMime($file)) { | ||||
|             return false; | ||||
|         } | ||||
|         if (!$this->validSize($file)) { | ||||
|             return false; | ||||
|         } | ||||
|         if ($this->hasFile($file, $model)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * @param Model        $model | ||||
|      * | ||||
|      * @return bool|Attachment | ||||
|      */ | ||||
|     protected function processFile(UploadedFile $file, Model $model) | ||||
|     { | ||||
|         $validation = $this->validateUpload($file, $model); | ||||
|         if ($validation === false) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $attachment = new Attachment; // create Attachment object. | ||||
|         $attachment->user()->associate(Auth::user()); | ||||
|         $attachment->attachable()->associate($model); | ||||
|         $attachment->md5      = md5_file($file->getRealPath()); | ||||
|         $attachment->filename = $file->getClientOriginalName(); | ||||
|         $attachment->mime     = $file->getMimeType(); | ||||
|         $attachment->size     = $file->getSize(); | ||||
|         $attachment->uploaded = 0; | ||||
|         $attachment->save(); | ||||
|  | ||||
|         $path      = $file->getRealPath(); // encrypt and move file to storage. | ||||
|         $content   = file_get_contents($path); | ||||
|         $encrypted = Crypt::encrypt($content); | ||||
|  | ||||
|         // store it: | ||||
|         $upload = $this->getAttachmentLocation($attachment); | ||||
|         if (is_writable(dirname($upload))) { | ||||
|             file_put_contents($upload, $encrypted); | ||||
|         } | ||||
|  | ||||
|         $attachment->uploaded = 1; // update attachment | ||||
|         $attachment->save(); | ||||
|  | ||||
|         $name = e($file->getClientOriginalName()); // add message: | ||||
|         $msg  = trans('validation.file_attached', ['name' => $name]); | ||||
|         $this->messages->add('attachments', $msg); | ||||
|  | ||||
|         // return it. | ||||
|         return $attachment; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validMime(UploadedFile $file) | ||||
|     { | ||||
|         $mime = e($file->getMimeType()); | ||||
|         $name = e($file->getClientOriginalName()); | ||||
|  | ||||
|         if (!in_array($mime, $this->allowedMimes)) { | ||||
|             $msg = trans('validation.file_invalid_mime', ['name' => $name, 'mime' => $mime]); | ||||
|             $this->errors->add('attachments', $msg); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validSize(UploadedFile $file) | ||||
|     { | ||||
|         $size = $file->getSize(); | ||||
|         $name = e($file->getClientOriginalName()); | ||||
|         if ($size > $this->maxUploadSize) { | ||||
|             $msg = trans('validation.file_too_large', ['name' => $name]); | ||||
|             $this->errors->add('attachments', $msg); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getErrors() | ||||
|     { | ||||
|         return $this->errors; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getMessages() | ||||
|     { | ||||
|         return $this->messages; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										41
									
								
								app/Helpers/Attachments/AttachmentHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Helpers/Attachments/AttachmentHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Attachments; | ||||
|  | ||||
| use FireflyIII\Models\Attachment; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Support\MessageBag; | ||||
|  | ||||
| /** | ||||
|  * Interface AttachmentHelperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Attachments | ||||
|  */ | ||||
| interface AttachmentHelperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Model $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function saveAttachmentsForModel(Model $model); | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getErrors(); | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getMessages(); | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getAttachmentLocation(Attachment $attachment); | ||||
|  | ||||
| } | ||||
							
								
								
									
										90
									
								
								app/Helpers/Collection/Account.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								app/Helpers/Collection/Account.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * Class Account | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Account | ||||
| { | ||||
|  | ||||
|     /** @var Collection */ | ||||
|     protected $accounts; | ||||
|     /** @var float */ | ||||
|     protected $difference; | ||||
|     /** @var float */ | ||||
|     protected $end; | ||||
|     /** @var float */ | ||||
|     protected $start; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      */ | ||||
|     public function getAccounts() | ||||
|     { | ||||
|         return $this->accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param \Illuminate\Support\Collection $accounts | ||||
|      */ | ||||
|     public function setAccounts($accounts) | ||||
|     { | ||||
|         $this->accounts = $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getDifference() | ||||
|     { | ||||
|         return $this->difference; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $difference | ||||
|      */ | ||||
|     public function setDifference($difference) | ||||
|     { | ||||
|         $this->difference = $difference; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getEnd() | ||||
|     { | ||||
|         return $this->end; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $end | ||||
|      */ | ||||
|     public function setEnd($end) | ||||
|     { | ||||
|         $this->end = $end; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getStart() | ||||
|     { | ||||
|         return $this->start; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $start | ||||
|      */ | ||||
|     public function setStart($start) | ||||
|     { | ||||
|         $this->start = $start; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										64
									
								
								app/Helpers/Collection/Balance.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								app/Helpers/Collection/Balance.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Balance | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Balance | ||||
| { | ||||
|  | ||||
|     /** @var  BalanceHeader */ | ||||
|     protected $balanceHeader; | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $balanceLines; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->balanceLines = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BalanceLine $line | ||||
|      */ | ||||
|     public function addBalanceLine(BalanceLine $line) | ||||
|     { | ||||
|         $this->balanceLines->push($line); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BalanceHeader | ||||
|      */ | ||||
|     public function getBalanceHeader() | ||||
|     { | ||||
|         return $this->balanceHeader; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BalanceHeader $balanceHeader | ||||
|      */ | ||||
|     public function setBalanceHeader($balanceHeader) | ||||
|     { | ||||
|         $this->balanceHeader = $balanceHeader; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      */ | ||||
|     public function getBalanceLines() | ||||
|     { | ||||
|         return $this->balanceLines; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										74
									
								
								app/Helpers/Collection/BalanceEntry.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/Helpers/Collection/BalanceEntry.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Account as AccountModel; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BalanceEntry | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BalanceEntry | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** @var  AccountModel */ | ||||
|     protected $account; | ||||
|     /** @var float */ | ||||
|     protected $left = 0.0; | ||||
|     /** @var float */ | ||||
|     protected $spent = 0.0; | ||||
|  | ||||
|     /** | ||||
|      * @return AccountModel | ||||
|      */ | ||||
|     public function getAccount() | ||||
|     { | ||||
|         return $this->account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountModel $account | ||||
|      */ | ||||
|     public function setAccount($account) | ||||
|     { | ||||
|         $this->account = $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getLeft() | ||||
|     { | ||||
|         return $this->left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $left | ||||
|      */ | ||||
|     public function setLeft($left) | ||||
|     { | ||||
|         $this->left = $left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getSpent() | ||||
|     { | ||||
|         return $this->spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $spent | ||||
|      */ | ||||
|     public function setSpent($spent) | ||||
|     { | ||||
|         $this->spent = $spent; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										46
									
								
								app/Helpers/Collection/BalanceHeader.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/Helpers/Collection/BalanceHeader.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Account as AccountModel; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BalanceHeader | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BalanceHeader | ||||
| { | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $accounts; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->accounts = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountModel $account | ||||
|      */ | ||||
|     public function addAccount(AccountModel $account) | ||||
|     { | ||||
|         $this->accounts->push($account); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAccounts() | ||||
|     { | ||||
|         return $this->accounts; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										133
									
								
								app/Helpers/Collection/BalanceLine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								app/Helpers/Collection/BalanceLine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BalanceLine | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BalanceLine | ||||
| { | ||||
|  | ||||
|     const ROLE_DEFAULTROLE = 1; | ||||
|     const ROLE_TAGROLE     = 2; | ||||
|     const ROLE_DIFFROLE    = 3; | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $balanceEntries; | ||||
|  | ||||
|     /** @var BudgetModel */ | ||||
|     protected $budget; | ||||
|  | ||||
|     protected $role = self::ROLE_DEFAULTROLE; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->balanceEntries = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BalanceEntry $balanceEntry | ||||
|      */ | ||||
|     public function addBalanceEntry(BalanceEntry $balanceEntry) | ||||
|     { | ||||
|         $this->balanceEntries->push($balanceEntry); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBalanceEntries() | ||||
|     { | ||||
|         return $this->balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $balanceEntries | ||||
|      */ | ||||
|     public function setBalanceEntries($balanceEntries) | ||||
|     { | ||||
|         $this->balanceEntries = $balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BudgetModel | ||||
|      */ | ||||
|     public function getBudget() | ||||
|     { | ||||
|         return $this->budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetModel $budget | ||||
|      */ | ||||
|     public function setBudget($budget) | ||||
|     { | ||||
|         $this->budget = $budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getRole() | ||||
|     { | ||||
|         return $this->role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $role | ||||
|      */ | ||||
|     public function setRole($role) | ||||
|     { | ||||
|         $this->role = $role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTitle() | ||||
|     { | ||||
|         if ($this->getBudget() instanceof BudgetModel) { | ||||
|             return $this->getBudget()->name; | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DEFAULTROLE) { | ||||
|             return trans('firefly.noBudget'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_TAGROLE) { | ||||
|             return trans('firefly.coveredWithTags'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DIFFROLE) { | ||||
|             return trans('firefly.leftUnbalanced'); | ||||
|         } | ||||
|  | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine | ||||
|      * should have a "spent" value, which is the amount of money that has been spent | ||||
|      * on the given budget/repetition. If you subtract all those amounts from the budget/repetition's | ||||
|      * total amount, this is returned: | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function leftOfRepetition() | ||||
|     { | ||||
|         $start = isset($this->budget->amount) ? $this->budget->amount : 0; | ||||
|         /** @var BalanceEntry $balanceEntry */ | ||||
|         foreach ($this->getBalanceEntries() as $balanceEntry) { | ||||
|             $start += $balanceEntry->getSpent(); | ||||
|         } | ||||
|  | ||||
|         return $start; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										56
									
								
								app/Helpers/Collection/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/Helpers/Collection/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Bill | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @var Collection | ||||
|      */ | ||||
|     protected $bills; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->bills = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillLine $bill | ||||
|      */ | ||||
|     public function addBill(BillLine $bill) | ||||
|     { | ||||
|         $this->bills->push($bill); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBills() | ||||
|     { | ||||
|         $set = $this->bills->sortBy( | ||||
|             function (BillLine $bill) { | ||||
|                 $active = intval($bill->getBill()->active) == 0 ? 1 : 0; | ||||
|                 $name   = $bill->getBill()->name; | ||||
|  | ||||
|                 return $active . $name; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										127
									
								
								app/Helpers/Collection/BillLine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								app/Helpers/Collection/BillLine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Bill as BillModel; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BillLine | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BillLine | ||||
| { | ||||
|  | ||||
|     /** @var  bool */ | ||||
|     protected $active; | ||||
|     /** @var  string */ | ||||
|     protected $amount; | ||||
|     /** @var  BillModel */ | ||||
|     protected $bill; | ||||
|     /** @var  bool */ | ||||
|     protected $hit; | ||||
|     /** @var  string */ | ||||
|     protected $max; | ||||
|     /** @var  string */ | ||||
|     protected $min; | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getAmount() | ||||
|     { | ||||
|         return $this->amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $amount | ||||
|      */ | ||||
|     public function setAmount($amount) | ||||
|     { | ||||
|         $this->amount = $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BillModel | ||||
|      */ | ||||
|     public function getBill() | ||||
|     { | ||||
|         return $this->bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillModel $bill | ||||
|      */ | ||||
|     public function setBill($bill) | ||||
|     { | ||||
|         $this->bill = $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getMax() | ||||
|     { | ||||
|         return $this->max; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $max | ||||
|      */ | ||||
|     public function setMax($max) | ||||
|     { | ||||
|         $this->max = $max; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getMin() | ||||
|     { | ||||
|         return $this->min; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $min | ||||
|      */ | ||||
|     public function setMin($min) | ||||
|     { | ||||
|         $this->min = $min; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function isActive() | ||||
|     { | ||||
|         return $this->active; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param boolean $active | ||||
|      */ | ||||
|     public function setActive($active) | ||||
|     { | ||||
|         $this->active = $active; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function isHit() | ||||
|     { | ||||
|         return $this->hit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param boolean $hit | ||||
|      */ | ||||
|     public function setHit($hit) | ||||
|     { | ||||
|         $this->hit = $hit; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										156
									
								
								app/Helpers/Collection/Budget.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								app/Helpers/Collection/Budget.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Budget | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Budget | ||||
| { | ||||
|     /** @var  Collection */ | ||||
|     protected $budgetLines; | ||||
|     /** @var string */ | ||||
|     protected $budgeted = '0'; | ||||
|     /** @var string */ | ||||
|     protected $left = '0'; | ||||
|     /** @var string */ | ||||
|     protected $overspent = '0'; | ||||
|     /** @var string */ | ||||
|     protected $spent = '0'; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->budgetLines = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetLine $budgetLine | ||||
|      */ | ||||
|     public function addBudgetLine(BudgetLine $budgetLine) | ||||
|     { | ||||
|         $this->budgetLines->push($budgetLine); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addBudgeted($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|         $this->budgeted = bcadd($this->budgeted, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addLeft($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|         $this->left = bcadd($this->left, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addOverspent($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|         $this->overspent = bcadd($this->overspent, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addSpent($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|         $this->spent = bcadd($this->spent, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      */ | ||||
|     public function getBudgetLines() | ||||
|     { | ||||
|         return $this->budgetLines; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getBudgeted() | ||||
|     { | ||||
|         return $this->budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $budgeted | ||||
|      */ | ||||
|     public function setBudgeted($budgeted) | ||||
|     { | ||||
|         $this->budgeted = $budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getLeft() | ||||
|     { | ||||
|         return $this->left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $left | ||||
|      */ | ||||
|     public function setLeft($left) | ||||
|     { | ||||
|         $this->left = $left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getOverspent() | ||||
|     { | ||||
|         return $this->overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $overspent | ||||
|      */ | ||||
|     public function setOverspent($overspent) | ||||
|     { | ||||
|         $this->overspent = strval(round($overspent, 2)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getSpent() | ||||
|     { | ||||
|         return $this->spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $spent | ||||
|      */ | ||||
|     public function setSpent($spent) | ||||
|     { | ||||
|         $this->spent = strval(round($spent, 2)); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										128
									
								
								app/Helpers/Collection/BudgetLine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								app/Helpers/Collection/BudgetLine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BudgetLine | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BudgetLine | ||||
| { | ||||
|  | ||||
|     /** @var  BudgetModel */ | ||||
|     protected $budget; | ||||
|     /** @var float */ | ||||
|     protected $budgeted = 0; | ||||
|     /** @var float */ | ||||
|     protected $left = 0; | ||||
|     /** @var float */ | ||||
|     protected $overspent = 0; | ||||
|     /** @var  LimitRepetition */ | ||||
|     protected $repetition; | ||||
|     /** @var float */ | ||||
|     protected $spent = 0; | ||||
|  | ||||
|     /** | ||||
|      * @return BudgetModel | ||||
|      */ | ||||
|     public function getBudget() | ||||
|     { | ||||
|         return $this->budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetModel $budget | ||||
|      */ | ||||
|     public function setBudget($budget) | ||||
|     { | ||||
|         $this->budget = $budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getBudgeted() | ||||
|     { | ||||
|         return $this->budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $budgeted | ||||
|      */ | ||||
|     public function setBudgeted($budgeted) | ||||
|     { | ||||
|         $this->budgeted = $budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getLeft() | ||||
|     { | ||||
|         return $this->left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $left | ||||
|      */ | ||||
|     public function setLeft($left) | ||||
|     { | ||||
|         $this->left = $left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getOverspent() | ||||
|     { | ||||
|         return $this->overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $overspent | ||||
|      */ | ||||
|     public function setOverspent($overspent) | ||||
|     { | ||||
|         $this->overspent = $overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return LimitRepetition | ||||
|      */ | ||||
|     public function getRepetition() | ||||
|     { | ||||
|         return $this->repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param LimitRepetition $repetition | ||||
|      */ | ||||
|     public function setRepetition($repetition) | ||||
|     { | ||||
|         $this->repetition = $repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getSpent() | ||||
|     { | ||||
|         return $this->spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $spent | ||||
|      */ | ||||
|     public function setSpent($spent) | ||||
|     { | ||||
|         $this->spent = $spent; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										78
									
								
								app/Helpers/Collection/Category.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								app/Helpers/Collection/Category.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Category as CategoryModel; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Category | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Category | ||||
| { | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $categories; | ||||
|     /** @var string */ | ||||
|     protected $total = '0'; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->categories = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryModel $category | ||||
|      */ | ||||
|     public function addCategory(CategoryModel $category) | ||||
|     { | ||||
|         // spent is minus zero for an expense report: | ||||
|         if ($category->spent < 0) { | ||||
|             $this->categories->push($category); | ||||
|             $this->addTotal($category->spent); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addTotal($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|         $this->total = bcadd($this->total, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCategories() | ||||
|     { | ||||
|         $set = $this->categories->sortBy( | ||||
|             function (CategoryModel $category) { | ||||
|                 return $category->spent; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTotal() | ||||
|     { | ||||
|         return strval(round($this->total, 2)); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										101
									
								
								app/Helpers/Collection/Expense.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								app/Helpers/Collection/Expense.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Crypt; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Expense | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Expense | ||||
| { | ||||
|     /** @var Collection */ | ||||
|     protected $expenses; | ||||
|     /** @var string */ | ||||
|     protected $total = '0'; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->expenses = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $entry | ||||
|      */ | ||||
|     public function addOrCreateExpense(TransactionJournal $entry) | ||||
|     { | ||||
|         bcscale(2); | ||||
|  | ||||
|         $accountId = $entry->account_id; | ||||
|         $amount    = strval(round($entry->journalAmount, 2)); | ||||
|         if (bccomp('0', $amount) === -1) { | ||||
|             $amount = bcmul($amount, '-1'); | ||||
|         } | ||||
|  | ||||
|         if (!$this->expenses->has($accountId)) { | ||||
|             $newObject         = new stdClass; | ||||
|             $newObject->amount = $amount; | ||||
|             $newObject->name   = Crypt::decrypt($entry->account_name); | ||||
|             $newObject->count  = 1; | ||||
|             $newObject->id     = $accountId; | ||||
|             $this->expenses->put($accountId, $newObject); | ||||
|         } else { | ||||
|             $existing         = $this->expenses->get($accountId); | ||||
|             $existing->amount = bcadd($existing->amount, $amount); | ||||
|             $existing->count++; | ||||
|             $this->expenses->put($accountId, $existing); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $add | ||||
|      */ | ||||
|     public function addToTotal($add) | ||||
|     { | ||||
|         bcscale(2); | ||||
|  | ||||
|  | ||||
|         $add = strval(round($add, 2)); | ||||
|         if (bccomp('0', $add) === -1) { | ||||
|             $add = bcmul($add, '-1'); | ||||
|         } | ||||
|  | ||||
|         // if amount is positive, the original transaction | ||||
|         // was a transfer. But since this is an expense report, | ||||
|         // that amount must be negative. | ||||
|  | ||||
|         $this->total = bcadd($this->total, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getExpenses() | ||||
|     { | ||||
|         $set = $this->expenses->sortBy( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTotal() | ||||
|     { | ||||
|         return strval(round($this->total, 2)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										89
									
								
								app/Helpers/Collection/Income.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								app/Helpers/Collection/Income.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Crypt; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Income | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Income | ||||
| { | ||||
|  | ||||
|     /** @var Collection */ | ||||
|     protected $incomes; | ||||
|     /** @var string */ | ||||
|     protected $total; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->incomes = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $entry | ||||
|      */ | ||||
|     public function addOrCreateIncome(TransactionJournal $entry) | ||||
|     { | ||||
|  | ||||
|         $accountId = $entry->account_id; | ||||
|         if (!$this->incomes->has($accountId)) { | ||||
|             $newObject         = new stdClass; | ||||
|             $newObject->amount = strval(round($entry->journalAmount, 2)); | ||||
|             $newObject->name   = Crypt::decrypt($entry->account_name); | ||||
|             $newObject->count  = 1; | ||||
|             $newObject->id     = $accountId; | ||||
|             $this->incomes->put($accountId, $newObject); | ||||
|         } else { | ||||
|             bcscale(2); | ||||
|             $existing         = $this->incomes->get($accountId); | ||||
|             $existing->amount = bcadd($existing->amount, $entry->journalAmount); | ||||
|             $existing->count++; | ||||
|             $this->incomes->put($accountId, $existing); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $add | ||||
|      */ | ||||
|     public function addToTotal($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|         $this->total = bcadd($this->total, $add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getIncomes() | ||||
|     { | ||||
|         $set = $this->incomes->sortByDesc( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTotal() | ||||
|     { | ||||
|         return strval(round($this->total, 2)); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/Converter/AccountId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/Converter/AccountId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class AccountId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class AccountId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|  | ||||
|             /** @var Account $account */ | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|  | ||||
|             /** @var Account $account */ | ||||
|             $account = Auth::user()->accounts()->find($this->value); | ||||
|  | ||||
|             if (!is_null($account)) { | ||||
|                 Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value . ' (not mapped) '); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								app/Helpers/Csv/Converter/Amount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Helpers/Csv/Converter/Amount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class Amount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Amount extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (is_numeric($this->value)) { | ||||
|             return $this->value; | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										68
									
								
								app/Helpers/Csv/Converter/AssetAccountIban.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								app/Helpers/Csv/Converter/AssetAccountIban.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccountIban | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class AssetAccountIban extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } | ||||
|         if (strlen($this->value) > 0) { | ||||
|             // find or create new account: | ||||
|             $account     = $this->findAccount(); | ||||
|             $accountType = AccountType::where('type', 'Asset account')->first(); | ||||
|  | ||||
|             if (is_null($account)) { | ||||
|                 // create it if doesn't exist. | ||||
|                 $account = Account::firstOrCreateEncrypted( | ||||
|                     [ | ||||
|                         'name'            => $this->value, | ||||
|                         'iban'            => $this->value, | ||||
|                         'user_id'         => Auth::user()->id, | ||||
|                         'account_type_id' => $accountType->id, | ||||
|                         'active'          => 1, | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             return $account; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function findAccount() | ||||
|     { | ||||
|         $set = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); | ||||
|         /** @var Account $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             if ($entry->iban == $this->value) { | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										51
									
								
								app/Helpers/Csv/Converter/AssetAccountName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/Helpers/Csv/Converter/AssetAccountName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccountName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class AssetAccountName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } | ||||
|         // find or create new account: | ||||
|         $accountType = AccountType::where('type', 'Asset account')->first(); | ||||
|         $set         = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get(); | ||||
|         /** @var Account $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             if ($entry->name == $this->value) { | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // create it if doesnt exist. | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'name'            => $this->value, | ||||
|                 'iban'            => '', | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'active'          => 1, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										122
									
								
								app/Helpers/Csv/Converter/BasicConverter.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								app/Helpers/Csv/Converter/BasicConverter.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| /** | ||||
|  * Class BasicConverter | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BasicConverter | ||||
| { | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|     /** @var string */ | ||||
|     protected $field; | ||||
|     /** @var int */ | ||||
|     protected $index; | ||||
|     /** @var  array */ | ||||
|     protected $mapped; | ||||
|     /** @var string */ | ||||
|     protected $role; | ||||
|     /** @var string */ | ||||
|     protected $value; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getData() | ||||
|     { | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getField() | ||||
|     { | ||||
|         return $this->field; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      */ | ||||
|     public function setField($field) | ||||
|     { | ||||
|         $this->field = $field; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getIndex() | ||||
|     { | ||||
|         return $this->index; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $index | ||||
|      */ | ||||
|     public function setIndex($index) | ||||
|     { | ||||
|         $this->index = $index; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMapped() | ||||
|     { | ||||
|         return $this->mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $mapped | ||||
|      */ | ||||
|     public function setMapped($mapped) | ||||
|     { | ||||
|         $this->mapped = $mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getRole() | ||||
|     { | ||||
|         return $this->role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $role | ||||
|      */ | ||||
|     public function setRole($role) | ||||
|     { | ||||
|         $this->role = $role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getValue() | ||||
|     { | ||||
|         return $this->value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setValue($value) | ||||
|     { | ||||
|         $this->value = $value; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										30
									
								
								app/Helpers/Csv/Converter/BillId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/Helpers/Csv/Converter/BillId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
|  | ||||
| /** | ||||
|  * Class BillId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BillId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $bill = Auth::user()->bills()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/Converter/BillName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/Converter/BillName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
|  | ||||
| /** | ||||
|  * Class BillName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BillName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $bill = null; | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|  | ||||
|             $bills = Auth::user()->bills()->get(); | ||||
|             /** @var Bill $bill */ | ||||
|             foreach ($bills as $bill) { | ||||
|                 if ($bill->name == $this->value) { | ||||
|                     return $bill; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Helpers/Csv/Converter/BudgetId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Helpers/Csv/Converter/BudgetId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class AccountId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BudgetId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Budget | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $budget = Auth::user()->budgets()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $budget; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Helpers/Csv/Converter/BudgetName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Helpers/Csv/Converter/BudgetName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BudgetName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Budget | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $budget = Budget::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'name'    => $this->value, | ||||
|                     'user_id' => Auth::user()->id, | ||||
|                     'active'  => true, | ||||
|                 ] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $budget; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Helpers/Csv/Converter/CategoryId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Helpers/Csv/Converter/CategoryId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CategoryId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $category = Auth::user()->categories()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $category; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Converter/CategoryName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Converter/CategoryName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CategoryName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $category = Category::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'name'    => $this->value, | ||||
|                     'user_id' => Auth::user()->id | ||||
|                 ] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $category; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										49
									
								
								app/Helpers/Csv/Converter/ConverterInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/Helpers/Csv/Converter/ConverterInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| /** | ||||
|  * Interface ConverterInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| interface ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function convert(); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      * | ||||
|      */ | ||||
|     public function setField($field); | ||||
|  | ||||
|     /** | ||||
|      * @param int $index | ||||
|      */ | ||||
|     public function setIndex($index); | ||||
|  | ||||
|     /** | ||||
|      * @param array $mapped | ||||
|      */ | ||||
|     public function setMapped($mapped); | ||||
|  | ||||
|     /** | ||||
|      * @param string $role | ||||
|      */ | ||||
|     public function setRole($role); | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setValue($value); | ||||
|  | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyCode.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyCode.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyCode | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencyCode extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::whereCode($this->value)->first(); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencyId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencyName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::whereName($this->value)->first(); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencySymbol.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencySymbol.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencySymbol | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencySymbol extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::whereSymbol($this->value)->first(); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								app/Helpers/Csv/Converter/Date.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/Helpers/Csv/Converter/Date.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use InvalidArgumentException; | ||||
| use Log; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class Date | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Date extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return static | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $format = Session::get('csv-date-format'); | ||||
|         try { | ||||
|             $date = Carbon::createFromFormat($format, $this->value); | ||||
|         } catch (InvalidArgumentException $e) { | ||||
|             Log::error('Date conversion error: ' . $e->getMessage() . '. Value was "' . $this->value . '", format was "' . $format . '".'); | ||||
|  | ||||
|             $message = trans('firefly.csv_date_parse_error', ['format' => $format, 'value' => $this->value]); | ||||
|  | ||||
|             throw new FireflyException($message); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $date; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										21
									
								
								app/Helpers/Csv/Converter/Description.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/Helpers/Csv/Converter/Description.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| /** | ||||
|  * Class Description | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Description extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         return trim($this->data['description'] . ' ' . $this->value); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										22
									
								
								app/Helpers/Csv/Converter/Ignore.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Helpers/Csv/Converter/Ignore.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class Amount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Ignore extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										57
									
								
								app/Helpers/Csv/Converter/OpposingAccountIban.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/Helpers/Csv/Converter/OpposingAccountIban.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingAccountIban | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class OpposingAccountIban extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * If mapped, return account. Otherwise, only return the name itself. | ||||
|      * | ||||
|      * @return Account|string | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } else { | ||||
|             if (strlen($this->value) > 0) { | ||||
|                 $account = $this->findAccount(); | ||||
|                 if (!is_null($account)) { | ||||
|                     return $account; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return $this->value; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function findAccount() | ||||
|     { | ||||
|         $set = Auth::user()->accounts()->get(); | ||||
|         /** @var Account $account */ | ||||
|         foreach ($set as $account) { | ||||
|             if ($account->iban == $this->value) { | ||||
|                 Log::debug('OpposingAccountIban::convert found an Account (#' . $account->id . ': ******) with IBAN ******'); | ||||
|  | ||||
|                 return $account; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Helpers/Csv/Converter/OpposingAccountId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Helpers/Csv/Converter/OpposingAccountId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class OpposingAccountId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|         } else { | ||||
|             $account = Auth::user()->accounts()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $account; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								app/Helpers/Csv/Converter/OpposingAccountName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/Helpers/Csv/Converter/OpposingAccountName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class OpposingAccountName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * If mapped, return account. Otherwise, only return the name itself. | ||||
|      * | ||||
|      * @return Account|string | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } else { | ||||
|             return $this->value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								app/Helpers/Csv/Converter/RabobankDebetCredit.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Helpers/Csv/Converter/RabobankDebetCredit.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RabobankDebetCredit | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class RabobankDebetCredit extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if ($this->value == 'D') { | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         return 1; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Helpers/Csv/Converter/TagsComma.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Helpers/Csv/Converter/TagsComma.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Tag; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class TagsComma | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class TagsComma extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $tags = new Collection; | ||||
|  | ||||
|         $strings = explode(',', $this->value); | ||||
|         foreach ($strings as $string) { | ||||
|             $tag = Tag::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'tag'     => $string, | ||||
|                     'tagMode' => 'nothing', | ||||
|                     'user_id' => Auth::user()->id, | ||||
|                 ] | ||||
|             ); | ||||
|             $tags->push($tag); | ||||
|         } | ||||
|         $tags = $tags->merge($this->data['tags']); | ||||
|  | ||||
|         return $tags; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Helpers/Csv/Converter/TagsSpace.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Helpers/Csv/Converter/TagsSpace.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Tag; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class TagsSpace | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class TagsSpace extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $tags = new Collection; | ||||
|  | ||||
|         $strings = explode(' ', $this->value); | ||||
|         foreach ($strings as $string) { | ||||
|             $tag = Tag::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'tag'     => $string, | ||||
|                     'tagMode' => 'nothing', | ||||
|                     'user_id' => Auth::user()->id, | ||||
|                 ] | ||||
|             ); | ||||
|             $tags->push($tag); | ||||
|         } | ||||
|         $tags = $tags->merge($this->data['tags']); | ||||
|  | ||||
|         return $tags; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										283
									
								
								app/Helpers/Csv/Data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								app/Helpers/Csv/Data.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,283 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use Crypt; | ||||
| use League\Csv\Reader; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class Data | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| class Data | ||||
| { | ||||
|  | ||||
|     /** @var string */ | ||||
|     protected $csvFileContent; | ||||
|  | ||||
|     /** @var string */ | ||||
|     protected $csvFileLocation; | ||||
|     /** @var  string */ | ||||
|     protected $dateFormat; | ||||
|     /** @var  bool */ | ||||
|     protected $hasHeaders; | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $map = []; | ||||
|     /** @var  array */ | ||||
|     protected $mapped = []; | ||||
|     /** @var  Reader */ | ||||
|     protected $reader; | ||||
|     /** @var  array */ | ||||
|     protected $roles = []; | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $specifix = []; | ||||
|  | ||||
|     /** @var int */ | ||||
|     protected $importAccount = 0; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->sessionHasHeaders(); | ||||
|         $this->sessionDateFormat(); | ||||
|         $this->sessionCsvFileLocation(); | ||||
|         $this->sessionMap(); | ||||
|         $this->sessionRoles(); | ||||
|         $this->sessionMapped(); | ||||
|         $this->sessionSpecifix(); | ||||
|         $this->sessionImportAccount(); | ||||
|     } | ||||
|  | ||||
|     protected function sessionHasHeaders() | ||||
|     { | ||||
|         if (Session::has('csv-has-headers')) { | ||||
|             $this->hasHeaders = (bool)Session::get('csv-has-headers'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionImportAccount() | ||||
|     { | ||||
|         if (Session::has('csv-import-account')) { | ||||
|             $this->importAccount = intval(Session::get('csv-import-account')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionDateFormat() | ||||
|     { | ||||
|         if (Session::has('csv-date-format')) { | ||||
|             $this->dateFormat = (string)Session::get('csv-date-format'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionCsvFileLocation() | ||||
|     { | ||||
|         if (Session::has('csv-file')) { | ||||
|             $this->csvFileLocation = (string)Session::get('csv-file'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionMap() | ||||
|     { | ||||
|         if (Session::has('csv-map')) { | ||||
|             $this->map = (array)Session::get('csv-map'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionRoles() | ||||
|     { | ||||
|         if (Session::has('csv-roles')) { | ||||
|             $this->roles = (array)Session::get('csv-roles'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionMapped() | ||||
|     { | ||||
|         if (Session::has('csv-mapped')) { | ||||
|             $this->mapped = (array)Session::get('csv-mapped'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionSpecifix() | ||||
|     { | ||||
|         if (Session::has('csv-specifix')) { | ||||
|             $this->specifix = (array)Session::get('csv-specifix'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getDateFormat() | ||||
|     { | ||||
|         return $this->dateFormat; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $dateFormat | ||||
|      */ | ||||
|     public function setDateFormat($dateFormat) | ||||
|     { | ||||
|         Session::put('csv-date-format', $dateFormat); | ||||
|         $this->dateFormat = $dateFormat; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $importAccount | ||||
|      */ | ||||
|     public function setImportAccount($importAccount) | ||||
|     { | ||||
|         Session::put('csv-import-account', $importAccount); | ||||
|         $this->importAccount = $importAccount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function hasHeaders() | ||||
|     { | ||||
|         return $this->hasHeaders; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param bool $hasHeaders | ||||
|      */ | ||||
|     public function setHasHeaders($hasHeaders) | ||||
|     { | ||||
|         Session::put('csv-has-headers', $hasHeaders); | ||||
|         $this->hasHeaders = $hasHeaders; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         return $this->map; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $map | ||||
|      */ | ||||
|     public function setMap(array $map) | ||||
|     { | ||||
|         Session::put('csv-map', $map); | ||||
|         $this->map = $map; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMapped() | ||||
|     { | ||||
|         return $this->mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $mapped | ||||
|      */ | ||||
|     public function setMapped(array $mapped) | ||||
|     { | ||||
|         Session::put('csv-mapped', $mapped); | ||||
|         $this->mapped = $mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Reader | ||||
|      */ | ||||
|     public function getReader() | ||||
|     { | ||||
|  | ||||
|         if (strlen($this->csvFileContent) === 0) { | ||||
|             $this->loadCsvFile(); | ||||
|         } | ||||
|  | ||||
|         if (is_null($this->reader)) { | ||||
|             $this->reader = Reader::createFromString($this->getCsvFileContent()); | ||||
|         } | ||||
|  | ||||
|         return $this->reader; | ||||
|     } | ||||
|  | ||||
|     protected function loadCsvFile() | ||||
|     { | ||||
|         $file             = $this->getCsvFileLocation(); | ||||
|         $content          = file_get_contents($file); | ||||
|         $contentDecrypted = Crypt::decrypt($content); | ||||
|         $this->setCsvFileContent($contentDecrypted); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getCsvFileLocation() | ||||
|     { | ||||
|         return $this->csvFileLocation; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $csvFileLocation | ||||
|      */ | ||||
|     public function setCsvFileLocation($csvFileLocation) | ||||
|     { | ||||
|         Session::put('csv-file', $csvFileLocation); | ||||
|         $this->csvFileLocation = $csvFileLocation; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getCsvFileContent() | ||||
|     { | ||||
|         return $this->csvFileContent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $csvFileContent | ||||
|      */ | ||||
|     public function setCsvFileContent($csvFileContent) | ||||
|     { | ||||
|         $this->csvFileContent = $csvFileContent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getRoles() | ||||
|     { | ||||
|         return $this->roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $roles | ||||
|      */ | ||||
|     public function setRoles(array $roles) | ||||
|     { | ||||
|         Session::put('csv-roles', $roles); | ||||
|         $this->roles = $roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getSpecifix() | ||||
|     { | ||||
|         return is_array($this->specifix) ? $this->specifix : []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $specifix | ||||
|      */ | ||||
|     public function setSpecifix($specifix) | ||||
|     { | ||||
|         Session::put('csv-specifix', $specifix); | ||||
|         $this->specifix = $specifix; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										371
									
								
								app/Helpers/Csv/Importer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								app/Helpers/Csv/Importer.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,371 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Csv\Converter\ConverterInterface; | ||||
| use FireflyIII\Helpers\Csv\PostProcessing\PostProcessorInterface; | ||||
| use FireflyIII\Helpers\Csv\Specifix\SpecifixInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class Importer | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| class Importer | ||||
| { | ||||
|  | ||||
|     /** @var Data */ | ||||
|     protected $data; | ||||
|     /** @var array */ | ||||
|     protected $errors; | ||||
|     /** @var  array */ | ||||
|     protected $importData; | ||||
|     /** @var  array */ | ||||
|     protected $importRow; | ||||
|     /** @var int */ | ||||
|     protected $imported = 0; | ||||
|     /** @var array */ | ||||
|     protected $map; | ||||
|     /** @var  array */ | ||||
|     protected $mapped; | ||||
|     /** @var  array */ | ||||
|     protected $roles; | ||||
|     /** @var  int */ | ||||
|     protected $rows = 0; | ||||
|     /** @var array */ | ||||
|     protected $specifix = []; | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $journals; | ||||
|  | ||||
|     /** | ||||
|      * Used by CsvController. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getErrors() | ||||
|     { | ||||
|         return $this->errors; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Used by CsvController | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getImported() | ||||
|     { | ||||
|         return $this->imported; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Used by CsvController | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getRows() | ||||
|     { | ||||
|         return $this->rows; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals() | ||||
|     { | ||||
|         return $this->journals; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function run() | ||||
|     { | ||||
|         set_time_limit(0); | ||||
|  | ||||
|         $this->journals = new Collection; | ||||
|         $this->map      = $this->data->getMap(); | ||||
|         $this->roles    = $this->data->getRoles(); | ||||
|         $this->mapped   = $this->data->getMapped(); | ||||
|         $this->specifix = $this->data->getSpecifix(); | ||||
|  | ||||
|         foreach ($this->data->getReader() as $index => $row) { | ||||
|             if ($this->parseRow($index)) { | ||||
|                 Log::debug('--- Importing row ' . $index); | ||||
|                 $this->rows++; | ||||
|                 $result = $this->importRow($row); | ||||
|                 if (!($result instanceof TransactionJournal)) { | ||||
|                     Log::error('Caught error at row #' . $index . ': ' . $result); | ||||
|                     $this->errors[$index] = $result; | ||||
|                 } else { | ||||
|                     $this->imported++; | ||||
|                     $this->journals->push($result); | ||||
|                 } | ||||
|                 Log::debug('---'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $index | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function parseRow($index) | ||||
|     { | ||||
|         return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $row | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return string|bool | ||||
|      */ | ||||
|     protected function importRow($row) | ||||
|     { | ||||
|  | ||||
|         $data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional | ||||
|         foreach ($row as $index => $value) { | ||||
|             $role  = isset($this->roles[$index]) ? $this->roles[$index] : '_ignore'; | ||||
|             $class = Config::get('csv.roles.' . $role . '.converter'); | ||||
|             $field = Config::get('csv.roles.' . $role . '.field'); | ||||
|  | ||||
|             Log::debug('Column #' . $index . ' (role: ' . $role . ') : converter ' . $class . ' stores its data into field ' . $field . ':'); | ||||
|  | ||||
|             /** @var ConverterInterface $converter */ | ||||
|             $converter = app('FireflyIII\Helpers\Csv\Converter\\' . $class); | ||||
|             $converter->setData($data); // the complete array so far. | ||||
|             $converter->setField($field); | ||||
|             $converter->setIndex($index); | ||||
|             $converter->setMapped($this->mapped); | ||||
|             $converter->setValue($value); | ||||
|             $converter->setRole($role); | ||||
|             $data[$field] = $converter->convert(); | ||||
|         } | ||||
|         // move to class vars. | ||||
|         $this->importData = $data; | ||||
|         $this->importRow  = $row; | ||||
|         unset($data, $row); | ||||
|         // post processing and validating. | ||||
|         $this->postProcess(); | ||||
|         $result = $this->validateData(); | ||||
|  | ||||
|         if (!($result === true)) { | ||||
|             return $result; // return error. | ||||
|         } | ||||
|         $journal = $this->createTransactionJournal(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getFiller() | ||||
|     { | ||||
|         $filler = []; | ||||
|         foreach (Config::get('csv.roles') as $role) { | ||||
|             if (isset($role['field'])) { | ||||
|                 $fieldName          = $role['field']; | ||||
|                 $filler[$fieldName] = null; | ||||
|             } | ||||
|         } | ||||
|         // some extra's: | ||||
|         $filler['bill-id']                 = null; | ||||
|         $filler['opposing-account-object'] = null; | ||||
|         $filler['asset-account-object']    = null; | ||||
|         $filler['amount-modifier']         = '1'; | ||||
|  | ||||
|         return $filler; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Row denotes the original data. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     protected function postProcess() | ||||
|     { | ||||
|         // do bank specific fixes (must be enabled but now all of them. | ||||
|  | ||||
|         foreach ($this->getSpecifix() as $className) { | ||||
|             /** @var SpecifixInterface $specifix */ | ||||
|             $specifix = app('FireflyIII\Helpers\Csv\Specifix\\' . $className); | ||||
|             $specifix->setData($this->importData); | ||||
|             $specifix->setRow($this->importRow); | ||||
|             Log::debug('Now post-process specifix named ' . $className . ':'); | ||||
|             $this->importData = $specifix->fix(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $set = Config::get('csv.post_processors'); | ||||
|         foreach ($set as $className) { | ||||
|             /** @var PostProcessorInterface $postProcessor */ | ||||
|             $postProcessor = app('FireflyIII\Helpers\Csv\PostProcessing\\' . $className); | ||||
|             $postProcessor->setData($this->importData); | ||||
|             Log::debug('Now post-process processor named ' . $className . ':'); | ||||
|             $this->importData = $postProcessor->process(); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getSpecifix() | ||||
|     { | ||||
|         return is_array($this->specifix) ? $this->specifix : []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return bool|string | ||||
|      */ | ||||
|     protected function validateData() | ||||
|     { | ||||
|         if (is_null($this->importData['date']) && is_null($this->importData['date-rent'])) { | ||||
|             return 'No date value for this row.'; | ||||
|         } | ||||
|         if (is_null($this->importData['opposing-account-object'])) { | ||||
|             return 'Opposing account is null'; | ||||
|         } | ||||
|  | ||||
|         if (!($this->importData['asset-account-object'] instanceof Account)) { | ||||
|             return 'No asset account to import into.'; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return TransactionJournal|string | ||||
|      */ | ||||
|     protected function createTransactionJournal() | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $date = $this->importData['date']; | ||||
|         if (is_null($this->importData['date'])) { | ||||
|             $date = $this->importData['date-rent']; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $transactionType = $this->getTransactionType(); // defaults to deposit | ||||
|         $errors          = new MessageBag; | ||||
|         $journal         = TransactionJournal::create( | ||||
|             ['user_id'     => Auth::user()->id, 'transaction_type_id' => $transactionType->id, 'transaction_currency_id' => $this->importData['currency']->id, | ||||
|              'description' => $this->importData['description'], 'completed' => 0, 'date' => $date, 'bill_id' => $this->importData['bill-id'],] | ||||
|         ); | ||||
|         if ($journal->getErrors()->count() == 0) { | ||||
|             // first transaction | ||||
|             $accountId   = $this->importData['asset-account-object']->id; // create first transaction: | ||||
|             $amount      = $this->importData['amount']; | ||||
|             $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); | ||||
|             $errors      = $transaction->getErrors(); | ||||
|  | ||||
|             // second transaction | ||||
|             $accountId   = $this->importData['opposing-account-object']->id; // create second transaction: | ||||
|             $amount      = bcmul($this->importData['amount'], -1); | ||||
|             $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); | ||||
|             $errors      = $transaction->getErrors()->merge($errors); | ||||
|         } | ||||
|         if ($errors->count() == 0) { | ||||
|             $journal->completed = 1; | ||||
|             $journal->save(); | ||||
|         } else { | ||||
|             $text = join(',', $errors->all()); | ||||
|  | ||||
|             return $text; | ||||
|         } | ||||
|         $this->saveBudget($journal); | ||||
|         $this->saveCategory($journal); | ||||
|         $this->saveTags($journal); | ||||
|  | ||||
|         // some debug info: | ||||
|         $journalId = $journal->id; | ||||
|         $type      = $journal->getTransactionType(); | ||||
|         /** @var Account $asset */ | ||||
|         $asset = $this->importData['asset-account-object']; | ||||
|         /** @var Account $opposing */ | ||||
|         $opposing = $this->importData['opposing-account-object']; | ||||
|  | ||||
|         Log::info('Created journal #' . $journalId . ' of type ' . $type . '!'); | ||||
|         Log::info('Asset account ****** (#' . $asset->id . ') lost/gained: ' . $this->importData['amount']); | ||||
|         Log::info($opposing->accountType->type . ' ****** (#' . $opposing->id . ') lost/gained: ' . bcmul($this->importData['amount'], -1)); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return TransactionType | ||||
|      */ | ||||
|     protected function getTransactionType() | ||||
|     { | ||||
|         $transactionType = TransactionType::where('type', TransactionType::DEPOSIT)->first(); | ||||
|         if ($this->importData['amount'] < 0) { | ||||
|             $transactionType = TransactionType::where('type', TransactionType::WITHDRAWAL)->first(); | ||||
|         } | ||||
|  | ||||
|         if (in_array($this->importData['opposing-account-object']->accountType->type, ['Asset account', 'Default account'])) { | ||||
|             $transactionType = TransactionType::where('type', TransactionType::TRANSFER)->first(); | ||||
|         } | ||||
|  | ||||
|         return $transactionType; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      */ | ||||
|     protected function saveBudget(TransactionJournal $journal) | ||||
|     { | ||||
|         // add budget: | ||||
|         if (!is_null($this->importData['budget'])) { | ||||
|             $journal->budgets()->save($this->importData['budget']); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      */ | ||||
|     protected function saveCategory(TransactionJournal $journal) | ||||
|     { | ||||
|         // add category: | ||||
|         if (!is_null($this->importData['category'])) { | ||||
|             $journal->categories()->save($this->importData['category']); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      */ | ||||
|     protected function saveTags(TransactionJournal $journal) | ||||
|     { | ||||
|         if (!is_null($this->importData['tags'])) { | ||||
|             foreach ($this->importData['tags'] as $tag) { | ||||
|                 $journal->tags()->save($tag); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Data $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/AnyAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/AnyAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class AnyAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class AnyAccount implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->accounts()->with('accountType')->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|  | ||||
|         $list = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $list[$account->id] = $account->name . ' (' . $account->accountType->type . ')'; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Helpers/Csv/Mapper/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Helpers/Csv/Mapper/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class AssetAccount implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->accounts()->with( | ||||
|             ['accountmeta' => function (HasMany $query) { | ||||
|                 $query->where('name', 'accountRole'); | ||||
|             }] | ||||
|         )->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|  | ||||
|         $list = []; | ||||
|  | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $name = $account->name; | ||||
|             if (strlen($account->iban) > 0) { | ||||
|                 $name .= ' (' . $account->iban . ')'; | ||||
|             } | ||||
|             $list[$account->id] = $name; | ||||
|         } | ||||
|  | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill as BillModel; | ||||
|  | ||||
| /** | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Bill implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->bills()->get(['bills.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var BillModel $bill */ | ||||
|         foreach ($result as $bill) { | ||||
|             $list[$bill->id] = $bill->name . ' [' . $bill->match . ']'; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Budget.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Budget.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
|  | ||||
| /** | ||||
|  * Class Budget | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Budget implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->budgets()->get(['budgets.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var BudgetModel $budget */ | ||||
|         foreach ($result as $budget) { | ||||
|             $list[$budget->id] = $budget->name; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Category.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Category.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category as CategoryModel; | ||||
|  | ||||
| /** | ||||
|  * Class Category | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Category implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->categories()->get(['categories.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var CategoryModel $category */ | ||||
|         foreach ($result as $category) { | ||||
|             $list[$category->id] = $category->name; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										16
									
								
								app/Helpers/Csv/Mapper/MapperInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/Helpers/Csv/Mapper/MapperInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| /** | ||||
|  * Interface MapperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| interface MapperInterface | ||||
| { | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap(); | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Tag.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Tag.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Tag as TagModel; | ||||
|  | ||||
| /** | ||||
|  * Class Tag | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Tag implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->budgets()->get(['tags.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var TagModel $tag */ | ||||
|         foreach ($result as $tag) { | ||||
|             $list[$tag->id] = $tag->tag; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Helpers/Csv/Mapper/TransactionCurrency.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Helpers/Csv/Mapper/TransactionCurrency.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency as TC; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionCurrency | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class TransactionCurrency implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $currencies = TC::get(); | ||||
|         $list       = []; | ||||
|         foreach ($currencies as $currency) { | ||||
|             $list[$currency->id] = $currency->name . ' (' . $currency->code . ')'; | ||||
|         } | ||||
|  | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Helpers/Csv/PostProcessing/Amount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Helpers/Csv/PostProcessing/Amount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| /** | ||||
|  * Class Amount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Amount implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $this->data['amount'] = bcmul($this->data['amount'], $this->data['amount-modifier']); | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										185
									
								
								app/Helpers/Csv/PostProcessing/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								app/Helpers/Csv/PostProcessing/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use Log; | ||||
| use Validator; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class AssetAccount implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         $result = $this->checkIdNameObject(); // has object in ID or Name? | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkIbanString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkNameString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function checkIdNameObject() | ||||
|     { | ||||
|         if ($this->data['asset-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any | ||||
|             $this->data['asset-account-object'] = $this->data['asset-account-id']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if ($this->data['asset-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any. | ||||
|             $this->data['asset-account-object'] = $this->data['asset-account-iban']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkIbanString() | ||||
|     { | ||||
|         $rules     = ['iban' => 'iban']; | ||||
|         $check     = ['iban' => $this->data['asset-account-iban']]; | ||||
|         $validator = Validator::make($check, $rules); | ||||
|         if (!$validator->fails()) { | ||||
|             $this->data['asset-account-object'] = $this->parseIbanString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseIbanString() | ||||
|     { | ||||
|         // create by name and/or iban. | ||||
|         $accounts = Auth::user()->accounts()->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->iban == $this->data['asset-account-iban']) { | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         $account = $this->createAccount(); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function createAccount() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|  | ||||
|         // create if not exists: | ||||
|         $name    = is_string($this->data['asset-account-name']) && strlen($this->data['asset-account-name']) > 0 ? $this->data['asset-account-name'] | ||||
|             : $this->data['asset-account-iban']; | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $name, | ||||
|                 'iban'            => $this->data['asset-account-iban'], | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return AccountType | ||||
|      */ | ||||
|     protected function getAccountType() | ||||
|     { | ||||
|         return AccountType::where('type', 'Asset account')->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkNameString() | ||||
|     { | ||||
|         if ($this->data['asset-account-name'] instanceof Account) { // third: try to find account based on name, if any. | ||||
|             $this->data['asset-account-object'] = $this->data['asset-account-name']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if (is_string($this->data['asset-account-name'])) { | ||||
|             $this->data['asset-account-object'] = $this->parseNameString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseNameString() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|         $accounts    = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->name == $this->data['asset-account-name']) { | ||||
|                 Log::debug('Found an asset account with this name (#' . $entry->id . ': ******)'); | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         // create if not exists: | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $this->data['asset-account-name'], | ||||
|                 'iban'            => '', | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								app/Helpers/Csv/PostProcessing/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Helpers/Csv/PostProcessing/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| /** | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Bill implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|  | ||||
|         // get bill id. | ||||
|         if (!is_null($this->data['bill'])) { | ||||
|             $this->data['bill-id'] = $this->data['bill']->id; | ||||
|         } | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										41
									
								
								app/Helpers/Csv/PostProcessing/Currency.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Helpers/Csv/PostProcessing/Currency.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class Currency | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Currency implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|  | ||||
|         // fix currency | ||||
|         if (is_null($this->data['currency'])) { | ||||
|             $currencyPreference     = Preferences::get('currencyPreference', env('DEFAULT_CURRENCY', 'EUR')); | ||||
|             $this->data['currency'] = TransactionCurrency::whereCode($currencyPreference->data)->first(); | ||||
|         } | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/PostProcessing/Description.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/PostProcessing/Description.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| /** | ||||
|  * Class Description | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Description implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         $this->data['description'] = trim($this->data['description']); | ||||
|         if (strlen($this->data['description']) == 0) { | ||||
|             $this->data['description'] = trans('firefly.csv_empty_description'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|  | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										210
									
								
								app/Helpers/Csv/PostProcessing/OpposingAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								app/Helpers/Csv/PostProcessing/OpposingAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use Log; | ||||
| use Validator; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class OpposingAccount implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         // three values: | ||||
|         // opposing-account-id, opposing-account-iban, opposing-account-name | ||||
|  | ||||
|  | ||||
|         $result = $this->checkIdNameObject(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkIbanString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkNameString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function checkIdNameObject() | ||||
|     { | ||||
|         if ($this->data['opposing-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-id is an Account.'); | ||||
|             $this->data['opposing-account-object'] = $this->data['opposing-account-id']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if ($this->data['opposing-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any. | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-iban is an Account.'); | ||||
|             $this->data['opposing-account-object'] = $this->data['opposing-account-iban']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkIbanString() | ||||
|     { | ||||
|         $rules     = ['iban' => 'iban']; | ||||
|         $iban      = $this->data['opposing-account-iban']; | ||||
|         $check     = ['iban' => $iban]; | ||||
|         $validator = Validator::make($check, $rules); | ||||
|         if (is_string($iban) && strlen($iban) > 0 && !$validator->fails()) { | ||||
|  | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-iban is a string (******).'); | ||||
|             $this->data['opposing-account-object'] = $this->parseIbanString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseIbanString() | ||||
|     { | ||||
|         // create by name and/or iban. | ||||
|         $accounts = Auth::user()->accounts()->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->iban == $this->data['opposing-account-iban']) { | ||||
|                 Log::debug('OpposingAccountPostProcession: opposing-account-iban matches an Account.'); | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         $account = $this->createAccount(); | ||||
|  | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function createAccount() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|  | ||||
|         // create if not exists: | ||||
|         $name    = is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name'] | ||||
|             : $this->data['opposing-account-iban']; | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $name, | ||||
|                 'iban'            => $this->data['opposing-account-iban'], | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|         Log::debug('OpposingAccountPostProcession: created a new account.'); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return AccountType | ||||
|      */ | ||||
|     protected function getAccountType() | ||||
|     { | ||||
|         // opposing account type: | ||||
|         if ($this->data['amount'] < 0) { | ||||
|             // create expense account: | ||||
|  | ||||
|             return AccountType::where('type', 'Expense account')->first(); | ||||
|         } else { | ||||
|             // create revenue account: | ||||
|  | ||||
|             return AccountType::where('type', 'Revenue account')->first(); | ||||
|  | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkNameString() | ||||
|     { | ||||
|         if ($this->data['opposing-account-name'] instanceof Account) { // third: try to find account based on name, if any. | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-name is an Account.'); | ||||
|             $this->data['opposing-account-object'] = $this->data['opposing-account-name']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if (is_string($this->data['opposing-account-name'])) { | ||||
|  | ||||
|             $this->data['opposing-account-object'] = $this->parseNameString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseNameString() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|         $accounts    = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->name == $this->data['opposing-account-name']) { | ||||
|                 Log::debug('Found an account with this name (#' . $entry->id . ': ******)'); | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         // create if not exists: | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $this->data['opposing-account-name'], | ||||
|                 'iban'            => '', | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Helpers/Csv/PostProcessing/PostProcessorInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Helpers/Csv/PostProcessing/PostProcessorInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 05/07/15 | ||||
|  * Time: 19:20 | ||||
|  */ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Interface PostProcessorInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| interface PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process(); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data); | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Helpers/Csv/Specifix/Dummy.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Helpers/Csv/Specifix/Dummy.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Specifix; | ||||
|  | ||||
| /** | ||||
|  * Class Dummy | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Specifix | ||||
|  */ | ||||
| class Dummy | ||||
| { | ||||
|     /** @var array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $row; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function fix() | ||||
|     { | ||||
|         return $this->data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row) | ||||
|     { | ||||
|         $this->row = $row; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										66
									
								
								app/Helpers/Csv/Specifix/RabobankDescription.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								app/Helpers/Csv/Specifix/RabobankDescription.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Specifix; | ||||
|  | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RabobankDescription | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Specifix | ||||
|  */ | ||||
| class RabobankDescription | ||||
| { | ||||
|     /** @var array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $row; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function fix() | ||||
|     { | ||||
|         $this->rabobankFixEmptyOpposing(); | ||||
|  | ||||
|         return $this->data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row) | ||||
|     { | ||||
|         $this->row = $row; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Fixes Rabobank specific thing. | ||||
|      */ | ||||
|     protected function rabobankFixEmptyOpposing() | ||||
|     { | ||||
|         Log::debug('RaboSpecifix: Opposing account name is "******".'); | ||||
|         if (is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) == 0) { | ||||
|             Log::debug('RaboSpecifix: opp-name is zero length, changed to: "******"'); | ||||
|             $this->data['opposing-account-name'] = $this->row[10]; | ||||
|  | ||||
|             Log::debug('Description was: "******".'); | ||||
|             $this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description'])); | ||||
|             Log::debug('Description is now: "******".'); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										25
									
								
								app/Helpers/Csv/Specifix/SpecifixInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Helpers/Csv/Specifix/SpecifixInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Specifix; | ||||
|  | ||||
| /** | ||||
|  * Interface SpecifixInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Specifix | ||||
|  */ | ||||
| interface SpecifixInterface | ||||
| { | ||||
|     /** | ||||
|      * Implement bank and locale related fixes. | ||||
|      */ | ||||
|     public function fix(); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data); | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row); | ||||
| } | ||||
							
								
								
									
										194
									
								
								app/Helpers/Csv/Wizard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								app/Helpers/Csv/Wizard.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Crypt; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Csv\Mapper\MapperInterface; | ||||
| use League\Csv\Reader; | ||||
| use Log; | ||||
| use ReflectionException; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class Wizard | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| class Wizard implements WizardInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Reader $reader | ||||
|      * @param array  $map | ||||
|      * @param bool   $hasHeaders | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMappableValues($reader, array $map, $hasHeaders) | ||||
|     { | ||||
|         $values = []; | ||||
|         /* | ||||
|          * Loop over the CSV and collect mappable data: | ||||
|          */ | ||||
|         $keys = array_keys($map); | ||||
|         foreach ($reader as $index => $row) { | ||||
|             if ($this->useRow($hasHeaders, $index)) { | ||||
|                 // collect all map values | ||||
|  | ||||
|                 foreach ($keys as $column) { | ||||
|                     $values[$column][] = $row[$column]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         /* | ||||
|          * Make each one unique. | ||||
|          */ | ||||
|         $values = $this->uniqueRecursive($values); | ||||
|  | ||||
|         return $values; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $roles | ||||
|      * @param mixed $map | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedMapping(array $roles, $map) | ||||
|     { | ||||
|         $configRoles = Config::get('csv.roles'); | ||||
|         $maps        = []; | ||||
|  | ||||
|  | ||||
|         if (is_array($map)) { | ||||
|             foreach ($map as $index => $field) { | ||||
|                 if (isset($roles[$index])) { | ||||
|                     $name = $roles[$index]; | ||||
|                     if ($configRoles[$name]['mappable']) { | ||||
|                         $maps[$index] = $name; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $maps; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $input | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedRoles($input) | ||||
|     { | ||||
|         $roles = []; | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Store all rows for each column: | ||||
|          */ | ||||
|         if (is_array($input)) { | ||||
|             foreach ($input as $index => $role) { | ||||
|                 if ($role != '_ignore') { | ||||
|                     $roles[$index] = $role; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function sessionHasValues(array $fields) | ||||
|     { | ||||
|         foreach ($fields as $field) { | ||||
|             if (!Session::has($field)) { | ||||
|                 Log::error('Session is missing field: ' . $field); | ||||
|  | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $map | ||||
|      * | ||||
|      * @return array | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function showOptions(array $map) | ||||
|     { | ||||
|         $options = []; | ||||
|         foreach ($map as $index => $columnRole) { | ||||
|  | ||||
|             $mapper = Config::get('csv.roles.' . $columnRole . '.mapper'); | ||||
|             if (is_null($mapper)) { | ||||
|                 throw new FireflyException('Cannot map field of type "' . $columnRole . '".'); | ||||
|             } | ||||
|             $class = 'FireflyIII\Helpers\Csv\Mapper\\' . $mapper; | ||||
|             try { | ||||
|                 /** @var MapperInterface $mapObject */ | ||||
|                 $mapObject = app($class); | ||||
|             } catch (ReflectionException $e) { | ||||
|                 throw new FireflyException('Column "' . $columnRole . '" cannot be mapped because class ' . $mapper . ' does not exist.'); | ||||
|             } | ||||
|             $set             = $mapObject->getMap(); | ||||
|             $options[$index] = $set; | ||||
|         } | ||||
|  | ||||
|         return $options; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $path | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function storeCsvFile($path) | ||||
|     { | ||||
|         $time             = str_replace(' ', '-', microtime()); | ||||
|         $fileName         = 'csv-upload-' . Auth::user()->id . '-' . $time . '.csv.encrypted'; | ||||
|         $fullPath         = storage_path('upload') . DIRECTORY_SEPARATOR . $fileName; | ||||
|         $content          = file_get_contents($path); | ||||
|         $contentEncrypted = Crypt::encrypt($content); | ||||
|         file_put_contents($fullPath, $contentEncrypted); | ||||
|  | ||||
|         return $fullPath; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param bool $hasHeaders | ||||
|      * @param int  $index | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function useRow($hasHeaders, $index) | ||||
|     { | ||||
|         return ($hasHeaders && $index > 1) || !$hasHeaders; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $array | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function uniqueRecursive(array $array) | ||||
|     { | ||||
|         foreach ($array as $column => $found) { | ||||
|             $array[$column] = array_unique($found); | ||||
|         } | ||||
|  | ||||
|         return $array; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										59
									
								
								app/Helpers/Csv/WizardInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								app/Helpers/Csv/WizardInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use League\Csv\Reader; | ||||
|  | ||||
| /** | ||||
|  * Interface WizardInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| interface WizardInterface | ||||
| { | ||||
|     /** | ||||
|      * @param Reader $reader | ||||
|      * @param array  $map | ||||
|      * @param bool   $hasHeaders | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMappableValues($reader, array $map, $hasHeaders); | ||||
|  | ||||
|     /** | ||||
|      * @param array $roles | ||||
|      * @param mixed $map | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedMapping(array $roles, $map); | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $input | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedRoles($input); | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function sessionHasValues(array $fields); | ||||
|  | ||||
|     /** | ||||
|      * @param array $map | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function showOptions(array $map); | ||||
|  | ||||
|     /** | ||||
|      * @param $path | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function storeCsvFile($path); | ||||
|  | ||||
| } | ||||
| @@ -17,6 +17,8 @@ class Help implements HelpInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $key | ||||
|      * | ||||
|      * @return string | ||||
| @@ -27,16 +29,20 @@ class Help implements HelpInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getFromGithub($route) | ||||
|     { | ||||
|         $uri     = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md'; | ||||
|         $content = [ | ||||
|         $uri        = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md'; | ||||
|         $routeIndex = str_replace('.', '-', $route); | ||||
|         $title      = trans('help.' . $routeIndex); | ||||
|         $content    = [ | ||||
|             'text'  => '<p>There is no help for this route!</p>', | ||||
|             'title' => $route, | ||||
|             'title' => $title, | ||||
|         ]; | ||||
|         try { | ||||
|             $content['text'] = file_get_contents($uri); | ||||
| @@ -54,6 +60,8 @@ class Help implements HelpInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
| @@ -64,6 +72,20 @@ class Help implements HelpInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function inCache($route) | ||||
|     { | ||||
|         return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param       $route | ||||
|      * @param array $content | ||||
|      * | ||||
| @@ -74,14 +96,4 @@ class Help implements HelpInterface | ||||
|         Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week. | ||||
|         Cache::put('help.' . $route . '.title', $content['title'], 10080); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function inCache($route) | ||||
|     { | ||||
|         return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,145 +0,0 @@ | ||||
| <?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. | ||||
|             $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'); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Reminders; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Reminder; | ||||
|  | ||||
| /** | ||||
|  * Interface ReminderHelperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Reminders | ||||
|  */ | ||||
| interface ReminderHelperInterface | ||||
| { | ||||
|     /** | ||||
|      * Takes a reminder, finds the piggy bank and tells you what to do now. | ||||
|      * Aka how much money to put in. | ||||
|      * | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getReminderText(Reminder $reminder); | ||||
|  | ||||
|     /** | ||||
|      * This routine will return an array consisting of two dates which indicate the start | ||||
|      * and end date for each reminder that this piggy bank will have, if the piggy bank has | ||||
|      * any reminders. For example: | ||||
|      * | ||||
|      * [12 mar - 15 mar] | ||||
|      * [15 mar - 18 mar] | ||||
|      * | ||||
|      * etcetera. | ||||
|      * | ||||
|      * Array is filled with tiny arrays with Carbon objects in them. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getReminderRanges(PiggyBank $piggyBank); | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $start | ||||
|      * @param Carbon    $end | ||||
|      * | ||||
|      * @return Reminder | ||||
|      */ | ||||
|     public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end); | ||||
| } | ||||
| @@ -2,13 +2,27 @@ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use App; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use FireflyIII\Helpers\Collection\Account as AccountCollection; | ||||
| use FireflyIII\Helpers\Collection\Balance; | ||||
| use FireflyIII\Helpers\Collection\BalanceEntry; | ||||
| use FireflyIII\Helpers\Collection\BalanceHeader; | ||||
| use FireflyIII\Helpers\Collection\BalanceLine; | ||||
| use FireflyIII\Helpers\Collection\Bill as BillCollection; | ||||
| use FireflyIII\Helpers\Collection\BillLine; | ||||
| use FireflyIII\Helpers\Collection\Budget as BudgetCollection; | ||||
| use FireflyIII\Helpers\Collection\BudgetLine; | ||||
| use FireflyIII\Helpers\Collection\Category as CategoryCollection; | ||||
| use FireflyIII\Helpers\Collection\Expense; | ||||
| use FireflyIII\Helpers\Collection\Income; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class ReportHelper | ||||
| @@ -18,66 +32,44 @@ use Steam; | ||||
| 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); | ||||
|     /** @var ReportQueryInterface */ | ||||
|     protected $query; | ||||
|  | ||||
|         return $limited; | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param ReportQueryInterface $query | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(ReportQueryInterface $query) | ||||
|     { | ||||
|         $this->query = $query; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method gets some kind of list for a monthly overview. | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @return CategoryCollection | ||||
|      */ | ||||
|     public function getBudgetsForMonth(Carbon $date, $showSharedReports = false) | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         /** @var \FireflyIII\Helpers\Report\ReportQueryInterface $query */ | ||||
|         $query = App::make('FireflyIII\Helpers\Report\ReportQueryInterface'); | ||||
|         $object = new CategoryCollection; | ||||
|  | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|         $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 queryAmount']); | ||||
|         /** | ||||
|          * GET CATEGORIES: | ||||
|          */ | ||||
|         /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|  | ||||
|         $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]['queryAmount'] = isset($budgets[0]['queryAmount']) ? $budgets[0]['queryAmount'] : 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)->sum('queryAmount'); | ||||
|             $budgets[0]['spent'] += floatval($transfers) * -1; | ||||
|         $set = $repository->spentForAccountsPerMonth($accounts, $start, $end); | ||||
|         foreach ($set as $category) { | ||||
|             $object->addCategory($category); | ||||
|         } | ||||
|  | ||||
|         return $budgets; | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -87,13 +79,27 @@ class ReportHelper implements ReportHelperInterface | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date) | ||||
|     { | ||||
|  | ||||
|         $start  = clone $date; | ||||
|         $end    = Carbon::now(); | ||||
|         $months = []; | ||||
|         while ($start <= $end) { | ||||
|             $year            = $start->year; | ||||
|             $months[$year][] = [ | ||||
|                 'formatted' => $start->format('F Y'), | ||||
|             $year = $start->year; | ||||
|  | ||||
|             if (!isset($months[$year])) { | ||||
|                 $months[$year] = [ | ||||
|                     'start'  => Carbon::createFromDate($year, 1, 1)->format('Y-m-d'), | ||||
|                     'end'    => Carbon::createFromDate($year, 12, 31)->format('Y-m-d'), | ||||
|                     'months' => [], | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             $currentEnd = clone $start; | ||||
|             $currentEnd->endOfMonth(); | ||||
|             $months[$year]['months'][] = [ | ||||
|                 'formatted' => $start->formatLocalized('%B %Y'), | ||||
|                 'start'     => $start->format('Y-m-d'), | ||||
|                 'end'       => $currentEnd->format('Y-m-d'), | ||||
|                 'month'     => $start->month, | ||||
|                 'year'      => $year, | ||||
|             ]; | ||||
| @@ -104,75 +110,405 @@ class ReportHelper implements ReportHelperInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * This method generates a full report for the given period on all | ||||
|      * given accounts | ||||
|      * | ||||
|      * @return array | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return AccountCollection | ||||
|      */ | ||||
|     public function listOfYears(Carbon $date) | ||||
|     public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $start = clone $date; | ||||
|         $end   = Carbon::now(); | ||||
|         $years = []; | ||||
|         while ($start <= $end) { | ||||
|             $years[] = $start->year; | ||||
|             $start->addYear(); | ||||
|         } | ||||
|         $years[] = Carbon::now()->year; | ||||
|         // force the current year. | ||||
|         $years = array_unique($years); | ||||
|         $startAmount = '0'; | ||||
|         $endAmount   = '0'; | ||||
|         $diff        = '0'; | ||||
|         $ids         = $accounts->pluck('id')->toArray(); | ||||
|  | ||||
|         return $years; | ||||
|         $yesterday = clone $start; | ||||
|         $yesterday->subDay(); | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|         // get balances for start. | ||||
|         $startSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                            ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                            ->whereIn('accounts.id', $ids) | ||||
|                            ->whereNull('transaction_journals.deleted_at') | ||||
|                            ->whereNull('transactions.deleted_at') | ||||
|                            ->where('transaction_journals.date', '<=', $yesterday->format('Y-m-d')) | ||||
|                            ->groupBy('accounts.id') | ||||
|                            ->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]); | ||||
|  | ||||
|         // and for end: | ||||
|         $endSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                          ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                          ->whereIn('accounts.id', $ids) | ||||
|                          ->whereNull('transaction_journals.deleted_at') | ||||
|                          ->whereNull('transactions.deleted_at') | ||||
|                          ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                          ->groupBy('accounts.id') | ||||
|                          ->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]); | ||||
|  | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($startSet, $endSet) { | ||||
|                 /** | ||||
|                  * The balance for today always incorporates transactions | ||||
|                  * made on today. So to get todays "start" balance, we sub one | ||||
|                  * day. | ||||
|                  */ | ||||
|                 // | ||||
|                 $currentStart = $startSet->filter( | ||||
|                     function (Account $entry) use ($account) { | ||||
|                         return $account->id == $entry->id; | ||||
|                     } | ||||
|                 ); | ||||
|                 if ($currentStart->first()) { | ||||
|                     $account->startBalance = $currentStart->first()->balance; | ||||
|                 } | ||||
|  | ||||
|                 $currentEnd = $endSet->filter( | ||||
|                     function (Account $entry) use ($account) { | ||||
|                         return $account->id == $entry->id; | ||||
|                     } | ||||
|                 ); | ||||
|                 if ($currentEnd->first()) { | ||||
|                     $account->endBalance = $currentEnd->first()->balance; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         // summarize: | ||||
|         foreach ($accounts as $account) { | ||||
|             $startAmount = bcadd($startAmount, $account->startBalance); | ||||
|             $endAmount   = bcadd($endAmount, $account->endBalance); | ||||
|             $diff        = bcadd($diff, bcsub($account->endBalance, $account->startBalance)); | ||||
|         } | ||||
|  | ||||
|         $object = new AccountCollection; | ||||
|         $object->setStart($startAmount); | ||||
|         $object->setEnd($endAmount); | ||||
|         $object->setDifference($diff); | ||||
|         $object->setAccounts($accounts); | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * Get a full report on the users incomes during the period for the given accounts. | ||||
|      * | ||||
|      * @return array | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Income | ||||
|      */ | ||||
|     public function yearBalanceReport(Carbon $date, $showSharedReports = false) | ||||
|     public function getIncomeReport($start, $end, Collection $accounts) | ||||
|     { | ||||
|         $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']); | ||||
|         $object = new Income; | ||||
|         $set    = $this->query->income($accounts, $start, $end); | ||||
|  | ||||
|             foreach ($sharedCollection as $account) { | ||||
|                 $sharedAccounts[] = $account->id; | ||||
|             } | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->journalAmount); | ||||
|             $object->addOrCreateIncome($entry); | ||||
|         } | ||||
|  | ||||
|         $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 $object; | ||||
|     } | ||||
|  | ||||
|                                 return null; | ||||
|                             } | ||||
|                         ); | ||||
|         $report   = []; | ||||
|         $start->startOfYear()->subDay(); | ||||
|         $end->endOfYear(); | ||||
|     /** | ||||
|      * Get a full report on the users expenses during the period for a list of accounts. | ||||
|      * | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Expense | ||||
|      */ | ||||
|     public function getExpenseReport($start, $end, Collection $accounts) | ||||
|     { | ||||
|         $object = new Expense; | ||||
|         $set    = $this->query->expense($accounts, $start, $end); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->journalAmount); // can be positive, if it's a transfer | ||||
|             $object->addOrCreateExpense($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return BudgetCollection | ||||
|      */ | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $object = new BudgetCollection; | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository     = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $set            = $repository->getBudgets(); | ||||
|         $allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end); | ||||
|         $allTotalSpent  = $repository->spentAllPerDayForAccounts($accounts, $start, $end); | ||||
|         bcscale(2); | ||||
|  | ||||
|         foreach ($set as $budget) { | ||||
|  | ||||
|             $repetitions = $allRepetitions->filter( | ||||
|                 function (LimitRepetition $rep) use ($budget) { | ||||
|                     return $rep->budget_id == $budget->id; | ||||
|                 } | ||||
|             ); | ||||
|             $totalSpent  = isset($allTotalSpent[$budget->id]) ? $allTotalSpent[$budget->id] : []; | ||||
|  | ||||
|             // no repetition(s) for this budget: | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $spent      = array_sum($totalSpent); | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setOverspent($spent); | ||||
|                 $object->addOverspent($spent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // one or more repetitions for budget: | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setRepetition($repetition); | ||||
|                 $expenses = $this->getSumOfRange($start, $end, $totalSpent); | ||||
|  | ||||
|                 // 200 en -100 is 100, vergeleken met 0 === 1 | ||||
|                 // 200 en -200 is 0, vergeleken met 0 === 0 | ||||
|                 // 200 en -300 is -100, vergeleken met 0 === -1 | ||||
|  | ||||
|                 $left      = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? bcadd($repetition->amount, $expenses) : 0; | ||||
|                 $spent     = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? $expenses : '0'; | ||||
|                 $overspent = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? '0' : bcadd($expenses, $repetition->amount); | ||||
|  | ||||
|                 $budgetLine->setLeft($left); | ||||
|                 $budgetLine->setSpent($spent); | ||||
|                 $budgetLine->setOverspent($overspent); | ||||
|                 $budgetLine->setBudgeted($repetition->amount); | ||||
|  | ||||
|                 $object->addBudgeted($repetition->amount); | ||||
|                 $object->addSpent($spent); | ||||
|                 $object->addLeft($left); | ||||
|                 $object->addOverspent($overspent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // stuff outside of budgets: | ||||
|         $noBudget   = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $budgetLine = new BudgetLine; | ||||
|         $budgetLine->setOverspent($noBudget); | ||||
|         $budgetLine->setSpent($noBudget); | ||||
|         $object->addOverspent($noBudget); | ||||
|         $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Balance | ||||
|      */ | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|  | ||||
|         /** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */ | ||||
|         $tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); | ||||
|  | ||||
|         $balance = new Balance; | ||||
|  | ||||
|         // build a balance header: | ||||
|         $header    = new BalanceHeader; | ||||
|         $budgets   = $repository->getBudgetsAndLimitsInRange($start, $end); | ||||
|         $spentData = $repository->spentPerBudgetPerAccount($budgets, $accounts, $start, $end); | ||||
|         foreach ($accounts as $account) { | ||||
|             $header->addAccount($account); | ||||
|         } | ||||
|  | ||||
|         /** @var BudgetModel $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $line = new BalanceLine; | ||||
|             $line->setBudget($budget); | ||||
|  | ||||
|             // loop accounts: | ||||
|             foreach ($accounts as $account) { | ||||
|                 $balanceEntry = new BalanceEntry; | ||||
|                 $balanceEntry->setAccount($account); | ||||
|  | ||||
|                 // get spent: | ||||
|                 $entry = $spentData->filter( | ||||
|                     function (TransactionJournal $model) use ($budget, $account) { | ||||
|                         return $model->account_id == $account->id && $model->budget_id == $budget->id; | ||||
|                     } | ||||
|                 ); | ||||
|                 $spent = 0; | ||||
|                 if (!is_null($entry->first())) { | ||||
|                     $spent = $entry->first()->spent; | ||||
|                 } | ||||
|                 $balanceEntry->setSpent($spent); | ||||
|                 $line->addBalanceEntry($balanceEntry); | ||||
|             } | ||||
|             // add line to balance: | ||||
|             $balance->addBalanceLine($line); | ||||
|         } | ||||
|  | ||||
|         // then a new line for without budget. | ||||
|         // and one for the tags: | ||||
|         // and one for "left unbalanced". | ||||
|         $empty    = new BalanceLine; | ||||
|         $tags     = new BalanceLine; | ||||
|         $diffLine = new BalanceLine; | ||||
|         $tagsLeft = $tagRepository->allCoveredByBalancingActs($accounts, $start, $end); | ||||
|  | ||||
|         $tags->setRole(BalanceLine::ROLE_TAGROLE); | ||||
|         $diffLine->setRole(BalanceLine::ROLE_DIFFROLE); | ||||
|  | ||||
|         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' | ||||
|             ]; | ||||
|             $entry = $spentData->filter( | ||||
|                 function (TransactionJournal $model) use ($budget, $account) { | ||||
|                     return $model->account_id == $account->id && is_null($model->budget_id); | ||||
|                 } | ||||
|             ); | ||||
|             $spent = 0; | ||||
|             if (!is_null($entry->first())) { | ||||
|                 $spent = $entry->first()->spent; | ||||
|             } | ||||
|             $leftEntry = $tagsLeft->filter( | ||||
|                 function (Tag $tag) use ($account) { | ||||
|                     return $tag->account_id == $account->id; | ||||
|                 } | ||||
|             ); | ||||
|             $left      = 0; | ||||
|             if (!is_null($leftEntry->first())) { | ||||
|                 $left = $leftEntry->first()->sum; | ||||
|             } | ||||
|             bcscale(2); | ||||
|             $diff = bcadd($spent, $left); | ||||
|  | ||||
|             // budget | ||||
|             $budgetEntry = new BalanceEntry; | ||||
|             $budgetEntry->setAccount($account); | ||||
|             $budgetEntry->setSpent($spent); | ||||
|             $empty->addBalanceEntry($budgetEntry); | ||||
|  | ||||
|             // balanced by tags | ||||
|             $tagEntry = new BalanceEntry; | ||||
|             $tagEntry->setAccount($account); | ||||
|             $tagEntry->setLeft($left); | ||||
|             $tags->addBalanceEntry($tagEntry); | ||||
|  | ||||
|             // difference: | ||||
|             $diffEntry = new BalanceEntry; | ||||
|             $diffEntry->setAccount($account); | ||||
|             $diffEntry->setSpent($diff); | ||||
|             $diffLine->addBalanceEntry($diffEntry); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $report; | ||||
|         $balance->addBalanceLine($empty); | ||||
|         $balance->addBalanceLine($tags); | ||||
|         $balance->addBalanceLine($diffLine); | ||||
|  | ||||
|         $balance->setBalanceHeader($header); | ||||
|  | ||||
|         return $balance; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users bills and their payments. | ||||
|      * | ||||
|      * Excludes bills which have not had a payment on the mentioned accounts. | ||||
|      * | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return BillCollection | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $bills      = $repository->getBillsForAccounts($accounts); | ||||
|         $journals   = $repository->getAllJournalsInRange($bills, $start, $end); | ||||
|         $collection = new BillCollection; | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $billLine = new BillLine; | ||||
|             $billLine->setBill($bill); | ||||
|             $billLine->setActive(intval($bill->active) == 1); | ||||
|             $billLine->setMin($bill->amount_min); | ||||
|             $billLine->setMax($bill->amount_max); | ||||
|  | ||||
|             // is hit in period? | ||||
|             bcscale(2); | ||||
|  | ||||
|             $entry = $journals->filter( | ||||
|                 function (TransactionJournal $journal) use ($bill) { | ||||
|                     return $journal->bill_id == $bill->id; | ||||
|                 } | ||||
|             ); | ||||
|             if (!is_null($entry->first())) { | ||||
|                 $billLine->setAmount($entry->first()->journalAmount); | ||||
|                 $billLine->setHit(true); | ||||
|             } else { | ||||
|                 $billLine->setHit(false); | ||||
|             } | ||||
|  | ||||
|             $collection->addBill($billLine); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Take the array as returned by SingleCategoryRepositoryInterface::spentPerDay and SingleCategoryRepositoryInterface::earnedByDay | ||||
|      * and sum up everything in the array in the given range. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param array  $array | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function getSumOfRange(Carbon $start, Carbon $end, array $array) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $sum          = '0'; | ||||
|         $currentStart = clone $start; // to not mess with the original one | ||||
|         $currentEnd   = clone $end; // to not mess with the original one | ||||
|  | ||||
|         while ($currentStart <= $currentEnd) { | ||||
|             $date = $currentStart->format('Y-m-d'); | ||||
|             if (isset($array[$date])) { | ||||
|                 $sum = bcadd($sum, $array[$date]); | ||||
|             } | ||||
|             $currentStart->addDay(); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user