Compare commits

...

270 Commits

Author SHA1 Message Date
James Cole
b252b9da66 Merge branch 'release/3.4.3' 2015-06-01 17:37:02 +02:00
James Cole
cdef9c3c7e New version. 2015-06-01 17:36:53 +02:00
James Cole
71dcebb744 New read me [skip ci] 2015-06-01 17:36:13 +02:00
James Cole
25f248c60a New read me [skip ci] 2015-06-01 17:35:48 +02:00
James Cole
d5cbc17831 Update read me. 2015-06-01 17:35:03 +02:00
James Cole
7a10217511 New read me and scrutiniser instructions. 2015-05-31 20:53:31 +02:00
James Cole
7559efab77 Update build thing. 2015-05-31 20:52:20 +02:00
James Cole
8254efbd03 Fix modal. 2015-05-31 20:24:06 +02:00
James Cole
4ae24225a5 Cleanup some modals. 2015-05-31 20:23:49 +02:00
James Cole
67d9154563 Added some new code to implement a permission scheme. 2015-05-28 06:43:07 +02:00
James Cole
ad0319c188 Some new translations [skip ci] 2015-05-28 06:11:39 +02:00
James Cole
eb650ea3ec Some code cleanup 2015-05-27 08:36:26 +02:00
James Cole
7eba33e805 Fixed some issues for scrutiniser [skip ci] 2015-05-27 07:58:54 +02:00
James Cole
e1cb9d387e Fixed chart and redirect 2015-05-27 07:51:33 +02:00
James Cole
2ace7c3ca0 Some code cleanup [skip ci] 2015-05-27 07:27:05 +02:00
James Cole
58014f0592 Extra translation [skip ci] 2015-05-27 06:57:02 +02:00
James Cole
1d4938bb09 Small fix in error handler. 2015-05-26 22:12:34 +02:00
James Cole
bbf4007c3e Fixed return type [skip ci] 2015-05-26 20:59:16 +02:00
Sander Dorigo
4d5124fb4c Merge pull request #81 from JC5/scrutinizer-patch-4
Scrutinizer Auto-Fixes
2015-05-26 20:58:11 +02:00
Scrutinizer Auto-Fixer
14a7cd05b1 Scrutinizer Auto-Fixes
This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com
2015-05-26 18:57:31 +00:00
James Cole
946be80eef Fix route urls. 2015-05-26 20:37:01 +02:00
James Cole
9ad8b1a980 Some optimisations. 2015-05-26 20:28:18 +02:00
James Cole
f733216fcb Trigger a build. 2015-05-26 20:18:21 +02:00
Sander Dorigo
ffc6139e21 Merge pull request #80 from JC5/scrutinizer-patch-3
Scrutinizer Auto-Fixes
2015-05-26 20:16:39 +02:00
Scrutinizer Auto-Fixer
571cac6644 Scrutinizer Auto-Fixes
This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com
2015-05-26 17:50:09 +00:00
James Cole
2738ac5a5c Did some cleanup [skip ci] 2015-05-26 19:48:49 +02:00
James Cole
7dfde51b84 Fixed tests. 2015-05-26 19:38:52 +02:00
James Cole
2d2f18e538 Code cleanup. 2015-05-26 12:19:11 +02:00
James Cole
3af0dd2e3b Some code cleanup [skip ci] 2015-05-26 12:08:46 +02:00
James Cole
349e077802 Added model data to models to aid scrutiniser. 2015-05-26 11:15:45 +02:00
James Cole
812aae358f Some code cleanup. 2015-05-26 08:17:58 +02:00
James Cole
c3c59d0627 Fixed some JS things [skip ci] 2015-05-26 07:50:38 +02:00
James Cole
89518b412d Merge branch 'release/3.4.2' into develop 2015-05-25 23:18:33 +02:00
James Cole
f43b026162 Merge branch 'release/3.4.2' 2015-05-25 23:18:32 +02:00
James Cole
b806c70f52 New read me. 2015-05-25 22:58:49 +02:00
James Cole
10bff3c0b8 Fix tests. 2015-05-25 22:56:00 +02:00
James Cole
65c12fd0b2 Merge branch 'release/3.4.1' 2015-05-25 22:24:28 +02:00
James Cole
50f71c4130 Merge branch 'release/3.4.1' into develop 2015-05-25 22:24:28 +02:00
James Cole
8e401a53dc New version. 2015-05-25 22:24:21 +02:00
James Cole
64a289a47c Cleanup some code [skip ci] 2015-05-25 22:17:41 +02:00
James Cole
8f2c37061b Update translations [skip ci] 2015-05-25 22:16:00 +02:00
James Cole
39f2de6b90 Cleanup code [skip ci] 2015-05-25 22:04:24 +02:00
James Cole
855ba8d4f3 Cleanup [skip ci] 2015-05-25 22:01:48 +02:00
James Cole
74f098e718 Some new translations [skip ci] 2015-05-25 21:39:05 +02:00
James Cole
56c8a84691 Update translations [skip ci] 2015-05-25 21:26:34 +02:00
James Cole
8bbf319032 Some translations and a new test. 2015-05-25 21:17:36 +02:00
James Cole
afbca4ae65 Newline in travis.ml [skip ci] 2015-05-25 20:08:31 +02:00
James Cole
0ef6d2f91a Code cleanup. 2015-05-25 19:58:13 +02:00
James Cole
fbe4435599 Fix translation [skip ci] 2015-05-25 19:19:27 +02:00
James Cole
34be565dd1 New translations [skip ci] 2015-05-25 19:18:16 +02:00
James Cole
af838e4ed1 New translations. 2015-05-25 09:23:45 +02:00
James Cole
60fe8ce011 New GA events [skip ci] 2015-05-25 08:12:31 +02:00
James Cole
8ece341467 Add GA events [skip ci] 2015-05-25 08:01:06 +02:00
James Cole
dfa6bdbcb8 Fixed menu for mobile screens [skip ci] 2015-05-25 07:53:13 +02:00
James Cole
fb2481ebaa Add some GA events. 2015-05-25 07:26:19 +02:00
James Cole
4874c116cf Add GA to 503 page. [skip ci] 2015-05-25 07:23:35 +02:00
James Cole
e19c44efbd Some code cleanup. 2015-05-25 07:14:04 +02:00
James Cole
4b687b9bdc Clean up config 2015-05-25 07:03:26 +02:00
James Cole
6af79ef601 Fixed tests 2015-05-24 23:08:55 +02:00
James Cole
352b996ad2 Cleanup some code. 2015-05-24 22:59:48 +02:00
James Cole
4a93bb35f8 Cleanup budget view. 2015-05-24 22:54:59 +02:00
James Cole
8e1f493daf Another build routine. 2015-05-24 21:45:10 +02:00
James Cole
59ee153375 Fixed test. 2015-05-24 21:11:37 +02:00
James Cole
60f7f1fc16 New build routine. 2015-05-24 21:07:22 +02:00
James Cole
b7433683d8 Cleanup cleanup [skip ci] 2015-05-24 20:57:27 +02:00
James Cole
42799b9273 Some JS cleanup. 2015-05-24 20:48:31 +02:00
James Cole
860a0f790e Update js [skip ci] 2015-05-24 20:41:14 +02:00
James Cole
8daccbfbb4 Add JSHint stuff. [skip ci] 2015-05-24 18:22:41 +02:00
James Cole
285b77dcb7 Merge branch 'release/3.4.0.10' into develop 2015-05-24 15:56:05 +02:00
James Cole
6e48827d3f Merge branch 'release/3.4.0.10' 2015-05-24 15:56:04 +02:00
James Cole
f0c20cc706 New release. 2015-05-24 15:55:59 +02:00
James Cole
8916c0a3de Clean code [skip ci] 2015-05-24 15:18:19 +02:00
James Cole
7193a77840 Some translations and cleanup [skip ci] 2015-05-24 15:13:07 +02:00
James Cole
61930b5b51 Code cleanup [skip ci] 2015-05-24 15:03:45 +02:00
James Cole
11a494cacf Remove some middleware, fix cleanup [skip ci] 2015-05-24 12:53:47 +02:00
James Cole
17f9bf0339 Merge branch 'release/3.4.0.9' into develop 2015-05-24 11:53:44 +02:00
James Cole
3d9755ca8c Merge branch 'release/3.4.0.9' 2015-05-24 11:53:43 +02:00
James Cole
b5cf2d03e6 New version. 2015-05-24 11:53:34 +02:00
James Cole
e3b35b8f35 Add code climate file [skip ci] 2015-05-24 11:46:41 +02:00
James Cole
1c1fe672bd Some code cleanup [skip ci] 2015-05-24 11:41:52 +02:00
James Cole
6c71f68ed8 Should cover models. 2015-05-24 11:13:46 +02:00
James Cole
8f2f912cdf New (empty) tests for models. 2015-05-24 10:01:00 +02:00
James Cole
bf6ea16acb Fixed test. 2015-05-24 09:29:44 +02:00
James Cole
288546c2b9 Fixed some math. 2015-05-24 08:00:40 +02:00
James Cole
724db6c34c Built some new tests 2015-05-24 07:43:48 +02:00
James Cole
067c451c1d Fixed tests 2015-05-23 21:41:04 +02:00
James Cole
11e3696191 Cleanup tests. 2015-05-23 21:23:51 +02:00
James Cole
41e20664de Fixed coverage. 2015-05-23 21:18:20 +02:00
James Cole
d8de90d6f3 Ignore constructors. 2015-05-23 20:49:57 +02:00
James Cole
b01e8299d3 Fixed tests 2015-05-23 20:47:31 +02:00
James Cole
1ec11e3e2e Compartmentalised all tests. 2015-05-23 19:41:54 +02:00
James Cole
422f429725 Experimental count thing. 2015-05-23 17:38:16 +02:00
James Cole
5c55fa5fbb Remove encrypted amounts because it stinks. 2015-05-23 17:33:04 +02:00
James Cole
80d845fdf2 Save but don't use. 2015-05-23 17:18:23 +02:00
James Cole
601fe68346 Don't multiply transactions. 2015-05-23 17:14:36 +02:00
James Cole
9e050fb059 Updated some tests. 2015-05-23 17:11:16 +02:00
James Cole
99d4adf5e6 Translations [skip ci] 2015-05-23 15:57:38 +02:00
James Cole
85f8d1e8e9 Math is hard [skip ci] 2015-05-23 15:45:01 +02:00
James Cole
8334d3d99f Translation error [skip ci] 2015-05-23 15:43:48 +02:00
James Cole
cff08d19eb Slowly move away from using the raw 'transactions.amount' field. 2015-05-23 15:42:19 +02:00
James Cole
2d86390bc1 Experimental query.Code cleanup [skip ci] 2015-05-23 09:11:59 +02:00
James Cole
7a20835571 Code cleanup [skip ci] 2015-05-23 09:09:25 +02:00
James Cole
ff3c9676b5 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 09:05:08 +02:00
James Cole
055f97dab1 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 09:03:52 +02:00
James Cole
8a867e71a1 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 09:02:27 +02:00
James Cole
b8275b4734 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 09:01:38 +02:00
James Cole
36b951b146 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 09:01:07 +02:00
James Cole
c5a5f17643 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 09:00:11 +02:00
James Cole
16b909c4df Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 08:59:23 +02:00
James Cole
92b7648e03 Encrypt more stuff in the cleanup routine [skip ci] 2015-05-23 08:58:21 +02:00
James Cole
ca46ebe3b2 Encrypt bill amounts [skip ci] 2015-05-23 08:57:02 +02:00
James Cole
676e48254a Whoops [skip ci] 2015-05-23 08:55:16 +02:00
James Cole
b15b55227d Add another cleanup routine. [skip ci] 2015-05-23 08:54:25 +02:00
James Cole
3c3b723913 Some code cleanup [skip ci] 2015-05-23 08:51:24 +02:00
James Cole
f05002c729 Updated models for encryption. 2015-05-23 08:46:46 +02:00
James Cole
1c2cbd5b40 New stuff for encrypted amounts. 2015-05-23 07:47:36 +02:00
James Cole
54c6ca9f45 Expanded some tests. 2015-05-22 20:25:12 +02:00
James Cole
c10efbb170 Also encrypt meta data for reminders. 2015-05-22 19:19:18 +02:00
James Cole
a496ad5814 Simple routine to encrypt entries which were not encrypted yet. 2015-05-22 19:18:00 +02:00
James Cole
50cf7f6a3b Merge branch 'release/3.4.0.8' 2015-05-22 18:55:13 +02:00
James Cole
f946f10afd Merge branch 'release/3.4.0.8' into develop 2015-05-22 18:55:13 +02:00
James Cole
eecb4db34c Built chart tests. 2015-05-22 18:31:57 +02:00
James Cole
1f865d3ea4 Improved coverage. 2015-05-22 15:05:32 +02:00
James Cole
623bb4b350 New tests. 2015-05-22 10:17:20 +02:00
James Cole
dc8ad673a6 New test to cover some reminder stuff. 2015-05-22 08:52:30 +02:00
James Cole
4914ad821e Fixed coverage for transaction controller. 2015-05-22 08:03:34 +02:00
James Cole
f099cbadc3 Version increment. 2015-05-22 07:16:36 +02:00
James Cole
42cda384c8 Fix help routes 2015-05-22 07:15:40 +02:00
James Cole
23c91b9990 Some translations, playing around with popups. [skip ci] 2015-05-21 23:05:31 +02:00
James Cole
ff0379182e Sort chart [skip ci] 2015-05-21 18:57:14 +02:00
James Cole
e08a23948f Fixed chart. [skip ci] 2015-05-21 18:50:23 +02:00
James Cole
bd56de6d36 Fix other translations [skip ci] 2015-05-21 17:47:10 +02:00
James Cole
42970aea80 Fix some translations. 2015-05-21 17:45:01 +02:00
James Cole
003a05ee8d Fixed the category chart. 2015-05-21 17:27:48 +02:00
James Cole
ffb11b01a6 Some new translations. 2015-05-21 07:44:44 +02:00
James Cole
e426f5d5da Some new translations. 2015-05-21 07:30:38 +02:00
James Cole
6989f61e1b Extra translations [skip ci] 2015-05-20 20:10:01 +02:00
James Cole
0e6677ccb3 Remove cash accounts from list [skip ci] 2015-05-20 20:04:27 +02:00
James Cole
8f104d555a Added newlines to files. 2015-05-20 19:56:14 +02:00
James Cole
b1d3158db1 Code cleanup. 2015-05-20 19:55:53 +02:00
James Cole
7645005d5a Return of account id. 2015-05-20 18:18:05 +02:00
James Cole
411f77fd29 Fixed some other displays of money 2015-05-20 18:09:44 +02:00
James Cole
568ab26db1 Spell check [skip ci] 2015-05-20 17:06:47 +02:00
James Cole
29652108f0 Fixed tests. 2015-05-20 17:04:53 +02:00
James Cole
f07e4dc711 Fix sort. [skip ci] 2015-05-20 07:21:40 +02:00
James Cole
8a2ac457c2 Name fix [skip ci] 2015-05-20 07:21:01 +02:00
James Cole
9e54eecfaa Fixed some views. 2015-05-20 07:20:02 +02:00
James Cole
95ef691077 Fixed some more reports and charts. [skip ci] 2015-05-20 07:07:46 +02:00
James Cole
7a0ad5a587 Fixed a chart [skip ci] 2015-05-20 06:50:24 +02:00
James Cole
42b49d0e4b Added some correcting methods. [skip ci] 2015-05-20 06:50:15 +02:00
James Cole
9217c2f003 Corrected some charts [skip ci] 2015-05-20 06:49:51 +02:00
James Cole
fbdf66998d Added a forgotten chart, corrected some others. [skip ci] 2015-05-20 06:49:22 +02:00
James Cole
deda9d3c54 Add corrected expense routes [skip ci] 2015-05-20 06:49:03 +02:00
James Cole
a5d78f20ae Add corrected income and expense methods [skip ci] 2015-05-20 06:48:52 +02:00
James Cole
5ed09e3f38 Call the corrected spent function [skip ci] 2015-05-20 06:47:53 +02:00
James Cole
3e9774cd66 Merge branch 'release/3.4.0.7' 2015-05-18 18:23:07 +02:00
James Cole
54387c8fdf Merge branch 'release/3.4.0.7' into develop 2015-05-18 18:23:07 +02:00
James Cole
7eec949a13 Push new release. 2015-05-18 18:23:01 +02:00
James Cole
4113c4ff40 Fixed the tests. 2015-05-18 17:57:44 +02:00
James Cole
1bf0968bfe Show correct icon. [skip ci] 2015-05-18 17:05:22 +02:00
James Cole
374b90fb00 Show correct amount [skip ci] 2015-05-18 17:04:10 +02:00
James Cole
064e60e9d5 Show tag amount better [skip ci] 2015-05-18 17:02:18 +02:00
James Cole
b637455970 New translations [skip ci] 2015-05-18 16:59:01 +02:00
James Cole
68158937d1 Fixed translation [skip ci] 2015-05-18 06:56:59 +02:00
James Cole
adb1356b7a Small bug fix in display of income vs. expenses [skip ci] 2015-05-18 06:55:36 +02:00
James Cole
d880ccb8e0 Small bug fix in display of income vs. expenses [skip ci] 2015-05-18 06:54:46 +02:00
James Cole
050fb1d1ef Some translations [skip ci] 2015-05-17 18:06:00 +02:00
James Cole
6580752bde Now includes chart! [skip ci] 2015-05-17 18:03:16 +02:00
James Cole
c9df265c9b Included bills in month report. [skip ci] 2015-05-17 17:54:13 +02:00
James Cole
098e5bc162 Small translation fix [skip ci] 2015-05-17 17:27:56 +02:00
James Cole
4b2dcc74d4 Expanded the amount thing. 2015-05-17 16:12:00 +02:00
James Cole
a9254c5c9a Some new translations, better tag view [skip ci] 2015-05-17 15:55:24 +02:00
James Cole
7ce57e6ccb Fix a view, fix tag format. 2015-05-17 15:24:30 +02:00
James Cole
0fcb32a66f Fix update error. 2015-05-17 15:17:06 +02:00
James Cole
9946535f01 Some new bread crumbs [skip ci] 2015-05-17 15:12:45 +02:00
James Cole
2b17396d6b Fix some translations. 2015-05-17 13:44:58 +02:00
James Cole
b01d5bc237 Translation fixes [skip ci] 2015-05-17 12:53:32 +02:00
James Cole
b123860304 More stuff. 2015-05-17 12:49:09 +02:00
James Cole
033f5b67db Code cleanup 2015-05-17 11:28:58 +02:00
James Cole
6280448dfb Fixed more tests. 2015-05-17 10:47:12 +02:00
James Cole
01cd3333e4 Fixing tests. 2015-05-17 10:36:11 +02:00
James Cole
63050907b9 Code cleanup. 2015-05-17 10:30:18 +02:00
James Cole
beedf7d780 Cleaning up 2015-05-17 10:10:58 +02:00
James Cole
6b8194261f Clean up and simplify code. 2015-05-17 10:01:47 +02:00
James Cole
dbb1c4d534 Fixed some reports. 2015-05-17 09:35:49 +02:00
James Cole
e6263f9ff5 Some cleaning up 2015-05-17 09:18:44 +02:00
James Cole
6ca119c4db Minor changes [skip ci] 2015-05-17 09:04:55 +02:00
James Cole
c483a1ab3a Ignore simple classes. 2015-05-16 19:08:54 +02:00
James Cole
2e7edd033c Some expanded things. 2015-05-16 16:47:52 +02:00
James Cole
c576902501 Fixed tests. 2015-05-16 16:04:51 +02:00
James Cole
66c2951594 Cleanup 2015-05-16 15:52:09 +02:00
James Cole
b812881cdb More hip report stuff. 2015-05-16 15:43:58 +02:00
James Cole
cdeac2c6db Should simplify reports. 2015-05-16 14:51:23 +02:00
James Cole
bca2ddd529 Budget report thing. 2015-05-16 14:14:22 +02:00
James Cole
e7285c6499 Some overhauls. 2015-05-16 13:53:08 +02:00
James Cole
bdff275672 Simplified report code. 2015-05-16 13:06:38 +02:00
James Cole
bec58a1ee6 Experimental test coverage. 2015-05-16 10:34:38 +02:00
James Cole
f64616748c Expenses only [skip ci] 2015-05-16 10:18:32 +02:00
James Cole
512ce15973 Small tweaks in charts. 2015-05-16 10:13:41 +02:00
James Cole
ed8b301574 Routes and JS cleanup. 2015-05-16 10:05:22 +02:00
James Cole
d22a6c019c Fixed lots of chart references. 2015-05-16 09:57:31 +02:00
James Cole
a0cb1b9d9e Clean up and split chart controllers 2015-05-16 09:41:14 +02:00
James Cole
a5294c62ea Renamed a method. 2015-05-16 09:26:54 +02:00
James Cole
e155d3311c Fixed tests 2015-05-16 09:25:14 +02:00
James Cole
0a372b0daf Cleanup tests 2015-05-16 09:16:32 +02:00
James Cole
69143399d1 Moved some stuff around. 2015-05-16 09:09:52 +02:00
James Cole
3270d3bf96 Cleanup. 2015-05-16 08:14:26 +02:00
James Cole
3896a66122 Fixed tests. 2015-05-16 08:09:15 +02:00
James Cole
b94781aef1 Some optimisations. 2015-05-16 08:05:04 +02:00
James Cole
bed1adc367 Fixed budget. 2015-05-16 07:56:15 +02:00
James Cole
ae54497efa Differ between shared and normal transactions (not build yet). 2015-05-16 07:49:02 +02:00
James Cole
06b747c221 Some cleanup and translations. 2015-05-16 07:28:58 +02:00
James Cole
f159beee0d Fixed preferences tests. 2015-05-15 23:24:55 +02:00
James Cole
49d7dea086 Fixed some coverage. 2015-05-15 23:02:42 +02:00
James Cole
3e65733dc5 Small fix in report view [skip ci] 2015-05-15 22:12:31 +02:00
James Cole
cc375d58bb Fixed tests. 2015-05-15 22:06:52 +02:00
James Cole
911c7c662a Expanded reports. 2015-05-15 22:00:00 +02:00
James Cole
aae003be33 Some more cleaning up and fixing 2015-05-15 21:01:24 +02:00
James Cole
aede03d8b2 Some more layout changes. 2015-05-15 20:43:50 +02:00
James Cole
f0f5ada7de More changes to reports. 2015-05-15 20:38:39 +02:00
James Cole
58365121a3 Fixed tests. 2015-05-15 20:15:58 +02:00
James Cole
d5a154d2e6 Cleaned up reports and associated views. 2015-05-15 20:07:51 +02:00
James Cole
b20f369aef Some new tests. 2015-05-15 18:39:59 +02:00
James Cole
abb8aa0b29 Merge branch 'feature/translations' into develop 2015-05-15 18:38:26 +02:00
James Cole
5368a0f1d7 Some new translations. 2015-05-14 19:44:20 +02:00
James Cole
d3897eece7 This should fix the tests on the translations branch. 2015-05-14 18:15:31 +02:00
James Cole
a82b829da9 More translations. 2015-05-14 18:00:56 +02:00
James Cole
9f5058e81a Some new translations. 2015-05-14 17:52:50 +02:00
James Cole
5b19263720 Some more [skip ci] 2015-05-14 16:43:12 +02:00
James Cole
9d5a0db0d9 [skip ci] 2015-05-14 16:36:08 +02:00
James Cole
4bd8a7014f Count things [skip ci] 2015-05-14 16:35:41 +02:00
James Cole
353e96d951 Better (and translated) delete forms. [skip ci] 2015-05-14 16:32:35 +02:00
James Cole
149a6f92b0 Translations [skip ci] 2015-05-14 15:56:23 +02:00
James Cole
d66426c137 Nieuw vertalingen [skip ci] 2015-05-14 15:53:56 +02:00
James Cole
4fc9966392 Chart translations [skip ci] 2015-05-14 13:43:58 +02:00
James Cole
417766f0db Various date localisation. [skip ci] 2015-05-14 13:41:21 +02:00
James Cole
de9ac97887 Also english. [skip ci] 2015-05-14 13:19:26 +02:00
James Cole
6be42f112a Charts and titles in Dutch. [skip ci] 2015-05-14 13:17:53 +02:00
James Cole
3895ae63c7 Some translations for lists [skip ci] 2015-05-14 13:00:43 +02:00
James Cole
607d416d54 Better translation for 'balance' [skip ci] 2015-05-14 12:11:56 +02:00
James Cole
038693dc86 More index translations [skip ci] 2015-05-14 12:10:42 +02:00
James Cole
cc9be13544 Added a bread crumb [skip ci] 2015-05-14 11:50:48 +02:00
James Cole
9c1474087f Forgot one [skip ci] 2015-05-14 11:50:04 +02:00
James Cole
831de2bcf4 New menu translations [skip ci] 2015-05-14 11:48:59 +02:00
James Cole
eb687333bb Small edits to buttons and others. [skip ci] 2015-05-14 11:31:54 +02:00
James Cole
5cc7966d54 Some new form things. [skip ci] 2015-05-14 11:25:43 +02:00
James Cole
d1a34e7a6f Breadcrumbs translated to English. [skip ci] 2015-05-14 11:22:20 +02:00
James Cole
d63d791717 Translated all bread crumbs to Dutch. [skip ci] 2015-05-14 11:17:56 +02:00
James Cole
015570c741 Small translations as a basic start [skip ci] 2015-05-14 10:26:15 +02:00
James Cole
8400ebc9c6 Added a language test, added Dutch basic file. [skip ci] 2015-05-14 10:03:57 +02:00
James Cole
9f99e7c0af Edit and set language [skip ci] 2015-05-14 09:59:30 +02:00
James Cole
392c1fc399 Add language selector to preferences [skip ci] 2015-05-14 09:56:41 +02:00
James Cole
d3cea7a89c Add new supported languages [skip ci] 2015-05-14 09:52:58 +02:00
James Cole
1dcf7407e6 Cleanup [skip ci] 2015-05-14 09:51:54 +02:00
James Cole
d543c033a3 Small fixes to translations. 2015-05-14 09:50:07 +02:00
James Cole
aaa186be5e Merge branch 'release/3.4.0.6' 2015-05-14 09:21:23 +02:00
James Cole
2054b5b3dd Merge branch 'release/3.4.0.6' into develop 2015-05-14 09:21:23 +02:00
James Cole
98ae5b0ca0 New read me. 2015-05-14 09:21:12 +02:00
James Cole
36c8171d0f Clean up and tests. 2015-05-14 09:01:10 +02:00
James Cole
3603eb94cc Different budget query [skip ci] 2015-05-14 08:08:25 +02:00
James Cole
0e068d4ccf Fixed some tests. 2015-05-13 21:37:11 +02:00
James Cole
199f348ff4 Smaller mobile pages. 2015-05-13 21:32:33 +02:00
James Cole
b22655fb7c Fix helper 2015-05-13 21:32:27 +02:00
James Cole
06cc9618ba Some new tests 2015-05-13 21:32:21 +02:00
James Cole
b9019c8c7f Smaller screens update [skip ci] 2015-05-13 06:34:17 +02:00
James Cole
77e133e67c Some cleaning up for mobile screens [skip ci] 2015-05-13 06:31:32 +02:00
James Cole
571e7df807 Some tiny optimisations. 2015-05-12 20:51:03 +02:00
James Cole
22f4d2979a Added some more ignores, edited some middleware. 2015-05-11 22:12:53 +02:00
James Cole
e46e366694 Added some tests to cover an event. 2015-05-11 21:45:31 +02:00
James Cole
9ca79f767c Merge branch 'release/3.4.0.5' into develop 2015-05-10 19:18:57 +02:00
277 changed files with 12539 additions and 6407 deletions

25
.codeclimate.yml Normal file
View 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/*"

View File

@@ -1,3 +1,3 @@
src_dir: .
coverage_clover: storage/coverage/clover.xml
json_path: storage/coverage/coveralls-upload.json
coverage_clover: build/logs/clover.xml
json_path: build/logs/coveralls-upload.json

View File

@@ -16,4 +16,6 @@ EMAIL_DRIVER=smtp
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=
EMAIL_PRETEND=false
EMAIL_PRETEND=false
RUNCLEANUP=true
SITE_OWNER=mail@example.com

22
.jshintrc Normal file
View 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"
]
}

5
.scrutinizer.yml Normal file
View File

@@ -0,0 +1,5 @@
# .scrutinizer.yml
tools:
external_code_coverage:
timeout: 1800 # Timeout in seconds.
runs: 2

View File

@@ -6,10 +6,6 @@ php:
- 5.5
- 5.6
addons:
code_climate:
repo_token: 26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61
install:
- composer update
- php artisan env
@@ -20,3 +16,7 @@ script:
after_script:
- php vendor/bin/coveralls
- CODECLIMATE_REPO_TOKEN=26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61 ./vendor/bin/test-reporter --stdout > codeclimate.json
- "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports"
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml

View File

@@ -1,23 +1,21 @@
# Firefly III
#### v3.4.0.5
# Firefly III (v3.4.3)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
[![Build Status](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/build.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/build-status/master)
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii)
[![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102)
[![Code Climate](https://codeclimate.com/github/JC5/firefly-iii/badges/gpa.svg)](https://codeclimate.com/github/JC5/firefly-iii)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=master)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
![GA](https://ga-beacon.appspot.com/UA-58172398-6/firefly-iii/readme)
## About
"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.
Firefly is a system you'll have install yourself on webhosting of your choosing.
_Firefly is a system you'll have install yourself on webhosting of your choosing._
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 get a better job.
There are tons of ways to save and earn money.
make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase
their current cashflow. There are tons of ways to save and earn money.
Firefly works on the principle that if you know where you're money is going, you can stop it from going there.
To get to know Firefly, and to see if it fits you, check out these resources:
@@ -28,24 +26,15 @@ To get to know Firefly, and to see if it fits you, check out these resources:
and the philosophy behind it.
### About the name (if you care)
#### About the name (if 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.
## 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.
## 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](https://en.wikipedia.org/wiki/Financial_transaction). This allows you full financial management;
- You can manage different types of accounts
- 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
@@ -63,8 +52,8 @@ 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;
- Lots of charts because we all love them;
- Financial reporting showing you how well you are doing.
## Screenshots
@@ -84,6 +73,16 @@ _Please note that everything in these screenshots is fictional and may not be re
![Piggy banks](https://i.nder.be/hkud0h53)
## 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.
## Current state
Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. One of the things on the todo-list
@@ -92,3 +91,9 @@ is adding translations.
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&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted).
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102)
[![Code Climate](https://codeclimate.com/github/JC5/firefly-iii/badges/gpa.svg)](https://codeclimate.com/github/JC5/firefly-iii)
[![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
![GA](https://ga-beacon.appspot.com/UA-58172398-6/firefly-iii/readme)

View File

@@ -26,6 +26,8 @@ class Kernel extends ConsoleKernel
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return void
*/
protected function schedule(Schedule $schedule)

View File

@@ -2,6 +2,7 @@
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Class Handler
@@ -27,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);
@@ -43,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
*

View File

@@ -6,7 +6,6 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class ConnectJournalToPiggyBank
@@ -19,6 +18,8 @@ class ConnectJournalToPiggyBank
/**
* Create the event handler.
*
* @codeCoverageIgnore
*
*/
public function __construct()
{
@@ -28,54 +29,36 @@ class ConnectJournalToPiggyBank
/**
* Handle the event when journal is saved.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @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;
return false;
}
Log::debug('Found rep! ' . $repetition->id);
/*
* Add amount when
*/
$amount = $journal->amount;
/** @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);
$amount = $transaction->amount * -1;
}
}
}
@@ -83,14 +66,9 @@ class ConnectJournalToPiggyBank
$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;
}

View File

@@ -1,36 +0,0 @@
<?php namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\JournalDeleted;
/**
* Class JournalDeletedHandler
*
* @codeCoverageIgnore
* @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)
{
//
}
}

View File

@@ -7,6 +7,7 @@ use Log;
/**
* Class RescanJournal
*
* @codeCoverageIgnore
* @package FireflyIII\Handlers\Events
*/
class RescanJournal

View File

@@ -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,13 +40,17 @@ 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
$diff = $amount - $event->amount; // update current repetition
$repetition->currentamount += $diff;
$repetition->save();

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -0,0 +1,171 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
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;
/** @var LimitRepetition */
protected $repetition;
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 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 '';
}
/**
* @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;
}
/**
* 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 = $this->getRepetition() ? $this->getRepetition()->amount : 0;
/** @var BalanceEntry $balanceEntry */
foreach ($this->getBalanceEntries() as $balanceEntry) {
$start += $balanceEntry->getSpent();
}
return $start;
}
/**
* @return LimitRepetition
*/
public function getRepetition()
{
return $this->repetition;
}
/**
* @param LimitRepetition $repetition
*/
public function setRepetition($repetition)
{
$this->repetition = $repetition;
}
/**
* @return Collection
*/
public function getBalanceEntries()
{
return $this->balanceEntries;
}
/**
* @param Collection $balanceEntries
*/
public function setBalanceEntries($balanceEntries)
{
$this->balanceEntries = $balanceEntries;
}
/**
* If the BalanceEntries for a BalanceLine have a "left" value, the amount
* of money left in the entire BalanceLine is returned here:
*
* @return float
*/
public function sumOfLeft()
{
$sum = 0.0;
/** @var BalanceEntry $balanceEntry */
foreach ($this->getBalanceEntries() as $balanceEntry) {
$sum += $balanceEntry->getLeft();
}
return $sum;
}
}

View 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()
{
$this->bills->sortBy(
function(BillLine $bill) {
$active = intval($bill->getBill()->active) == 0 ? 1 : 0;
$name = $bill->getBill()->name;
return $active . $name;
}
);
return $this->bills;
}
}

View 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 float */
protected $amount;
/** @var BillModel */
protected $bill;
/** @var bool */
protected $hit;
/** @var float */
protected $max;
/** @var float */
protected $min;
/**
* @return float
*/
public function getAmount()
{
return $this->amount;
}
/**
* @param float $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 float
*/
public function getMax()
{
return $this->max;
}
/**
* @param float $max
*/
public function setMax($max)
{
$this->max = $max;
}
/**
* @return float
*/
public function getMin()
{
return $this->min;
}
/**
* @param float $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;
}
}

View 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));
}
}

View 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;
}
}

View File

@@ -0,0 +1,76 @@
<?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)
{
if ($category->spent > 0) {
$this->categories->push($category);
}
}
/**
* @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()
{
$this->categories->sortByDesc(
function(CategoryModel $category) {
return $category->spent;
}
);
return $this->categories;
}
/**
* @return string
*/
public function getTotal()
{
return strval(round($this->total, 2));
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace FireflyIII\Helpers\Collection;
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)
{
$accountId = $entry->account_id;
if (!$this->expenses->has($accountId)) {
$newObject = new stdClass;
$newObject->amount = strval(round($entry->amount, 2));
$newObject->name = $entry->name;
$newObject->count = 1;
$newObject->id = $accountId;
$this->expenses->put($accountId, $newObject);
} else {
bcscale(2);
$existing = $this->expenses->get($accountId);
$existing->amount = bcadd($existing->amount, $entry->amount);
$existing->count++;
$this->expenses->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 getExpenses()
{
$this->expenses->sortByDesc(
function(stdClass $object) {
return $object->amount;
}
);
return $this->expenses;
}
/**
* @return string
*/
public function getTotal()
{
return strval(round($this->total, 2));
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace FireflyIII\Helpers\Collection;
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->amount, 2));
$newObject->name = $entry->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->amount);
$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()
{
$this->incomes->sortByDesc(
function(stdClass $object) {
return $object->amount;
}
);
return $this->incomes;
}
/**
* @return string
*/
public function getTotal()
{
return strval(round($this->total, 2));
}
}

View File

@@ -17,6 +17,8 @@ class Help implements HelpInterface
{
/**
* @codeCoverageIgnore
*
* @param $key
*
* @return string
@@ -27,13 +29,15 @@ 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';
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md';
$content = [
'text' => '<p>There is no help for this route!</p>',
'title' => $route,
@@ -54,6 +58,8 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return bool
@@ -64,6 +70,8 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
* @param array $content
*
@@ -76,6 +84,8 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return bool

View File

@@ -5,9 +5,11 @@ namespace FireflyIII\Helpers\Reminders;
use Amount;
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use Navigation;
use Preferences;
/**
* Class ReminderHelper
@@ -33,7 +35,7 @@ class ReminderHelper implements ReminderHelperInterface
$ranges = $this->getReminderRanges($piggyBank, $start);
$currentRep = $piggyBank->currentRelevantRep();
$left = $piggyBank->targetamount - $currentRep->currentamount;
$perReminder = $left / count($ranges);
$perReminder = count($ranges) == 0 ? $left : $left / count($ranges);
} else {
$perReminder = null;
$ranges = [];
@@ -46,8 +48,6 @@ class ReminderHelper implements ReminderHelperInterface
'leftToSave' => $left,
];
// create one:
$reminder = new Reminder;
$reminder->user()->associate(Auth::user());
$reminder->startdate = $start;
@@ -65,6 +65,30 @@ class ReminderHelper implements ReminderHelperInterface
}
}
/**
* Create all reminders for a piggy bank for a given date.
*
* @param PiggyBank $piggyBank
*
* @param Carbon $date
*
* @return mixed
*/
public function createReminders(PiggyBank $piggyBank, Carbon $date)
{
$ranges = $this->getReminderRanges($piggyBank);
foreach ($ranges as $range) {
if ($date < $range['end'] && $date > $range['start']) {
// create a reminder here!
$this->createReminder($piggyBank, $range['start'], $range['end']);
// stop looping, we're done.
break;
}
}
}
/**
* 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
@@ -132,14 +156,21 @@ class ReminderHelper implements ReminderHelperInterface
$piggyBank = $reminder->remindersable;
if (is_null($piggyBank)) {
return 'Piggy bank no longer exists.';
return trans('firefly.piggy_bank_not_exists');
}
if (is_null($piggyBank->targetdate)) {
return 'Add money to this piggy bank to reach your target of ' . Amount::format($piggyBank->targetamount);
return trans('firefly.add_any_amount_to_piggy', ['amount' => Amount::format($piggyBank->targetamount)]);
}
return 'Add ' . Amount::format($reminder->metadata->perReminder) . ' to fill this piggy bank on ' . $piggyBank->targetdate->format('jS F Y');
$lang = Preferences::get('language', 'en')->data;
return trans(
'firefly.add_set_amount_to_piggy',
[
'amount' => Amount::format($reminder->metadata->perReminder),
'date' => $piggyBank->targetdate->formatLocalized(Config::get('firefly.monthAndDay.' . $lang))
]
);
}
}

View File

@@ -49,4 +49,15 @@ interface ReminderHelperInterface
* @return Reminder
*/
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end);
/**
* Create all reminders for a piggy bank for a given date.
*
* @param PiggyBank $piggyBank
*
* @param Carbon $date
*
* @return mixed
*/
public function createReminders(PiggyBank $piggyBank, Carbon $date);
}

View File

@@ -3,12 +3,23 @@
namespace FireflyIII\Helpers\Report;
use App;
use Auth;
use Carbon\Carbon;
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 Illuminate\Support\Collection;
use Steam;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
/**
* Class ReportHelper
@@ -18,66 +29,349 @@ 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 generates a full report for the given period on all
* the users asset and cash accounts.
*
* @param Carbon $date
* @param Carbon $end
* @param $shared
*
* @return AccountCollection
*/
public function getAccountReport(Carbon $date, Carbon $end, $shared)
{
$accounts = $this->query->getAllAccounts($date, $end, $shared);
$start = 0;
$end = 0;
$diff = 0;
// remove cash account, if any:
$accounts = $accounts->filter(
function(Account $account) {
if ($account->accountType->type != 'Cash account') {
return $account;
}
return null;
}
);
// summarize:
foreach ($accounts as $account) {
$start += $account->startBalance;
$end += $account->endBalance;
$diff += ($account->endBalance - $account->startBalance);
}
$object = new AccountCollection;
$object->setStart($start);
$object->setEnd($end);
$object->setDifference($diff);
$object->setAccounts($accounts);
return $object;
}
/**
*
* The balance report contains a Balance object which in turn contains:
*
* A BalanceHeader object which contains all relevant user asset accounts for the report.
*
* A number of BalanceLine objects, which hold:
* - A budget
* - A number of BalanceEntry objects.
*
* The BalanceEntry object holds:
* - The same budget (again)
* - A user asset account as mentioned in the BalanceHeader
* - The amount of money spent on the budget by the user asset account
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Balance
*/
public function getBalanceReport(Carbon $start, Carbon $end, $shared)
{
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
$balance = new Balance;
// build a balance header:
$header = new BalanceHeader;
$accounts = $this->query->getAllAccounts($start, $end, $shared);
$budgets = $repository->getBudgets();
foreach ($accounts as $account) {
$header->addAccount($account);
}
/** @var BudgetModel $budget */
foreach ($budgets as $budget) {
$line = new BalanceLine;
$line->setBudget($budget);
// get budget amount for current period:
$rep = $repository->getCurrentRepetition($budget, $start);
$line->setRepetition($rep);
// loop accounts:
foreach ($accounts as $account) {
$balanceEntry = new BalanceEntry;
$balanceEntry->setAccount($account);
// get spent:
$spent = $this->query->spentInBudgetCorrected($account, $budget, $start, $end); // I think shared is irrelevant.
$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:
$empty = new BalanceLine;
$tags = new BalanceLine;
$diffLine = new BalanceLine;
$tags->setRole(BalanceLine::ROLE_TAGROLE);
$diffLine->setRole(BalanceLine::ROLE_DIFFROLE);
foreach ($accounts as $account) {
$spent = $this->query->spentNoBudget($account, $start, $end);
$left = $tagRepository->coveredByBalancingActs($account, $start, $end);
$diff = $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);
}
$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.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return BillCollection
*/
public function getBillReport(Carbon $start, Carbon $end, $shared)
{
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
$bills = $repository->getBills();
$collection = new BillCollection;
/** @var Bill $bill */
foreach ($bills as $bill) {
$billLine = new BillLine;
$billLine->setBill($bill);
$billLine->setActive(intval($bill->active) == 1);
$billLine->setMin(floatval($bill->amount_min));
$billLine->setMax(floatval($bill->amount_max));
// is hit in period?
$set = $repository->getJournalsInRange($bill, $start, $end);
if ($set->count() == 0) {
$billLine->setHit(false);
} else {
$billLine->setHit(true);
$amount = 0;
foreach ($set as $entry) {
$amount += $entry->amount;
}
$billLine->setAmount($amount);
}
$collection->addBill($billLine);
}
return $collection;
}
/**
* This method gets some kind of list for a monthly overview.
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @param Carbon $date
* @param bool $showSharedReports
*
* @return Collection
* @return BudgetCollection
*/
public function getBudgetsForMonth(Carbon $date, $showSharedReports = false)
public function getBudgetReport(Carbon $start, Carbon $end, $shared)
{
/** @var \FireflyIII\Helpers\Report\ReportQueryInterface $query */
$query = App::make('FireflyIII\Helpers\Report\ReportQueryInterface');
$object = new BudgetCollection;
/** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$set = $repository->getBudgets();
$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']);
foreach ($set as $budget) {
$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';
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
// no repetition(s) for this budget:
if ($repetitions->count() == 0) {
$spent = $repository->spentInPeriodCorrected($budget, $start, $end, $shared);
$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 = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared);
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
$spent = $expenses > floatval($repetition->amount) ? 0 : $expenses;
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
$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);
}
// 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;
}
return $budgets;
// stuff outside of budgets:
$noBudget = $repository->getWithoutBudgetSum($start, $end);
$budgetLine = new BudgetLine;
$budgetLine->setOverspent($noBudget);
$object->addOverspent($noBudget);
$object->addBudgetLine($budgetLine);
return $object;
}
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return CategoryCollection
*/
public function getCategoryReport(Carbon $start, Carbon $end, $shared)
{
$object = new CategoryCollection;
/**
* GET CATEGORIES:
*/
/** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
$set = $repository->getCategories();
foreach ($set as $category) {
$spent = $repository->spentInPeriodCorrected($category, $start, $end, $shared);
$category->spent = $spent;
$object->addCategory($category);
$object->addTotal($spent);
}
return $object;
}
/**
* Get a full report on the users expenses during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Expense
*/
public function getExpenseReport($start, $end, $shared)
{
$object = new Expense;
$set = $this->query->expenseInPeriodCorrected($start, $end, $shared);
foreach ($set as $entry) {
$object->addToTotal($entry->amount);
$object->addOrCreateExpense($entry);
}
return $object;
}
/**
* Get a full report on the users incomes during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Income
*/
public function getIncomeReport($start, $end, $shared)
{
$object = new Income;
$set = $this->query->incomeInPeriodCorrected($start, $end, $shared);
foreach ($set as $entry) {
$object->addToTotal($entry->amount);
$object->addOrCreateIncome($entry);
}
return $object;
}
/**
@@ -87,13 +381,14 @@ 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'),
'formatted' => $start->formatLocalized('%B %Y'),
'month' => $start->month,
'year' => $year,
];
@@ -102,77 +397,4 @@ class ReportHelper implements ReportHelperInterface
return $months;
}
/**
* @param Carbon $date
*
* @return array
*/
public function listOfYears(Carbon $date)
{
$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);
return $years;
}
/**
* @param Carbon $date
* @param bool $showSharedReports
*
* @return array
*/
public function yearBalanceReport(Carbon $date, $showSharedReports = false)
{
$start = clone $date;
$end = clone $date;
$sharedAccounts = [];
if ($showSharedReports === false) {
$sharedCollection = Auth::user()->accounts()
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('account_meta.name', '=', 'accountRole')
->where('account_meta.data', '=', json_encode('sharedAsset'))
->get(['accounts.id']);
foreach ($sharedCollection as $account) {
$sharedAccounts[] = $account->id;
}
}
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*'])
->filter(
function (Account $account) use ($sharedAccounts) {
if (!in_array($account->id, $sharedAccounts)) {
return $account;
}
return null;
}
);
$report = [];
$start->startOfYear()->subDay();
$end->endOfYear();
foreach ($accounts as $account) {
$startBalance = Steam::balance($account, $start);
$endBalance = Steam::balance($account, $end);
$report[] = [
'start' => $startBalance,
'end' => $endBalance,
'hide' => ($startBalance == 0 && $endBalance == 0),
'account' => $account,
'shared' => $account->accountRole == 'sharedAsset'
];
}
return $report;
}
}

View File

@@ -3,7 +3,13 @@
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use FireflyIII\Helpers\Collection\Account as AccountCollection;
use FireflyIII\Helpers\Collection\Balance;
use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
use FireflyIII\Helpers\Collection\Category as CategoryCollection;
use FireflyIII\Helpers\Collection\Bill as BillCollection;
use FireflyIII\Helpers\Collection\Expense;
use FireflyIII\Helpers\Collection\Income;
/**
* Interface ReportHelperInterface
@@ -13,26 +19,78 @@ use Illuminate\Support\Collection;
interface ReportHelperInterface
{
/**
* This method generates a full report for the given period on all
* the users asset and cash accounts.
*
* @param Carbon $date
* @param Carbon $end
* @param boolean $shared
*
* @return AccountCollection
*/
public function getAccountReport(Carbon $date, Carbon $end, $shared);
/**
* This methods fails to take in account transfers FROM shared accounts.
* This method generates a full report for the given period on all
* the users bills and their payments.
*
* @param Carbon $start
* @param Carbon $end
* @param int $limit
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Collection
* @return BillCollection
*/
public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15);
public function getBillReport(Carbon $start, Carbon $end, $shared);
/**
* This method gets some kind of list for a monthly overview.
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @param Carbon $date
*
* @return Collection
* @return Balance
*/
public function getBudgetsForMonth(Carbon $date);
public function getBalanceReport(Carbon $start, Carbon $end, $shared);
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return BudgetCollection
*/
public function getBudgetReport(Carbon $start, Carbon $end, $shared);
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return CategoryCollection
*/
public function getCategoryReport(Carbon $start, Carbon $end, $shared);
/**
* Get a full report on the users expenses during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Expense
*/
public function getExpenseReport($start, $end, $shared);
/**
* Get a full report on the users incomes during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Income
*/
public function getIncomeReport($start, $end, $shared);
/**
* @param Carbon $date
@@ -41,18 +99,4 @@ interface ReportHelperInterface
*/
public function listOfMonths(Carbon $date);
/**
* @param Carbon $date
*
* @return array
*/
public function listOfYears(Carbon $date);
/**
* @param Carbon $date
* @param bool $showSharedReports
*
* @return array
*/
public function yearBalanceReport(Carbon $date, $showSharedReports = false);
}

View File

@@ -5,11 +5,10 @@ namespace FireflyIII\Helpers\Report;
use Auth;
use Carbon\Carbon;
use Crypt;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Steam;
@@ -21,101 +20,63 @@ use Steam;
*/
class ReportQuery implements ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
* See ReportQueryInterface::incomeInPeriodCorrected
*
* @param bool $showSharedReports
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*
*/
public function accountList($showSharedReports = false)
public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false)
{
$query = Auth::user()->accounts();
if ($showSharedReports === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
}
)->where(
function (Builder $query) {
$query->where('account_meta.data', '!=', '"sharedAsset"');
$query->orWhereNull('account_meta.data');
$query = $this->queryJournalsWithTransactions($start, $end);
if ($includeShared === false) {
$query->where(
function(Builder $query) {
$query->where(
function(Builder $q) { // only get withdrawals not from a shared account
$q->where('transaction_types.type', 'Withdrawal');
$q->where('acm_from.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function(Builder $q) { // and transfers from a shared account.
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_to.data', '=', '"sharedAsset"');
}
);
}
);
} else {
$query->where('transaction_types.type', 'Withdrawal'); // any withdrawal is fine.
}
$query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
->where('active', 1)
->orderBy('accounts.name', 'ASC');
$query->orderBy('transaction_journals.date');
return $query->get(['accounts.*']);
}
// get everything
$data = $query->get(
['transaction_journals.*', 'transaction_types.type', 'ac_to.name as name', 'ac_to.id as account_id', 'ac_to.encrypted as account_encrypted']
);
/**
* This method will get a list of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end)
{
$data->each(
function(TransactionJournal $journal) {
if (intval($journal->account_encrypted) == 1) {
$journal->name = Crypt::decrypt($journal->name);
}
}
);
$data = $data->filter(
function(TransactionJournal $journal) {
if ($journal->amount != 0) {
return $journal;
}
return null;
}
);
$set = TransactionJournal::
leftJoin('transaction_group_transaction_journal', 'transaction_group_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin(
'transaction_group_transaction_journal as otherFromGroup', function (JoinClause $join) {
$join->on('otherFromGroup.transaction_group_id', '=', 'transaction_group_transaction_journal.transaction_group_id')
->on('otherFromGroup.transaction_journal_id', '!=', 'transaction_journals.id');
}
)
->leftJoin('transaction_journals as otherJournals', 'otherJournals.id', '=', 'otherFromGroup.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'otherJournals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
}
)
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'otherJournals.id')
->before($end)->after($start)
->where('transaction_types.type', 'Withdrawal')
->where('transaction_journals.user_id', Auth::user()->id)
->whereNull('budget_transaction_journal.budget_id')->whereNull('transaction_journals.deleted_at')
->whereNull('otherJournals.deleted_at')
->where('transactions.account_id', $account->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->whereNotNull('transaction_group_transaction_journal.transaction_group_id')
->get(
[
'transaction_journals.*',
'transactions.amount as queryAmount'
]
);
return $set;
}
/**
* This method will get the sum of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end)
{
return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount'));
return $data;
}
/**
@@ -123,33 +84,33 @@ class ReportQuery implements ReportQueryInterface
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
* @param bool $includeShared
*
* @return Collection
*/
public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false)
public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false)
{
$query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')
->accountTypeIn(['Default account', 'Asset account', 'Cash account']);
if ($showSharedReports === false) {
->accountTypeIn(['Default account', 'Asset account', 'Cash account']);
if ($includeShared === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
'account_meta', function(JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->orderBy('accounts.name', 'ASC')
->where(
function (Builder $query) {
->orderBy('accounts.name', 'ASC')
->where(
function(Builder $query) {
$query->where('account_meta.data', '!=', '"sharedAsset"');
$query->orWhereNull('account_meta.data');
$query->where('account_meta.data', '!=', '"sharedAsset"');
$query->orWhereNull('account_meta.data');
}
);
}
);
}
$set = $query->get(['accounts.*']);
$set->each(
function (Account $account) use ($start, $end) {
function(Account $account) use ($start, $end) {
/**
* The balance for today always incorporates transactions
* made on today. So to get todays "start" balance, we sub one
@@ -167,67 +128,38 @@ class ReportQuery implements ReportQueryInterface
return $set;
}
/**
* Grabs a summary of all expenses grouped by budget, related to the account.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end)
{
$query = $this->queryJournalsNoBudget($account, $start, $end);
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `queryAmount`')]);
}
/**
* Get a list of transaction journals that have no budget, filtered for the specified account
* and the specified date range.
* This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results
* will simply list the transaction journals only. This should allow any follow up counting to be accurate with
* regards to tags.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end)
{
$query = $this->queryJournalsNoBudget($account, $start, $end);
return $query->get(['budgets.name', 'transactions.amount as queryAmount', 'transaction_journals.*']);
}
/**
* This method returns all "income" journals in a certain period, which are both transfers from a shared account
* and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
* @param bool $includeShared
*
* @return Collection
*/
public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false)
public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false)
{
$query = $this->queryJournalsWithTransactions($start, $end);
if ($showSharedReports === false) {
if ($includeShared === false) {
// only get deposits not to a shared account
// and transfers to a shared account.
$query->where(
function (Builder $query) {
function(Builder $query) {
$query->where(
function (Builder $q) {
function(Builder $q) {
$q->where('transaction_types.type', 'Deposit');
$q->where('acm_to.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function (Builder $q) {
function(Builder $q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_from.data', '=', '"sharedAsset"');
}
@@ -238,219 +170,26 @@ class ReportQuery implements ReportQueryInterface
// any deposit is fine.
$query->where('transaction_types.type', 'Deposit');
}
$query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date');
$query->orderBy('transaction_journals.date');
// get everything, decrypt and return
// get everything
$data = $query->get(
['transaction_journals.id',
'transaction_journals.description',
'transaction_journals.encrypted',
'transaction_types.type',
DB::Raw('SUM(`t_to`.`amount`) as `queryAmount`'),
'transaction_journals.date',
't_from.account_id as account_id',
'ac_from.name as name',
'ac_from.encrypted as account_encrypted'
]
['transaction_journals.*', 'transaction_types.type', 'ac_from.name as name', 'ac_from.id as account_id', 'ac_from.encrypted as account_encrypted']
);
$data->each(
function (Model $object) {
$object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
return $data;
}
/**
* Gets a list of expenses grouped by the budget they were filed under.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = Auth::user()->transactionjournals()
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id');
if ($showSharedReports === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)->where('account_meta.data', '!=', '"sharedAsset"');
}
$query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_types.type', 'Withdrawal')
->groupBy('budgets.id')
->orderBy('budgets.name', 'ASC');
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]);
}
/**
* Gets a list of categories and the expenses therein, grouped by the relevant category.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = Auth::user()->transactionjournals()
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id');
if ($showSharedReports === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)->where('account_meta.data', '!=', '"sharedAsset"');
}
$query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('queryAmount');
$data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `queryAmount`')]);
// decrypt data:
$data->each(
function (Model $object) {
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
return $data;
}
/**
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* So now it will include them!
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = $this->queryJournalsWithTransactions($start, $end);
if ($showSharedReports === false) {
// get all withdrawals not from a shared accounts
// and all transfers to a shared account
$query->where(
function (Builder $query) {
$query->where(
function (Builder $q) {
$q->where('transaction_types.type', 'Withdrawal');
$q->where('acm_from.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function (Builder $q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_to.data', '=', '"sharedAsset"');
}
);
function(TransactionJournal $journal) {
if (intval($journal->account_encrypted) == 1) {
$journal->name = Crypt::decrypt($journal->name);
}
);
} else {
// any withdrawal goes:
$query->where('transaction_types.type', 'Withdrawal');
}
$query->before($end)->after($start)
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('t_to.account_id')
->orderBy('queryAmount', 'DESC');
$data = $query->get(['t_to.account_id as id', 'ac_to.name as name', 'ac_to.encrypted', DB::Raw('SUM(t_to.amount) as `queryAmount`')]);
// decrypt
$data->each(
function (Model $object) {
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
return $data;
}
/**
* This method returns all deposits into asset accounts, grouped by the revenue account,
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = $this->queryJournalsWithTransactions($start, $end);
if ($showSharedReports === false) {
// show queries where transfer type is deposit, and its not to a shared account
// or where its a transfer and its from a shared account (both count as incomes)
$query->where(
function (Builder $query) {
$query->where(
function (Builder $q) {
$q->where('transaction_types.type', 'Deposit');
$q->where('acm_to.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function (Builder $q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_from.data', '=', '"sharedAsset"');
}
);
$data = $data->filter(
function(TransactionJournal $journal) {
if ($journal->amount != 0) {
return $journal;
}
);
} else {
// any deposit goes:
$query->where('transaction_types.type', 'Deposit');
}
$query->groupBy('t_from.account_id')->orderBy('queryAmount');
$data = $query->get(
['t_from.account_id as account_id', 'ac_from.name as name', 'ac_from.encrypted as encrypted', DB::Raw('SUM(t_from.amount) as `queryAmount`')]
);
// decrypt
$data->each(
function (Model $object) {
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
return null;
}
);
@@ -458,119 +197,51 @@ class ReportQuery implements ReportQueryInterface
}
/**
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
* expenses.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpenses(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
'transactions.amount', '>', 0
);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->where('account_meta.data', '"sharedAsset"')
->after($start)
->before($end)
->where('transaction_types.type', 'Transfer')
->where('transaction_journals.user_id', Auth::user()->id)
->get(
['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name',
'transactions.amount as queryAmount']
);
}
/**
* With a slightly misleading name, this query returns all transfers to shared accounts
* which are technically expenses, since it won't be just your money that gets spend.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpensesByCategory(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
'transactions.amount', '>', 0
);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
->where('account_meta.data', '"sharedAsset"')
->after($start)
->before($end)
->where('transaction_types.type', 'Transfer')
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('categories.name')
->get(
[
'categories.id',
'categories.name as name',
DB::Raw('SUM(`transactions`.`amount`) * -1 AS `queryAmount`')
]
);
}
/**
*
* This query will get all transaction journals and budget information for a specified account
* in a certain date range, where the transaction journal does not have a budget.
* There is no get() specified, this is up to the method itself.
* Covers tags
*
* @param Account $account
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Builder
* @return float
*/
protected function queryJournalsNoBudget(Account $account, Carbon $start, Carbon $end)
public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->before($end)
->after($start)
->where('accounts.id', $account->id)
->where('transaction_journals.user_id', Auth::user()->id)
->where('transaction_types.type', 'Withdrawal')
->groupBy('budgets.id')
->orderBy('budgets.name', 'ASC');
return floatval(
Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->transactionTypes(['Withdrawal'])
->where('transactions.account_id', $account->id)
->before($end)
->after($start)
->where('budget_transaction_journal.budget_id', $budget->id)
->get(['transaction_journals.*'])->sum('amount')
) * -1;
}
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
* @param bool $shared
*
* @return float
*/
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false)
{
return floatval(
Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->transactionTypes(['Withdrawal'])
->where('transactions.account_id', $account->id)
->before($end)
->after($start)
->whereNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*'])->sum('amount')
);
}
/**
@@ -583,31 +254,30 @@ class ReportQuery implements ReportQueryInterface
{
$query = TransactionJournal::
leftJoin(
'transactions as t_from', function (JoinClause $join) {
'transactions as t_from', function(JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
->leftJoin(
'account_meta as acm_from', function (JoinClause $join) {
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
->leftJoin(
'account_meta as acm_to', function (JoinClause $join) {
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
}
)
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
->leftJoin(
'account_meta as acm_from', function(JoinClause $join) {
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
}
)
->leftJoin(
'transactions as t_to', function(JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
->leftJoin(
'account_meta as acm_to', function(JoinClause $join) {
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
}
)
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
$query->before($end)->after($start)->where('transaction_journals.user_id', Auth::user()->id);
return $query;
}
}

View File

@@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use Illuminate\Support\Collection;
/**
@@ -15,152 +16,66 @@ interface ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
* See ReportQueryInterface::incomeInPeriodCorrected
*
* @param bool $showSharedReports
* This method returns all "expense" journals in a certain period, which are both transfers to a shared account
* and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*
*/
public function accountList($showSharedReports = false);
/**
* This method will get a list of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end);
/**
* This method will get the sum of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end);
public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false);
/**
* Get a users accounts combined with various meta-data related to the start and end date.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
* @param bool $includeShared
*
* @return Collection
*/
public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false);
public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false);
/**
* Grabs a summary of all expenses grouped by budget, related to the account.
* This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results
* will simply list the transaction journals only. This should allow any follow up counting to be accurate with
* regards to tags.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*/
public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false);
/**
* Covers tags as well.
*
* @param Account $account
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
* @return float
*/
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end);
public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end);
/**
* Get a list of transaction journals that have no budget, filtered for the specified account
* and the specified date range.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
* @param bool $shared
*
* @return Collection
* @return float
*/
public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end);
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false);
/**
* This method returns all "income" journals in a certain period, which are both transfers from a shared account
* and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* Gets a list of expenses grouped by the budget they were filed under.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* Gets a list of categories and the expenses therein, grouped by the relevant category.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* So now it will include them!
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* This method returns all deposits into asset accounts, grouped by the revenue account,
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
* expenses.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpenses(Carbon $start, Carbon $end);
/**
* With a slightly misleading name, this query returns all transfers to shared accounts
* which are technically expenses, since it won't be just your money that gets spend.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpensesByCategory(Carbon $start, Carbon $end);
}

View File

@@ -3,7 +3,6 @@
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\AccountFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -22,13 +21,13 @@ use View;
class AccountController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('mainTitleIcon', 'fa-credit-card');
View::share('title', 'Accounts');
View::share('title', trans('firefly.accounts'));
}
/**
@@ -39,13 +38,15 @@ class AccountController extends Controller
public function create($what = 'asset')
{
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$subTitle = 'Create a new ' . e($what) . ' account';
$subTitle = trans('firefly.make_new_' . $what . '_account');
// put previous url in session if not redirect from store (not "create another").
if (Session::get('accounts.create.fromStore') !== true) {
Session::put('accounts.create.url', URL::previous());
}
Session::forget('accounts.create.fromStore');
Session::flash('gaEventCategory', 'accounts');
Session::flash('gaEventAction', 'create-' . $what);
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
@@ -58,10 +59,13 @@ class AccountController extends Controller
*/
public function delete(Account $account)
{
$subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
$typeName = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
// put previous url in session
Session::put('accounts.delete.url', URL::previous());
Session::flash('gaEventCategory', 'accounts');
Session::flash('gaEventAction', 'delete-' . $typeName);
return view('accounts.delete', compact('account', 'subTitle'));
}
@@ -81,7 +85,7 @@ class AccountController extends Controller
$repository->destroy($account);
Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.');
Session::flash('success', trans('firefly.' . $typeName . '_deleted', ['name' => $name]));
return Redirect::to(Session::get('accounts.delete.url'));
}
@@ -90,13 +94,13 @@ class AccountController extends Controller
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return View
* @return \Illuminate\View\View
*/
public function edit(AccountRepositoryInterface $repository, Account $account)
{
$what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type];
$subTitle = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$openingBalance = $repository->openingBalanceTransaction($account);
@@ -125,6 +129,8 @@ class AccountController extends Controller
'virtualBalance' => floatval($account->virtual_balance)
];
Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'accounts');
Session::flash('gaEventAction', 'edit-' . $what);
return view('accounts.edit', compact('account', 'subTitle', 'subTitleIcon', 'openingBalance', 'what'));
}
@@ -133,11 +139,11 @@ class AccountController extends Controller
* @param AccountRepositoryInterface $repository
* @param $what
*
* @return View
* @return \Illuminate\View\View
*/
public function index(AccountRepositoryInterface $repository, $what)
{
$subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what);
$subTitle = trans('firefly.' . $what . '_accounts');
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$types = Config::get('firefly.accountTypesByIdentifier.' . $what);
$accounts = $repository->getAccounts($types);
@@ -148,7 +154,7 @@ class AccountController extends Controller
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$start->subDay();
$accounts->each(
function (Account $account) use ($start, $repository) {
function(Account $account) use ($start, $repository) {
$account->lastActivityDate = $repository->getLastActivity($account);
$account->startBalance = Steam::balance($account, $start);
$account->endBalance = Steam::balance($account, clone Session::get('end', Carbon::now()->endOfMonth()));
@@ -162,7 +168,7 @@ class AccountController extends Controller
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return View
* @return \Illuminate\View\View
*/
public function show(AccountRepositoryInterface $repository, Account $account)
{
@@ -170,7 +176,7 @@ class AccountController extends Controller
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$journals = $repository->getJournals($account, $page);
$subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
$subTitle = trans('firefly.details_for_' . $what, ['name' => $account->name]);
$journals->setPath('accounts/show/' . $account->id);
@@ -193,11 +199,11 @@ class AccountController extends Controller
'user' => Auth::user()->id,
'accountRole' => $request->input('accountRole'),
'openingBalance' => floatval($request->input('openingBalance')),
'openingBalanceDate' => new Carbon($request->input('openingBalanceDate')),
'openingBalanceDate' => new Carbon((string) $request->input('openingBalanceDate')),
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
];
$account = $repository->store($accountData);
$account = $repository->store($accountData);
Session::flash('success', 'New account "' . $account->name . '" stored!');
@@ -219,7 +225,7 @@ class AccountController extends Controller
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(AccountFormRequest $request, AccountRepositoryInterface $repository, Account $account)
{
@@ -231,7 +237,7 @@ class AccountController extends Controller
'accountRole' => $request->input('accountRole'),
'virtualBalance' => floatval($request->input('virtualBalance')),
'openingBalance' => floatval($request->input('openingBalance')),
'openingBalanceDate' => new Carbon($request->input('openingBalanceDate')),
'openingBalanceDate' => new Carbon((string) $request->input('openingBalanceDate')),
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
'ccType' => $request->input('ccType'),
'ccMonthlyPaymentDate' => $request->input('ccMonthlyPaymentDate'),
@@ -245,7 +251,7 @@ class AccountController extends Controller
// set value so edit routine will not overwrite URL:
Session::put('accounts.edit.fromUpdate', true);
return Redirect::route('accounts.edit', $account->id)->withInput(['return_to_edit' => 1]);
return Redirect::route('accounts.edit', [$account->id])->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.

View File

@@ -1,6 +1,9 @@
<?php namespace FireflyIII\Http\Controllers\Auth;
use App;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Role;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Registrar;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
@@ -38,6 +41,7 @@ class AuthController extends Controller
*
* @param \Illuminate\Contracts\Auth\Guard $auth
* @param \Illuminate\Contracts\Auth\Registrar $registrar
*
* @codeCoverageIgnore
*
*/
@@ -66,7 +70,7 @@ class AuthController extends Controller
*
* @param Request $request
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\RedirectResponse
*/
public function postRegister(Request $request)
{
@@ -86,22 +90,34 @@ class AuthController extends Controller
$this->auth->login($this->registrar->create($data));
// get the email address
$email = $this->auth->user()->email;
if ($this->auth->user() instanceof User) {
$email = $this->auth->user()->email;
// send email.
Mail::send(
'emails.registered', [], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Welcome to Firefly III!');
// send email.
Mail::send(
'emails.registered', [], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Welcome to Firefly III!');
}
);
// set flash message
Session::flash('success', 'You have registered successfully!');
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'new-registration');
// first user ever?
if (User::count() == 1) {
$admin = Role::where('name', 'owner')->first();
$this->auth->user()->attachRole($admin);
// $this->auth->user()->roles()->save($admin);
}
return redirect($this->redirectPath());
}
);
App::abort(500, 'Not a user!');
// set flash message
Session::flash('success', 'You have registered successfully!');
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'new-registration');
return redirect($this->redirectPath());
return redirect('/');
}
}

View File

@@ -7,6 +7,7 @@ use Illuminate\Foundation\Auth\ResetsPasswords;
/**
* Class PasswordController
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Controllers\Auth
*/
@@ -35,6 +36,8 @@ class PasswordController extends Controller
* @param \Illuminate\Contracts\Auth\Guard $auth
* @param \Illuminate\Contracts\Auth\PasswordBroker $passwords
*
* @codeCoverageIgnore
*
*/
public function __construct(Guard $auth, PasswordBroker $passwords)
{

View File

@@ -1,13 +1,9 @@
<?php namespace FireflyIII\Http\Controllers;
use Config;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\BillFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Input;
use Redirect;
@@ -24,61 +20,17 @@ class BillController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Bills');
View::share('title', trans('firefly.bills'));
View::share('mainTitleIcon', 'fa-calendar-o');
}
/**
* @param AccountRepositoryInterface $repository
* @param Bill $bill
*
* @return \Illuminate\Http\RedirectResponse
*/
public function add(AccountRepositoryInterface $repository, Bill $bill)
{
$matches = explode(',', $bill->match);
$description = [];
$expense = null;
// get users expense accounts:
$accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense'));
foreach ($matches as $match) {
$match = strtolower($match);
// find expense account for each word if not found already:
if (is_null($expense)) {
/** @var Account $account */
foreach ($accounts as $account) {
$name = strtolower($account->name);
if (!(strpos($name, $match) === false)) {
$expense = $account;
break;
}
}
}
if (is_null($expense)) {
$description[] = $match;
}
}
$parameters = [
'description' => ucfirst(join(' ', $description)),
'expense_account' => is_null($expense) ? '' : $expense->name,
'amount' => round(($bill->amount_min + $bill->amount_max), 2),
];
Session::put('preFilled', $parameters);
return Redirect::to(route('transactions.create', 'withdrawal'));
}
/**
* @return $this
* @return \Illuminate\View\View
*/
public function create()
{
@@ -89,6 +41,8 @@ class BillController extends Controller
Session::put('bills.create.url', URL::previous());
}
Session::forget('bills.create.fromStore');
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'create');
$subTitle = 'Create new bill';
return view('bills.create', compact('periods', 'subTitle'));
@@ -97,13 +51,15 @@ class BillController extends Controller
/**
* @param Bill $bill
*
* @return $this
* @return \Illuminate\View\View
*/
public function delete(Bill $bill)
{
// put previous url in session
Session::put('bills.delete.url', URL::previous());
$subTitle = 'Delete "' . e($bill->name) . '"';
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'delete');
$subTitle = trans('firefly.delete_bill', ['name' => $bill->name]);
return view('bills.delete', compact('bill', 'subTitle'));
}
@@ -127,7 +83,7 @@ class BillController extends Controller
/**
* @param Bill $bill
*
* @return $this
* @return \Illuminate\View\View
*/
public function edit(Bill $bill)
{
@@ -139,6 +95,8 @@ class BillController extends Controller
Session::put('bills.edit.url', URL::previous());
}
Session::forget('bills.edit.fromUpdate');
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'edit');
return view('bills.edit', compact('subTitle', 'periods', 'bill'));
}
@@ -152,7 +110,7 @@ class BillController extends Controller
{
$bills = $repository->getBills();
$bills->each(
function (Bill $bill) use ($repository) {
function(Bill $bill) use ($repository) {
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
$bill->lastFoundMatch = $repository->lastFoundMatch($bill);
}
@@ -191,7 +149,7 @@ class BillController extends Controller
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return mixed
* @return \Illuminate\View\View
*/
public function show(BillRepositoryInterface $repository, Bill $bill)
{
@@ -207,7 +165,7 @@ class BillController extends Controller
* @param BillFormRequest $request
* @param BillRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function store(BillFormRequest $request, BillRepositoryInterface $repository)
{
@@ -232,7 +190,7 @@ class BillController extends Controller
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(BillFormRequest $request, BillRepositoryInterface $repository, Bill $bill)
{
@@ -245,7 +203,7 @@ class BillController extends Controller
// set value so edit routine will not overwrite URL:
Session::put('bills.edit.fromUpdate', true);
return Redirect::route('bills.edit', $bill->id)->withInput(['return_to_edit' => 1]);
return Redirect::route('bills.edit', [$bill->id])->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.

View File

@@ -1,8 +1,8 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\BudgetFormRequest;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
@@ -19,17 +19,18 @@ use View;
* Class BudgetController
*
* @package FireflyIII\Http\Controllers
* @SuppressWarnings(PHPMD.TooManyMethods)
*/
class BudgetController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Budgets');
View::share('title', trans('firefly.budgets'));
View::share('mainTitleIcon', 'fa-tasks');
View::share('hideBudgets', true);
}
@@ -45,13 +46,16 @@ class BudgetController extends Controller
$amount = intval(Input::get('amount'));
$date = Session::get('start', Carbon::now()->startOfMonth());
$limitRepetition = $repository->updateLimitAmount($budget, $date, $amount);
if ($amount == 0) {
$limitRepetition = null;
}
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]);
}
/**
* @return $this
* @return \Illuminate\View\View
*/
public function create()
{
@@ -60,7 +64,9 @@ class BudgetController extends Controller
Session::put('budgets.create.url', URL::previous());
}
Session::forget('budgets.create.fromStore');
$subTitle = 'Create a new budget';
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'create');
$subTitle = trans('firefly.create_new_budget');
return view('budgets.create', compact('subTitle'));
}
@@ -72,10 +78,12 @@ class BudgetController extends Controller
*/
public function delete(Budget $budget)
{
$subTitle = 'Delete budget' . e($budget->name) . '"';
$subTitle = trans('firefly.delete_budget', ['name' => $budget->name]);
// put previous url in session
Session::put('budgets.delete.url', URL::previous());
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'delete');
return view('budgets.delete', compact('budget', 'subTitle'));
}
@@ -95,13 +103,14 @@ class BudgetController extends Controller
Session::flash('success', 'The budget "' . e($name) . '" was deleted.');
return Redirect::to(Session::get('budgets.delete.url'));
}
/**
* @param Budget $budget
*
* @return $this
* @return \Illuminate\View\View
*/
public function edit(Budget $budget)
{
@@ -112,6 +121,8 @@ class BudgetController extends Controller
Session::put('budgets.edit.url', URL::previous());
}
Session::forget('budgets.edit.fromUpdate');
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'edit');
return view('budgets.edit', compact('budget', 'subTitle'));
@@ -120,13 +131,15 @@ class BudgetController extends Controller
/**
* @param BudgetRepositoryInterface $repository
*
* @return View
* @return \Illuminate\View\View
*/
public function index(BudgetRepositoryInterface $repository)
{
$budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets();
$spent = '0';
$budgeted = '0';
bcscale(2);
/**
* Do some cleanup:
*/
@@ -134,36 +147,43 @@ class BudgetController extends Controller
// loop the budgets:
$budgets->each(
function (Budget $budget) use ($repository) {
$date = Session::get('start', Carbon::now()->startOfMonth());
$budget->spent = $repository->spentInMonth($budget, $date);
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
/** @var Budget $budget */
foreach ($budgets as $budget) {
$date = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$budget->spent = $repository->spentInPeriodCorrected($budget, $date, $end);
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
if ($budget->currentRep) {
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
}
$spent = bcadd($spent, $budget->spent);
}
$dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$budgetIncomeTotal = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data;
$budgetMaximum = Preferences::get('budgetMaximum', 1000)->data;
$defaultCurrency = Amount::getDefaultCurrency();
return view(
'budgets.index', compact('budgetMaximum', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
);
$dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$spent = $budgets->sum('spent');
$amount = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data;
$overspent = $spent > $amount;
$spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
return view('budgets.index', compact('budgetMaximum', 'inactive', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
}
/**
* @param BudgetRepositoryInterface $repository
*
* @return View
* @return \Illuminate\View\View
*/
public function noBudget(BudgetRepositoryInterface $repository)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->startOfMonth());
$list = $repository->getWithoutBudget($start, $end);
$subTitle = 'Transactions without a budget between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y');
$subTitle = trans(
'firefly.without_budget_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
return view('budgets.noBudget', compact('list', 'subTitle'));
}
@@ -185,7 +205,7 @@ class BudgetController extends Controller
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return View
* @return \Illuminate\View\View
*/
public function show(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition = null)
{
@@ -197,7 +217,11 @@ class BudgetController extends Controller
$journals = $repository->getJournals($budget, $repetition);
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget);
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
$subTitle = !is_null($repetition->id)
?
trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)])
:
e($budget->name);
$journals->setPath('/budgets/show/' . $budget->id);
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
@@ -215,7 +239,7 @@ class BudgetController extends Controller
'name' => $request->input('name'),
'user' => Auth::user()->id,
];
$budget = $repository->store($budgetData);
$budget = $repository->store($budgetData);
Session::flash('success', 'New budget "' . $budget->name . '" stored!');
@@ -236,7 +260,7 @@ class BudgetController extends Controller
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(BudgetFormRequest $request, BudgetRepositoryInterface $repository, Budget $budget)
{
@@ -253,7 +277,7 @@ class BudgetController extends Controller
// set value so edit routine will not overwrite URL:
Session::put('budgets.edit.fromUpdate', true);
return Redirect::route('budgets.edit', $budget->id)->withInput(['return_to_edit' => 1]);
return Redirect::route('budgets.edit', [$budget->id])->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
@@ -262,7 +286,7 @@ class BudgetController extends Controller
}
/**
* @return View
* @return \Illuminate\View\View
*/
public function updateIncome()
{

View File

@@ -21,17 +21,17 @@ class CategoryController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Categories');
View::share('title', trans('firefly.categories'));
View::share('mainTitleIcon', 'fa-bar-chart');
}
/**
* @return $this
* @return \Illuminate\View\View
*/
public function create()
{
@@ -40,6 +40,8 @@ class CategoryController extends Controller
Session::put('categories.create.url', URL::previous());
}
Session::forget('categories.create.fromStore');
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'create');
$subTitle = 'Create a new category';
return view('categories.create', compact('subTitle'));
@@ -52,10 +54,12 @@ class CategoryController extends Controller
*/
public function delete(Category $category)
{
$subTitle = 'Delete category "' . e($category->name) . '"';
$subTitle = trans('firefly.delete_category', ['name' => $category->name]);
// put previous url in session
Session::put('categories.delete.url', URL::previous());
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'delete');
return view('categories.delete', compact('category', 'subTitle'));
}
@@ -80,7 +84,7 @@ class CategoryController extends Controller
/**
* @param Category $category
*
* @return $this
* @return \Illuminate\View\View
*/
public function edit(Category $category)
{
@@ -91,6 +95,8 @@ class CategoryController extends Controller
Session::put('categories.edit.url', URL::previous());
}
Session::forget('categories.edit.fromUpdate');
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'edit');
return view('categories.edit', compact('category', 'subTitle'));
@@ -99,14 +105,14 @@ class CategoryController extends Controller
/**
* @param CategoryRepositoryInterface $repository
*
* @return $this
* @return \Illuminate\View\View
*/
public function index(CategoryRepositoryInterface $repository)
{
$categories = $repository->getCategories();
$categories->each(
function (Category $category) use ($repository) {
function(Category $category) use ($repository) {
$category->lastActivity = $repository->getLatestActivity($category);
}
);
@@ -133,7 +139,7 @@ class CategoryController extends Controller
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return View
* @return \Illuminate\View\View
*/
public function show(CategoryRepositoryInterface $repository, Category $category)
{
@@ -151,7 +157,7 @@ class CategoryController extends Controller
* @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository
*
* @return mixed
* @return \Illuminate\Http\RedirectResponse
*/
public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository)
{
@@ -159,7 +165,7 @@ class CategoryController extends Controller
'name' => $request->input('name'),
'user' => Auth::user()->id,
];
$category = $repository->store($categoryData);
$category = $repository->store($categoryData);
Session::flash('success', 'New category "' . $category->name . '" stored!');
@@ -193,7 +199,7 @@ class CategoryController extends Controller
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('categories.edit.fromUpdate', true);
return Redirect::route('categories.edit', $category->id);
return Redirect::route('categories.edit', [$category->id]);
}
// redirect to previous URL.

View File

@@ -0,0 +1,152 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Preferences;
use Response;
use Session;
use Steam;
/**
* Class AccountController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class AccountController extends Controller
{
/**
* Shows the balances for all the user's accounts.
*
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @param $year
* @param $month
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function all(GChart $chart, AccountRepositoryInterface $repository, $year, $month, $shared = false)
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
/** @var Collection $accounts */
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
if ($shared === false) {
/** @var Account $account */
foreach ($accounts as $index => $account) {
if ($account->getMeta('accountRole') == 'sharedAsset') {
$accounts->forget($index);
}
}
}
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows the balances for all the user's frontpage accounts.
*
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, AccountRepositoryInterface $repository)
{
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = $repository->getFrontpageAccounts($frontPage);
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows an account's balance for a single month.
*
* @param GChart $chart
* @param Account $account
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(GChart $chart, Account $account)
{
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$current = clone $start;
$today = new Carbon;
while ($end >= $current) {
$certain = $current < $today;
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Response;
use Session;
use Steam;
/**
* Class BillController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class BillController extends Controller
{
/**
* Shows the overview for a bill. The min/max amount and matched journals.
*
* @param GChart $chart
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
{
$chart->addColumn(trans('firefly.date'), 'date');
$chart->addColumn(trans('firefly.maxAmount'), 'number');
$chart->addColumn(trans('firefly.minAmount'), 'number');
$chart->addColumn(trans('firefly.billEntry'), 'number');
// get first transaction or today for start:
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows all bills and whether or not theyve been paid this month (pie chart).
*
* @param GChart $chart
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{
$chart->addColumn(trans('firefly.name'), 'string');
$chart->addColumn(trans('firefly.amount'), 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$bills = $repository->getActiveBills();
$paid = new Collection; // journals.
$unpaid = new Collection; // bills
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
if ($journals->count() == 0) {
$unpaid->push([$bill, $range['start']]);
} else {
$paid = $paid->merge($journals);
}
}
}
$creditCards = $accounts->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, $end, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid! create a fake bill that matches the amount.
$description = $creditCard->name;
$amount = $balance * -1;
$fakeBill = $repository->createFakeBill($description, $date, $amount);
unset($description, $amount);
$unpaid->push([$fakeBill, $date]);
}
if ($balance == 0) {
// find transfer(s) TO the credit card which should account for
// anything paid. If not, the CC is not yet used.
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
$paid = $paid->merge($journals);
}
}
/** @var TransactionJournal $entry */
foreach ($paid as $entry) {
$paidDescriptions[] = $entry->description;
$paidAmount += floatval($entry->amount);
}
// loop unpaid:
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$unpaidAmount += $amount;
unset($amount, $description);
}
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,197 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
use Response;
use Session;
/**
* Class BudgetController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class BudgetController extends Controller
{
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budget(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget)
{
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
$first = $repository->getFirstBudgetLimitDate($budget);
$range = Preferences::get('viewRange', '1M')->data;
$last = Session::get('end', new Carbon);
$final = clone $last;
$final->addYears(2);
$last = Navigation::endOfX($last, $range, $final);
while ($first < $last) {
$end = Navigation::addPeriod($first, $range, 0);
$spent = $repository->spentInPeriodCorrected($budget, $first, $end);
$chart->addRow($end, $spent);
$first = Navigation::addPeriod($first, $range, 0);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows the amount left in a specific budget limit.
*
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetLimit(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
$chart->addColumn(trans('firefly.day'), 'date');
$chart->addColumn(trans('firefly.left'), 'number');
$amount = $repetition->amount;
while ($start <= $end) {
/*
* Sum of expenses on this day:
*/
$sum = $repository->expensesOnDayCorrected($budget, $start);
$amount += $sum;
$chart->addRow(clone $start, $amount);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows a budget list with spent/left/overspent.
*
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, BudgetRepositoryInterface $repository)
{
$chart->addColumn(trans('firefly.budget'), 'string');
$chart->addColumn(trans('firefly.left'), 'number');
$chart->addColumn(trans('firefly.spent'), 'number');
$chart->addColumn(trans('firefly.overspent'), 'number');
$budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$allEntries = new Collection;
foreach ($budgets as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
$expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true);
$allEntries->push([$budget->name, 0, 0, $expenses]);
continue;
}
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
$spent = $expenses > floatval($repetition->amount) ? floatval($repetition->amount) : $expenses;
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
$allEntries->push(
[$budget->name . ' (' . $repetition->startdate->formatLocalized($this->monthAndDayFormat) . ')',
$left,
$spent,
$overspent
]
);
}
}
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1;
$allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses]);
foreach ($allEntries as $entry) {
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
}
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Show a yearly overview for a budget.
*
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function year(GChart $chart, BudgetRepositoryInterface $repository, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$budgets = $repository->getBudgets();
// add columns:
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
while ($start < $end) {
// month is the current end of the period:
$month = clone $start;
$month->endOfMonth();
// make a row:
$row = [clone $start];
// each budget, fill the row:
foreach ($budgets as $budget) {
$spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,178 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Navigation;
use Preferences;
use Response;
use Session;
/**
* Class CategoryController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class CategoryController extends Controller
{
/**
* Show an overview for a category for all time, per month/week/year.
*
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function all(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
$start = $repository->getFirstActivityDate($category);
$range = Preferences::get('viewRange', '1M')->data;
// jump to start of week / month / year / etc
$start = Navigation::startOfPeriod($start, $range);
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
$end = new Carbon;
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range);
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
$chart->addRow(clone $start, $spent);
$start = Navigation::addPeriod($start, $range, 0);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Show this month's category overview.
*
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, CategoryRepositoryInterface $repository)
{
$chart->addColumn(trans('firefly.category'), 'string');
$chart->addColumn(trans('firefly.spent'), 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$set = $repository->getCategoriesAndExpensesCorrected($start, $end);
// sort by callback:
uasort(
$set,
function($left, $right) {
if ($left['sum'] == $right['sum']) {
return 0;
}
return ($left['sum'] < $right['sum']) ? 1 : -1;
}
);
foreach ($set as $entry) {
$sum = floatval($entry['sum']);
if ($sum != 0) {
$chart->addRow($entry['name'], $sum);
}
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function month(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
while ($start <= $end) {
$spent = $repository->spentOnDaySumCorrected($category, $start);
$chart->addRow(clone $start, $spent);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* This chart will only show expenses.
*
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function year(GChart $chart, CategoryRepositoryInterface $repository, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$categories = $repository->getCategories();
// add columns:
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($categories as $category) {
$chart->addColumn($category->name, 'number');
}
while ($start < $end) {
// month is the current end of the period:
$month = clone $start;
$month->endOfMonth();
// make a row:
$row = [clone $start];
// each budget, fill the row:
foreach ($categories as $category) {
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Response;
/**
* Class PiggyBankController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class PiggyBankController extends Controller
{
/**
* Shows the piggy bank history.
*
* @param GChart $chart
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function history(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$chart->addColumn(trans('firefly.date'), 'date');
$chart->addColumn(trans('firefly.balance'), 'number');
/** @var Collection $set */
$set = $repository->getEventSummarySet($piggyBank);
$sum = 0;
foreach ($set as $entry) {
$sum += floatval($entry->sum);
$chart->addRow(new Carbon($entry->date), $sum);
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Http\Controllers\Controller;
use Grumpydictator\Gchart\GChart;
use Response;
/**
* Class ReportController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class ReportController extends Controller
{
/**
* Summarizes all income and expenses, per month, for a given year.
*
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInOut(GChart $chart, ReportQueryInterface $query, $year, $shared = false)
{
// get start and end of year
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$chart->addColumn(trans('firefly.month'), 'date');
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$incomeSum = floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
$expenseSum = floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
$chart->addRow(clone $start, $incomeSum, $expenseSum);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Summarizes all income and expenses for a given year. Gives a total and an average.
*
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInOutSummarized(GChart $chart, ReportQueryInterface $query, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$income = 0;
$expense = 0;
$count = 0;
$chart->addColumn(trans('firefly.summary'), 'string');
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$income += floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
$expense += floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
$count++;
$start->addMonth();
}
// add total + average:
$chart->addRow(trans('firefly.sum'), $income, $expense);
$count = $count > 0 ? $count : 1;
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -1,8 +1,11 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Config;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Preferences;
use View;
/**
@@ -15,8 +18,13 @@ abstract class Controller extends BaseController
use DispatchesCommands, ValidatesRequests;
/** @var string */
protected $monthAndDayFormat;
/** @var string */
protected $monthFormat;
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
@@ -24,5 +32,16 @@ abstract class Controller extends BaseController
View::share('hideCategories', false);
View::share('hideBills', false);
View::share('hideTags', false);
if (Auth::check()) {
$pref = Preferences::get('language', 'en');
$lang = $pref->data;
$this->monthFormat = Config::get('firefly.month.' . $lang);
$this->monthAndDayFormat = Config::get('firefly.monthAndDay.' . $lang);
View::share('monthFormat', $this->monthFormat);
View::share('monthAndDayFormat', $this->monthAndDayFormat);
View::share('language', $lang);
}
}
}

View File

@@ -1,9 +1,8 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Cache;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\CurrencyFormRequest;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Input;
@@ -23,12 +22,12 @@ class CurrencyController extends Controller
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Currencies');
View::share('title', trans('firefly.currencies'));
View::share('mainTitleIcon', 'fa-usd');
}
@@ -45,6 +44,8 @@ class CurrencyController extends Controller
Session::put('currency.create.url', URL::previous());
}
Session::forget('currency.create.fromStore');
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'create');
return view('currency.create', compact('subTitleIcon', 'subTitle'));
}
@@ -84,6 +85,8 @@ class CurrencyController extends Controller
// put previous url in session
Session::put('currency.delete.url', URL::previous());
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'delete');
return view('currency.delete', compact('currency'));
@@ -105,8 +108,9 @@ class CurrencyController extends Controller
}
Session::flash('success', 'Currency "' . e($currency->name) . '" deleted');
$currency->delete();
if (Auth::user()->hasRole('owner')) {
$currency->delete();
}
return Redirect::to(Session::get('currency.delete.url'));
}
@@ -127,6 +131,8 @@ class CurrencyController extends Controller
Session::put('currency.edit.url', URL::previous());
}
Session::forget('currency.edit.fromUpdate');
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'edit');
return view('currency.edit', compact('currency', 'subTitle', 'subTitleIcon'));
@@ -142,6 +148,12 @@ class CurrencyController extends Controller
$currencies = $repository->get();
$defaultCurrency = $repository->getCurrencyByPreference(Preferences::get('currencyPreference', 'EUR'));
if (!Auth::user()->hasRole('owner')) {
Session::flash('warning', 'Please ask ' . env('SITE_OWNER') . ' to add, remove or edit currencies.');
}
return view('currency.index', compact('currencies', 'defaultCurrency'));
}
@@ -154,11 +166,11 @@ class CurrencyController extends Controller
*/
public function store(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository)
{
$data = $request->getCurrencyData();
$currency = $repository->store($data);
Session::flash('success', 'Currency "' . $currency->name . '" created');
$data = $request->getCurrencyData();
if (Auth::user()->hasRole('owner')) {
$currency = $repository->store($data);
Session::flash('success', 'Currency "' . $currency->name . '" created');
}
if (intval(Input::get('create_another')) === 1) {
Session::put('currency.create.fromStore', true);
@@ -181,16 +193,17 @@ class CurrencyController extends Controller
*/
public function update(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
$data = $request->getCurrencyData();
$currency = $repository->update($currency, $data);
$data = $request->getCurrencyData();
if (Auth::user()->hasRole('owner')) {
$currency = $repository->update($currency, $data);
}
Session::flash('success', 'Currency "' . e($currency->name) . '" updated.');
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('currency.edit.fromUpdate', true);
return Redirect::route('currency.edit', $currency->id);
return Redirect::route('currency.edit', [$currency->id]);
}
// redirect to previous URL.

View File

@@ -1,590 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use Crypt;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
use Response;
use Session;
use Steam;
/**
* Class GoogleChartController
*
* @package FireflyIII\Http\Controllers
*/
class GoogleChartController extends Controller
{
/**
* @param GChart $chart
* @param Account $account
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function accountBalanceChart(GChart $chart, Account $account)
{
$chart->addColumn('Day of month', 'date');
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$current = clone $start;
$today = new Carbon;
while ($end >= $current) {
$certain = $current < $today;
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allAccountsBalanceChart(GChart $chart, AccountRepositoryInterface $repository)
{
$chart->addColumn('Day of the month', 'date');
$frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = $repository->getFrontpageAccounts($frontPage);
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, $year)
{
$budgets = $repository->getBudgets();
$chart->addColumn('Month', 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
$start = Carbon::createFromDate(intval($year), 1, 1);
$end = clone $start;
$end->endOfYear();
while ($start <= $end) {
$row = [clone $start];
foreach ($budgets as $budget) {
$spent = $repository->spentInMonth($budget, $start);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository)
{
$chart->addColumn('Budget', 'string');
$chart->addColumn('Left', 'number');
$chart->addColumn('Spent', 'number');
$chart->addColumn('Overspent', 'number');
$budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$allEntries = new Collection;
foreach ($budgets as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $start, $end);
$allEntries->push([$budget->name, 0, 0, $expenses]);
continue;
}
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $repetition->startdate, $repetition->enddate);
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
$spent = $expenses > floatval($repetition->amount) ? 0 : $expenses;
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
$allEntries->push(
[$budget->name . ' (' . $repetition->startdate->format('j M Y') . ')',
$left,
$spent,
$overspent
]
);
}
}
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end);
$allEntries->push(['(no budget)', 0, 0, $noBudgetExpenses]);
foreach ($allEntries as $entry) {
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
}
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allCategoriesHomeChart(GChart $chart, CategoryRepositoryInterface $repository)
{
$chart->addColumn('Category', 'string');
$chart->addColumn('Spent', 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$set = $repository->getCategoriesAndExpenses($start, $end);
foreach ($set as $entry) {
$isEncrypted = intval($entry->encrypted) == 1 ? true : false;
$name = strlen($entry->name) == 0 ? '(no category)' : $entry->name;
$name = $isEncrypted ? Crypt::decrypt($name) : $name;
$chart->addRow($name, floatval($entry->sum));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billOverview(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Max amount', 'number');
$chart->addColumn('Min amount', 'number');
$chart->addColumn('Recorded bill entry', 'number');
// get first transaction or today for start:
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billsOverview(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{
$chart->addColumn('Name', 'string');
$chart->addColumn('Amount', 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$bills = $repository->getActiveBills();
$paid = new Collection; // journals.
$unpaid = new Collection; // bills
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
if ($journals->count() == 0) {
$unpaid->push([$bill, $range['start']]);
} else {
$paid = $paid->merge($journals);
}
}
}
$creditCards = $accounts->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, null, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid! create a fake bill that matches the amount.
$description = $creditCard->name;
$amount = $balance * -1;
$fakeBill = $repository->createFakeBill($description, $date, $amount);
unset($description, $amount);
$unpaid->push([$fakeBill, $date]);
}
if ($balance == 0) {
// find transfer(s) TO the credit card which should account for
// anything paid. If not, the CC is not yet used.
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
$paid = $paid->merge($journals);
}
}
/** @var TransactionJournal $entry */
foreach ($paid as $entry) {
$paidDescriptions[] = $entry->description;
$paidAmount += floatval($entry->amount);
}
// loop unpaid:
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$unpaidAmount += $amount;
unset($amount, $description);
}
$chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount);
$chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount);
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetLimitSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
$chart->addColumn('Day', 'date');
$chart->addColumn('Left', 'number');
$amount = $repetition->amount;
while ($start <= $end) {
/*
* Sum of expenses on this day:
*/
$sum = $repository->expensesOnDay($budget, $start);
$amount += $sum;
$chart->addRow(clone $start, $amount);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param int $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, $year = 0)
{
$chart->addColumn('Month', 'date');
$chart->addColumn('Budgeted', 'number');
$chart->addColumn('Spent', 'number');
if ($year == 0) {
$start = $repository->getFirstBudgetLimitDate($budget);
$end = $repository->getLastBudgetLimitDate($budget);
} else {
$start = Carbon::createFromDate(intval($year), 1, 1);
$end = clone $start;
$end->endOfYear();
}
while ($start <= $end) {
$spent = $repository->spentInMonth($budget, $start);
$budgeted = $repository->getLimitAmountOnDate($budget, $start);
$chart->addRow(clone $start, $budgeted, $spent);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function categoryOverviewChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
$start = $repository->getFirstActivityDate($category);
/** @var Preference $range */
$range = Preferences::get('viewRange', '1M');
// jump to start of week / month / year / etc (TODO).
$start = Navigation::startOfPeriod($start, $range->data);
$chart->addColumn('Period', 'date');
$chart->addColumn('Spent', 'number');
$end = new Carbon;
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range->data);
$spent = $repository->spentInPeriodSum($category, $start, $currentEnd);
$chart->addRow(clone $start, $spent);
$start = Navigation::addPeriod($start, $range->data, 0);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function categoryPeriodChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$chart->addColumn('Period', 'date');
$chart->addColumn('Spent', 'number');
$end = Session::get('end', Carbon::now()->endOfMonth());
while ($start <= $end) {
$spent = $repository->spentOnDaySum($category, $start);
$chart->addRow(clone $start, $spent);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function piggyBankHistory(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Balance', 'number');
/** @var Collection $set */
$set = $repository->getEventSummarySet($piggyBank);
$sum = 0;
foreach ($set as $entry) {
$sum += floatval($entry->sum);
$chart->addRow(new Carbon($entry->date), $sum);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInExp(GChart $chart, ReportQueryInterface $query, $year)
{
$start = new Carbon('01-01-' . $year);
$chart->addColumn('Month', 'date');
$chart->addColumn('Income', 'number');
$chart->addColumn('Expenses', 'number');
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
// get report query interface.
$end = clone $start;
$end->endOfYear();
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income && total expenses:
$incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
$expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
$chart->addRow(clone $start, $incomeSum, $expenseSum);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInExpSum(GChart $chart, ReportQueryInterface $query, $year)
{
$start = new Carbon('01-01-' . $year);
$chart->addColumn('Summary', 'string');
$chart->addColumn('Income', 'number');
$chart->addColumn('Expenses', 'number');
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$income = 0;
$expense = 0;
$count = 0;
$end = clone $start;
$end->endOfYear();
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income:
$incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
// total expenses:
$expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
$income += $incomeSum;
$expense += $expenseSum;
$count++;
$start->addMonth();
}
$chart->addRow('Sum', $income, $expense);
$count = $count > 0 ? $count : 1;
$chart->addRow('Average', ($income / $count), ($expense / $count));
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -6,6 +6,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Route;
use Session;
use Steam;
@@ -53,7 +54,7 @@ class HomeController extends Controller
$types = Config::get('firefly.accountTypesByIdentifier.asset');
$count = $repository->countAccounts($types);
$title = 'Firefly';
$subTitle = 'What\'s playing?';
$subTitle = trans('firefly.welcomeBack');
$mainTitleIcon = 'fa-fire';
$transactions = [];
$frontPage = Preferences::get('frontPageAccounts', []);
@@ -63,19 +64,17 @@ class HomeController extends Controller
$savings = $repository->getSavingsAccounts();
$piggyBankAccounts = $repository->getPiggyBankAccounts();
$savingsTotal = 0;
foreach ($savings as $savingAccount) {
$savingsTotal += Steam::balance($savingAccount, $end);
}
// check if all books are correct.
$sum = $repository->sumOfEverything();
if ($sum != 0) {
Session::flash(
'error', 'Your transactions are unbalanced. This means a'
. ' withdrawal, deposit or transfer was not stored properly. '
. 'Please check your accounts and transactions for errors.'
. ' withdrawal, deposit or transfer was not stored properly. '
. 'Please check your accounts and transactions for errors.'
);
}
@@ -89,5 +88,78 @@ class HomeController extends Controller
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal', 'piggyBankAccounts'));
}
/**
* @codeCoverageIgnore
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function routes()
{
$directory = '/vagrant_data/Sites/firefly-iii-help';
$languages = array_keys(Config::get('firefly.lang'));
$routes = [];
$ignored = [
'debugbar.openhandler', 'debugbar.assets.css', 'debugbar.assets.js', 'register', 'routes', 'daterange',
'flush', 'delete-account-post', 'change-password-post', 'logout', 'login', 'tags.hideTagHelp',
'budgets.postIncome', 'flush'
];
$ignoreMatch = ['.store', '.update', '.destroy', 'json.'];
$routeCollection = Route::getRoutes();
/** @var \Illuminate\Routing\Route $object */
foreach ($routeCollection as $object) {
// get name:
$name = $object->getName();
// has name and not in ignore list?
if (strlen($name) > 0 && !in_array($name, $ignored)) {
// not in ignoreMatch?
$continue = true;
foreach ($ignoreMatch as $ignore) {
$match = strpos($name, $ignore);
if (!($match === false)) {
$continue = false;
}
}
unset($ignore, $match);
if ($continue) {
$routes[] = $name;
// check all languages:
foreach ($languages as $lang) {
$file = $directory . '/' . $lang . '/' . $name . '.md';
if (!file_exists($file)) {
touch($file);
echo $name . '<br />';
}
}
}
}
}
// loop directories with language file.
// tag the ones not in the list of approved routes.
foreach ($languages as $lang) {
$dir = $directory . '/' . $lang;
$set = scandir($dir);
foreach ($set as $entry) {
if ($entry != '.' && $entry != '..') {
$name = str_replace('.md', '', $entry);
if (!in_array($name, $routes)) {
$file = $dir . '/' . $entry;
unlink($file);
}
}
}
}
echo 'Done!';
}
}

View File

@@ -5,14 +5,12 @@ use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection;
use Preferences;
use Response;
use Session;
use Steam;
@@ -39,19 +37,14 @@ class JsonController extends Controller
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = 0;
// these two functions are the same as the chart TODO
// these two functions are the same as the chart
$bills = $repository->getActiveBills();
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$amount += $repository->getJournalsInRange($bill, $range['start'], $range['end'])->sum('amount');
}
$amount += $repository->billPaymentsInRange($bill, $start, $end);
}
unset($ranges, $bill, $range, $bills);
unset($bill, $bills);
/**
* Find credit card accounts and possibly unpaid credit card bills.
@@ -60,7 +53,7 @@ class JsonController extends Controller
// if the balance is not zero, the monthly payment is still underway.
/** @var Account $creditCard */
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, null, true);
$balance = Steam::balance($creditCard, $end, true);
if ($balance == 0) {
// find a transfer TO the credit card which should account for
// anything paid. If not, the CC is not yet used.
@@ -100,7 +93,7 @@ class JsonController extends Controller
$creditCards = $accountRepository->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, null, true);
$balance = Steam::balance($creditCard, $end, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid! create a fake bill that matches the amount.
@@ -128,7 +121,7 @@ class JsonController extends Controller
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = $reportQuery->incomeByPeriod($start, $end, true)->sum('queryAmount');
$amount = $reportQuery->incomeInPeriodCorrected($start, $end, true)->sum('amount');
return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
}
@@ -142,7 +135,7 @@ class JsonController extends Controller
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = $reportQuery->journalsByExpenseAccount($start, $end, true)->sum('queryAmount');
$amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount');
return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
}
@@ -202,30 +195,6 @@ class JsonController extends Controller
}
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
public function setSharedReports()
{
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$new = !$pref->data;
Preferences::set('showSharedReports', $new);
return Response::json(['value' => $new]);
}
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showSharedReports()
{
$pref = Preferences::get('showSharedReports', false);
return Response::json(['value' => $pref->data]);
}
/**
* Returns a JSON list of all beneficiaries.
*

View File

@@ -4,7 +4,6 @@ use Amount;
use Carbon\Carbon;
use Config;
use ExpandedForm;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -18,6 +17,9 @@ use URL;
use View;
/**
*
* @SuppressWarnings(PHPMD.TooManyMethods)
*
* Class PiggyBankController
*
* @package FireflyIII\Http\Controllers
@@ -26,12 +28,12 @@ class PiggyBankController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Piggy banks');
View::share('title', trans('firefly.piggyBanks'));
View::share('mainTitleIcon', 'fa-sort-amount-asc');
}
@@ -45,7 +47,8 @@ class PiggyBankController extends Controller
*/
public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{
$leftOnAccount = $repository->leftOnAccount($piggyBank->account);
$date = Session::get('end', Carbon::now()->endOfMonth());
$leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date);
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
$leftToSave = $piggyBank->targetamount - $savedSoFar;
$maxAmount = min($leftOnAccount, $leftToSave);
@@ -71,6 +74,8 @@ class PiggyBankController extends Controller
Session::put('piggy-banks.create.url', URL::previous());
}
Session::forget('piggy-banks.create.fromStore');
Session::flash('gaEventCategory', 'piggy-banks');
Session::flash('gaEventAction', 'create');
return view('piggy-banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon'));
}
@@ -82,10 +87,12 @@ class PiggyBankController extends Controller
*/
public function delete(PiggyBank $piggyBank)
{
$subTitle = 'Delete "' . e($piggyBank->name) . '"';
$subTitle = trans('firefly.delete_piggy_bank', ['name' => $piggyBank->name]);
// put previous url in session
Session::put('piggy-banks.delete.url', URL::previous());
Session::flash('gaEventCategory', 'piggy-banks');
Session::flash('gaEventAction', 'delete');
return view('piggy-banks.delete', compact('piggyBank', 'subTitle'));
}
@@ -117,7 +124,7 @@ class PiggyBankController extends Controller
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"';
$subTitle = trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
$subTitleIcon = 'fa-pencil';
/*
@@ -130,13 +137,15 @@ class PiggyBankController extends Controller
$targetDate = $targetDate->format('Y-m-d');
}
$preFilled = ['name' => $piggyBank->name,
'account_id' => $piggyBank->account_id,
'targetamount' => $piggyBank->targetamount,
'targetdate' => $targetDate,
'reminder' => $piggyBank->reminder,
'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false
'account_id' => $piggyBank->account_id,
'targetamount' => $piggyBank->targetamount,
'targetdate' => $targetDate,
'reminder' => $piggyBank->reminder,
'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false
];
Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'piggy-banks');
Session::flash('gaEventAction', 'edit');
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('piggy-banks.edit.fromUpdate') !== true) {
@@ -157,6 +166,7 @@ class PiggyBankController extends Controller
{
/** @var Collection $piggyBanks */
$piggyBanks = $piggyRepository->getPiggyBanks();
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = [];
/** @var PiggyBank $piggyBank */
@@ -172,8 +182,8 @@ class PiggyBankController extends Controller
if (!isset($accounts[$account->id])) {
$accounts[$account->id] = [
'name' => $account->name,
'balance' => Steam::balance($account, null, true),
'leftForPiggyBanks' => $repository->leftOnAccount($account),
'balance' => Steam::balance($account, $end, true),
'leftForPiggyBanks' => $repository->leftOnAccount($account, $end),
'sumOfSaved' => $piggyBank->savedSoFar,
'sumOfTargets' => floatval($piggyBank->targetamount),
'leftToSave' => $piggyBank->leftToSave
@@ -215,7 +225,8 @@ class PiggyBankController extends Controller
public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank)
{
$amount = round(floatval(Input::get('amount')), 2);
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account);
$date = Session::get('end', Carbon::now()->endOfMonth());
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account, $date);
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
$leftToSave = $piggyBank->targetamount - $savedSoFar;
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);
@@ -228,11 +239,6 @@ class PiggyBankController extends Controller
// create event
$repository->createEvent($piggyBank, $amount);
/*
* Create event!
*/
//Event::fire('piggy_bank.addMoney', [$piggyBank, $amount]); // new and used.
Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
} else {
Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
@@ -360,7 +366,7 @@ class PiggyBankController extends Controller
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('piggy-banks.edit.fromUpdate', true);
return Redirect::route('piggy-banks.edit', $piggyBank->id);
return Redirect::route('piggy-banks.edit', [$piggyBank->id]);
}

View File

@@ -1,5 +1,6 @@
<?php namespace FireflyIII\Http\Controllers;
use Config;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
@@ -16,12 +17,12 @@ class PreferencesController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Preferences');
View::share('title', trans('firefly.preferences'));
View::share('mainTitleIcon', 'fa-gear');
}
@@ -37,9 +38,10 @@ class PreferencesController extends Controller
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$language = Preferences::get('language', 'en')->data;
$budgetMaximum = $budgetMax->data;
return view('preferences.index', compact('budgetMaximum', 'accounts', 'frontPageAccounts', 'viewRange'));
return view('preferences.index', compact('budgetMaximum', 'language', 'accounts', 'frontPageAccounts', 'viewRange'));
}
/**
@@ -49,10 +51,12 @@ class PreferencesController extends Controller
{
// front page accounts
$frontPageAccounts = [];
foreach (Input::get('frontPageAccounts') as $id) {
$frontPageAccounts[] = intval($id);
if (is_array(Input::get('frontPageAccounts'))) {
foreach (Input::get('frontPageAccounts') as $id) {
$frontPageAccounts[] = intval($id);
}
Preferences::set('frontPageAccounts', $frontPageAccounts);
}
Preferences::set('frontPageAccounts', $frontPageAccounts);
// view range:
Preferences::set('viewRange', Input::get('viewRange'));
@@ -65,6 +69,12 @@ class PreferencesController extends Controller
$budgetMaximum = intval(Input::get('budgetMaximum'));
Preferences::set('budgetMaximum', $budgetMaximum);
// language:
$lang = Input::get('language');
if (in_array($lang, array_keys(Config::get('firefly.lang')))) {
Preferences::set('language', $lang);
}
Session::flash('success', 'Preferences saved!');

View File

@@ -109,6 +109,8 @@ class ProfileController extends Controller
// DELETE!
Auth::user()->delete();
Session::flush();
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'delete-account');
return Redirect::route('index');
}

View File

@@ -31,7 +31,7 @@ class ReminderController extends Controller
];
Session::flash('_old_input', $data);
return Redirect::route('transactions.create', 'transfer');
return Redirect::route('transactions.create', ['transfer']);
}
/**

View File

@@ -2,13 +2,9 @@
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionJournal;
use Preferences;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Session;
use Steam;
use View;
/**
@@ -21,311 +17,142 @@ class ReportController extends Controller
/** @var ReportHelperInterface */
protected $helper;
/** @var ReportQueryInterface */
protected $query;
/**
* @codeCoverageIgnore
*
* @param ReportHelperInterface $helper
* @param ReportQueryInterface $query
*/
public function __construct(ReportHelperInterface $helper, ReportQueryInterface $query)
public function __construct(ReportHelperInterface $helper)
{
$this->query = $query;
parent::__construct();
$this->helper = $helper;
View::share('title', 'Reports');
View::share('title', trans('firefly.reports'));
View::share('mainTitleIcon', 'fa-line-chart');
}
/**
* @param string $year
* @param string $month
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function budget($year = '2014', $month = '1')
{
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Budget report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
// should show shared reports?
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$accountAmounts = []; // array with sums of spent amounts on each account.
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports); // all accounts and some data.
foreach ($accounts as $account) {
$budgets = $this->query->getBudgetSummary($account, $start, $end);// get budget summary for this account:
$balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end);
$accountAmounts[$account->id] = $balancedAmount;
// balance out the transactions (see transaction groups & tags) ^^
// array with budget information for each account:
$array = [];
// should always hide account
$hide = true;
// loop all budgets
/** @var \FireflyIII\Models\Budget $budget */
foreach ($budgets as $budget) {
$id = intval($budget->id);
$data = $budget->toArray();
$array[$id] = $data;
// no longer hide account if any budget has money in it.
if (floatval($data['queryAmount']) != 0) {
$hide = false;
}
$accountAmounts[$account->id] += $data['queryAmount'];
}
$account->hide = $hide;
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
}
/**
* Start getBudgetsForMonth DONE
*/
$budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports);
/**
* End getBudgetsForMonth DONE
*/
return view('reports.budget', compact('subTitle', 'accountAmounts', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets'));
}
/**
* @return View
* @internal param ReportHelperInterface $helper
*
*/
public function index()
public function index(AccountRepositoryInterface $repository)
{
$start = Session::get('first');
$months = $this->helper->listOfMonths($start);
$years = $this->helper->listOfYears($start);
$title = 'Reports';
$mainTitleIcon = 'fa-line-chart';
$start = Session::get('first');
$months = $this->helper->listOfMonths($start);
return view('reports.index', compact('years', 'months', 'title', 'mainTitleIcon'));
}
// does the user have shared accounts?
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
$hasShared = false;
/**
* @param Account $account
* @param string $year
* @param string $month
*
* @return \Illuminate\View\View
*/
public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1')
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$journals = $this->query->balancedTransactionsList($account, $start, $end);
return view('reports.modal-journal-list', compact('journals'));
}
/**
* @param Account $account
* @param string $year
* @param string $month
*
* @return View
* @internal param ReportQueryInterface $query
*
*/
public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1')
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$set = $this->query->getTransactionsWithoutBudget($account, $start, $end);
$journals = $set->filter(
function (TransactionJournal $journal) {
$count = $journal->transactiongroups()->where('relation', 'balance')->count();
if ($count == 0) {
return $journal;
}
return null;
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->getMeta('accountRole') == 'sharedAsset') {
$hasShared = true;
}
);
}
return view('reports.modal-journal-list', compact('journals'));
}
/**
* @param Account $account
* @param string $year
* @param string $month
*
* @return \Illuminate\View\View
*/
public function modalNoBudget(Account $account, $year = '2014', $month = '1')
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$journals = $this->query->getTransactionsWithoutBudget($account, $start, $end);
return view('reports.modal-journal-list', compact('journals'));
return view('reports.index', compact('months', 'hasShared'));
}
/**
* @param string $year
* @param string $month
*
* @param bool $shared
*
* @return \Illuminate\View\View
*/
public function month($year = '2014', $month = '1')
public function month($year = '2014', $month = '1', $shared = false)
{
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$displaySum = true; // to show sums in report.
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$start = new Carbon($year . '-' . $month . '-01');
$subTitle = trans('firefly.reportForMonth', ['date' => $start->formatLocalized($this->monthFormat)]);
$subTitleIcon = 'fa-calendar';
$end = clone $start;
$incomeTopLength = 8;
$expenseTopLength = 8;
if ($shared == 'shared') {
$shared = true;
$subTitle = trans('firefly.reportForMonthShared', ['date' => $start->formatLocalized($this->monthFormat)]);
}
/**
*
* get income for month (date)
*
*/
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
/**
* Start getIncomeForMonth DONE
*/
$income = $this->query->incomeByPeriod($start, $end, $showSharedReports);
/**
* End getIncomeForMonth DONE
*/
/**
* Start getExpenseGroupedForMonth DONE
*/
$set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports);
$accounts = $this->helper->getAccountReport($start, $end, $shared);
$incomes = $this->helper->getIncomeReport($start, $end, $shared);
$expenses = $this->helper->getExpenseReport($start, $end, $shared);
$budgets = $this->helper->getBudgetReport($start, $end, $shared);
$categories = $this->helper->getCategoryReport($start, $end, $shared);
$balance = $this->helper->getBalanceReport($start, $end, $shared);
$bills = $this->helper->getBillReport($start, $end, $shared);
$expenses = Steam::makeArray($set);
$expenses = Steam::sortArray($expenses);
$expenses = Steam::limitArray($expenses, 10);
/**
* End getExpenseGroupedForMonth DONE
*/
/**
* Start getBudgetsForMonth DONE
*/
$budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports);
/**
* End getBudgetsForMonth DONE
*/
/**
* Start getCategoriesForMonth DONE
*/
// all categories.
$result = $this->query->journalsByCategory($start, $end);
$categories = Steam::makeArray($result);
// all transfers
if ($showSharedReports === false) {
$result = $this->query->sharedExpensesByCategory($start, $end);
$transfers = Steam::makeArray($result);
$merged = Steam::mergeArrays($categories, $transfers);
} else {
$merged = $categories;
}
// sort.
$sorted = Steam::sortNegativeArray($merged);
// limit to $limit:
$categories = Steam::limitArray($sorted, 10);
/**
* End getCategoriesForMonth DONE
*/
/**
* Start getAccountsForMonth
*/
$list = $this->query->accountList($showSharedReports);
$accounts = [];
/** @var Account $account */
foreach ($list as $account) {
$id = intval($account->id);
/** @noinspection PhpParamsInspection */
$accounts[$id] = [
'name' => $account->name,
'startBalance' => Steam::balance($account, $start),
'endBalance' => Steam::balance($account, $end)
];
$accounts[$id]['difference'] = $accounts[$id]['endBalance'] - $accounts[$id]['startBalance'];
}
/**
* End getAccountsForMonth
*/
Session::flash('gaEventCategory', 'report');
Session::flash('gaEventAction', 'month');
Session::flash('gaEventLabel', $start->format('F Y'));
return view(
'reports.month',
compact(
'income', 'expenses', 'budgets', 'accounts', 'categories',
'date', 'subTitle', 'displaySum', 'subTitleIcon'
'start', 'shared',
'subTitle', 'subTitleIcon',
'accounts',
'incomes', 'incomeTopLength',
'expenses', 'expenseTopLength',
'budgets', 'balance',
'categories',
'bills'
)
);
}
/**
* @param $year
* @param $year
*
* @param bool $shared
*
* @return $this
*/
public function year($year)
public function year($year, $shared = false)
{
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$date = new Carbon('01-01-' . $year);
$end = clone $date;
$start = new Carbon('01-01-' . $year);
$end = clone $start;
$subTitle = trans('firefly.reportForYear', ['year' => $year]);
$subTitleIcon = 'fa-bar-chart';
$incomeTopLength = 8;
$expenseTopLength = 8;
if ($shared == 'shared') {
$shared = true;
$subTitle = trans('firefly.reportForYearShared', ['year' => $year]);
}
$end->endOfYear();
$title = 'Reports';
$subTitle = $year;
$subTitleIcon = 'fa-bar-chart';
$mainTitleIcon = 'fa-line-chart';
$balances = $this->helper->yearBalanceReport($date, $showSharedReports);
$groupedIncomes = $this->query->journalsByRevenueAccount($date, $end, $showSharedReports);
$groupedExpenses = $this->query->journalsByExpenseAccount($date, $end, $showSharedReports);
$accounts = $this->helper->getAccountReport($start, $end, $shared);
$incomes = $this->helper->getIncomeReport($start, $end, $shared);
$expenses = $this->helper->getExpenseReport($start, $end, $shared);
Session::flash('gaEventCategory', 'report');
Session::flash('gaEventAction', 'year');
Session::flash('gaEventLabel', $start->format('Y'));
return view(
'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon')
'reports.year',
compact(
'start', // the date for this report.
'shared', // is a shared report?
'accounts', // all accounts
'incomes', 'expenses', // expenses and incomes.
'subTitle', 'subTitleIcon', // subtitle and subtitle icon.
'incomeTopLength', // length of income top X
'expenseTopLength' // length of expense top X.
)
);
}

View File

@@ -31,8 +31,11 @@ use View;
*/
class TagController extends Controller
{
public $tagOptions = [];
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
@@ -40,12 +43,12 @@ class TagController extends Controller
View::share('title', 'Tags');
View::share('mainTitleIcon', 'fa-tags');
View::share('hideTags', true);
$tagOptions = [
$this->tagOptions = [
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
View::share('tagOptions', $tagOptions);
View::share('tagOptions', $this->tagOptions);
}
/**
@@ -67,6 +70,8 @@ class TagController extends Controller
Session::put('tags.create.url', URL::previous());
}
Session::forget('tags.create.fromStore');
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'create');
return view('tags.create', compact('subTitle', 'subTitleIcon'));
}
@@ -78,10 +83,12 @@ class TagController extends Controller
*/
public function delete(Tag $tag)
{
$subTitle = 'Delete "' . e($tag->tag) . '"';
$subTitle = trans('firefly.delete_tag', ['name' => $tag->tag]);
// put previous url in session
Session::put('tags.delete.url', URL::previous());
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'delete');
return view('tags.delete', compact('tag', 'subTitle'));
}
@@ -104,11 +111,13 @@ class TagController extends Controller
}
/**
* @param Tag $tag
* @param Tag $tag
*
* @return View
* @param TagRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function edit(Tag $tag)
public function edit(Tag $tag, TagRepositoryInterface $repository)
{
$subTitle = 'Edit tag "' . e($tag->tag) . '"';
$subTitleIcon = 'fa-tag';
@@ -116,67 +125,16 @@ class TagController extends Controller
/*
* Default tag options (again)
*/
$tagOptions = [
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
$tagOptions = $this->tagOptions;
/*
* Can this tag become another type?
*/
$allowToAdvancePayment = true;
$allowToBalancingAct = true;
/*
* If this tag is a balancing act, and it contains transfers, it cannot be
* changes to an advancePayment.
*/
if ($tag->tagMode == 'balancingAct') {
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Transfer') {
$allowToAdvancePayment = false;
}
}
}
/*
* If this tag contains more than one expenses, it cannot become an advance payment.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Withdrawal') {
$count++;
}
}
if ($count > 1) {
$allowToAdvancePayment = false;
}
/*
* If has more than two transactions already, cannot become a balancing act:
*/
if ($tag->transactionjournals->count() > 2) {
$allowToBalancingAct = false;
}
/*
* If any transaction is a deposit, cannot become a balancing act.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Deposit') {
$count++;
}
}
if ($count > 0) {
$allowToBalancingAct = false;
}
$allowAdvance = $repository->tagAllowAdvance($tag);
$allowToBalancingAct = $repository->tagAllowBalancing($tag);
// edit tag options:
if ($allowToAdvancePayment === false) {
if ($allowAdvance === false) {
unset($tagOptions['advancePayment']);
}
if ($allowToBalancingAct === false) {
@@ -189,6 +147,8 @@ class TagController extends Controller
Session::put('tags.edit.url', URL::previous());
}
Session::forget('tags.edit.fromUpdate');
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'edit');
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions'));
}
@@ -204,7 +164,7 @@ class TagController extends Controller
$state = $state == 'true' ? true : false;
Preferences::set('hideTagHelp', $state);
return Response::json(true);
return Response::json([true]);
}
/**
@@ -240,7 +200,7 @@ class TagController extends Controller
*
* @param TagRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function store(TagFormRequest $request, TagRepositoryInterface $repository)
{
@@ -284,14 +244,14 @@ class TagController extends Controller
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag)
{
if (Input::get('setTag') == 'true') {
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
$latitude = $request->get('latitude');
$longitude = $request->get('longitude');
$zoomLevel = $request->get('zoomLevel');
} else {
$latitude = null;
$longitude = null;
@@ -316,7 +276,7 @@ class TagController extends Controller
// set value so edit routine will not overwrite URL:
Session::put('tags.edit.fromUpdate', true);
return Redirect::route('tags.edit', $tag->id)->withInput(['return_to_edit' => 1]);
return Redirect::route('tags.edit', [$tag->id])->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.

View File

@@ -5,7 +5,6 @@ use Carbon\Carbon;
use ExpandedForm;
use FireflyIII\Events\JournalCreated;
use FireflyIII\Events\JournalSaved;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
@@ -26,11 +25,12 @@ use View;
class TransactionController extends Controller
{
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Transactions');
View::share('title', trans('firefly.transactions'));
View::share('mainTitleIcon', 'fa-repeat');
}
@@ -38,23 +38,21 @@ class TransactionController extends Controller
* @param AccountRepositoryInterface $repository
* @param string $what
*
* @return View
* @return \Illuminate\View\View
*/
public function create(AccountRepositoryInterface $repository, $what = 'deposit')
{
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$budgets[0] = trans('form.noBudget');
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = '(no piggy bank)';
$piggies[0] = trans('form.noPiggybank');
$preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
$respondTo = ['account_id', 'account_from_id'];
$subTitle = 'Add a new ' . e($what);
$subTitle = trans('form.add_new_' . $what);
foreach ($respondTo as $r) {
if (!is_null(Input::get($r))) {
$preFilled[$r] = Input::get($r);
}
$preFilled[$r] = Input::get($r);
}
Session::put('preFilled', $preFilled);
@@ -63,6 +61,8 @@ class TransactionController extends Controller
Session::put('transactions.create.url', URL::previous());
}
Session::forget('transactions.create.fromStore');
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'create-' . $what);
asort($piggies);
@@ -75,15 +75,17 @@ class TransactionController extends Controller
*
* @param TransactionJournal $journal
*
* @return $this
* @return \Illuminate\View\View
*/
public function delete(TransactionJournal $journal)
{
$type = strtolower($journal->transactionType->type);
$subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"';
$subTitle = trans('firefly.delete_' . $type, ['description' => $journal->description]);
// put previous url in session
Session::put('transactions.delete.url', URL::previous());
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'delete-' . $type);
return view('transactions.delete', compact('journal', 'subTitle'));
@@ -116,13 +118,14 @@ class TransactionController extends Controller
*/
public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal)
{
$what = strtolower($journal->transactiontype->type);
$what = strtolower($journal->transactionType->type);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$budgets[0] = trans('form.noBudget');
$transactions = $journal->transactions()->orderBy('amount', 'DESC')->get();
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = '(no piggy bank)';
$piggies[0] = trans('form.noPiggybank');
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
$preFilled = [
'date' => $journal->date->format('Y-m-d'),
'category' => '',
@@ -150,14 +153,16 @@ class TransactionController extends Controller
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
}
$preFilled['amount'] = $journal->amount;
$preFilled['account_id'] = $journal->assetAccount->id;
$preFilled['amount'] = $journal->actual_amount;
$preFilled['account_id'] = $journal->asset_account->id;
$preFilled['expense_account'] = $transactions[0]->account->name;
$preFilled['revenue_account'] = $transactions[1]->account->name;
$preFilled['account_from_id'] = $transactions[1]->account->id;
$preFilled['account_to_id'] = $transactions[0]->account->id;
Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'edit-' . $what);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('transactions.edit.fromUpdate') !== true) {
@@ -173,7 +178,7 @@ class TransactionController extends Controller
* @param JournalRepositoryInterface $repository
* @param $what
*
* @return View
* @return \Illuminate\View\View
*/
public function index(JournalRepositoryInterface $repository, $what)
{
@@ -182,19 +187,19 @@ class TransactionController extends Controller
case 'expenses':
case 'withdrawal':
$subTitleIcon = 'fa-long-arrow-left';
$subTitle = 'Expenses';
$subTitle = trans('firefly.expenses');
$types = ['Withdrawal'];
break;
case 'revenue':
case 'deposit':
$subTitleIcon = 'fa-long-arrow-right';
$subTitle = 'Revenue, income and deposits';
$subTitle = trans('firefly.income');
$types = ['Deposit'];
break;
case 'transfer':
case 'transfers':
$subTitleIcon = 'fa-exchange';
$subTitle = 'Transfers';
$subTitle = trans('firefly.transfers');
$types = ['Transfer'];
break;
}
@@ -231,7 +236,7 @@ class TransactionController extends Controller
}
}
return Response::json(true);
return Response::json([true]);
}
@@ -239,17 +244,17 @@ class TransactionController extends Controller
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return $this
* @return \Illuminate\View\View
*/
public function show(JournalRepositoryInterface $repository, TransactionJournal $journal)
{
$journal->transactions->each(
function (Transaction $t) use ($journal, $repository) {
function(Transaction $t) use ($journal, $repository) {
$t->before = $repository->getAmountBefore($journal, $t);
$t->after = $t->before + $t->amount;
}
);
$subTitle = e($journal->transactiontype->type) . ' "' . e($journal->description) . '"';
$subTitle = trans('firefly.' . $journal->transactionType->type) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal', 'subTitle'));
}
@@ -258,7 +263,7 @@ class TransactionController extends Controller
* @param JournalFormRequest $request
* @param JournalRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository)
{
@@ -269,7 +274,9 @@ class TransactionController extends Controller
// rescan journal, UpdateJournalConnection
event(new JournalSaved($journal));
// ConnectJournalToPiggyBank
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
if ($journal->transactionType->type == 'Transfer' && intval($request->get('piggy_bank_id')) > 0) {
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
}
$repository->deactivateReminder($request->get('reminder_id'));
@@ -279,7 +286,7 @@ class TransactionController extends Controller
// set value so create routine will not overwrite URL:
Session::put('transactions.create.fromStore', true);
return Redirect::route('transactions.create', $request->input('what'))->withInput();
return Redirect::route('transactions.create', [$request->input('what')])->withInput();
}
// redirect to previous URL.
@@ -293,7 +300,7 @@ class TransactionController extends Controller
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{
@@ -310,7 +317,7 @@ class TransactionController extends Controller
// set value so edit routine will not overwrite URL:
Session::put('transactions.edit.fromUpdate', true);
return Redirect::route('transactions.edit', $journal->id)->withInput(['return_to_edit' => 1]);
return Redirect::route('transactions.edit', [$journal->id])->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.

View File

@@ -37,8 +37,8 @@ class Kernel extends HttpKernel
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated',
'range' => 'FireflyIII\Http\Middleware\Range',
'cleanup' => 'FireflyIII\Http\Middleware\Cleanup',
'reminders' => 'FireflyIII\Http\Middleware\Reminders',
'piggybanks' => 'FireflyIII\Http\Middleware\PiggyBanks',
];

View File

@@ -1,9 +1,12 @@
<?php namespace FireflyIII\Http\Middleware;
use App;
use Closure;
use Config;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Preferences;
use Carbon\Carbon;
/**
* Class Authenticate
*
@@ -48,6 +51,12 @@ class Authenticate
return redirect()->guest('auth/login');
}
}
// if logged in, set user language:
$pref = Preferences::get('language', 'en');
App::setLocale($pref->data);
Carbon::setLocale($pref->data);
setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data));
return $next($request);
}

View File

@@ -0,0 +1,223 @@
<?php namespace FireflyIII\Http\Middleware;
use Closure;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Session;
/**
* Class Cleanup
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class Cleanup
{
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* @param Guard $auth
*
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($this->auth->guest()) {
return response('Unauthorized.', 401);
}
$count = -1;
bcscale(0);
if (env('RUNCLEANUP') == 'true') {
$count = 0;
$count = bcadd($count, $this->encryptAccountAndBills());
$count = bcadd($count, $this->encryptBudgetsAndCategories());
$count = bcadd($count, $this->encryptPiggiesAndJournals());
$count = bcadd($count, $this->encryptRemindersAndPreferences());
}
if ($count == 0) {
Session::flash('warning', 'Please open the .env file and change RUNCLEANUP=true to RUNCLEANUP=false');
}
return $next($request);
}
/**
* @return int
*/
protected function encryptAccountAndBills()
{
$count = 0;
// encrypt account name
$set = Account::where('encrypted', 0)->take(5)->get();
/** @var Account $entry */
foreach ($set as $entry) {
$count++;
$name = $entry->name;
$entry->name = $name;
$entry->save();
}
unset($set, $entry, $name);
// encrypt bill name
$set = Bill::where('name_encrypted', 0)->take(5)->get();
/** @var Bill $entry */
foreach ($set as $entry) {
$count++;
$name = $entry->name;
$entry->name = $name;
$entry->save();
}
unset($set, $entry, $name);
// encrypt bill match
$set = Bill::where('match_encrypted', 0)->take(5)->get();
/** @var Bill $entry */
foreach ($set as $entry) {
$match = $entry->match;
$entry->match = $match;
$entry->save();
}
unset($set, $entry, $match);
return $count;
}
/**
* @return int
*/
protected function encryptBudgetsAndCategories()
{
$count = 0;
// encrypt budget name
$set = Budget::where('encrypted', 0)->take(5)->get();
/** @var Budget $entry */
foreach ($set as $entry) {
$count++;
$name = $entry->name;
$entry->name = $name;
$entry->save();
}
unset($set, $entry, $name);
// encrypt category name
$set = Category::where('encrypted', 0)->take(5)->get();
/** @var Category $entry */
foreach ($set as $entry) {
$count++;
$name = $entry->name;
$entry->name = $name;
$entry->save();
}
unset($set, $entry, $name);
return $count;
}
/**
* @return int
*/
protected function encryptPiggiesAndJournals()
{
$count = 0;
// encrypt piggy bank name
$set = PiggyBank::where('encrypted', 0)->take(5)->get();
/** @var PiggyBank $entry */
foreach ($set as $entry) {
$count++;
$name = $entry->name;
$entry->name = $name;
$entry->save();
}
unset($set, $entry, $name);
// encrypt transaction journal description
$set = TransactionJournal::where('encrypted', 0)->take(5)->get();
/** @var TransactionJournal $entry */
foreach ($set as $entry) {
$count++;
$description = $entry->description;
$entry->description = $description;
$entry->save();
}
unset($set, $entry, $description);
return $count;
}
/**
* @return int
*/
protected function encryptRemindersAndPreferences()
{
$count = 0;
// encrypt reminder metadata
$set = Reminder::where('encrypted', 0)->take(5)->get();
/** @var Reminder $entry */
foreach ($set as $entry) {
$count++;
$metadata = $entry->metadata;
$entry->metadata = $metadata;
$entry->save();
}
unset($set, $entry, $metadata);
//encrypt preference name
$set = Preference::whereNull('name_encrypted')->take(5)->get();
/** @var Preference $entry */
foreach ($set as $entry) {
$count++;
$name = $entry->name;
$entry->name = $name;
$entry->save();
}
unset($set, $entry, $name);
//encrypt preference data
$set = Preference::whereNull('data_encrypted')->take(5)->get();
/** @var Preference $entry */
foreach ($set as $entry) {
$count++;
$data = $entry->data;
$entry->data = $data;
$entry->save();
}
unset($set, $entry, $data);
return $count;
}
}

View File

@@ -1,72 +0,0 @@
<?php
namespace FireflyIII\Http\Middleware;
use App;
use Closure;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
/**
* Class PiggyBanks
*
* @package FireflyIII\Http\Middleware
*/
class PiggyBanks
{
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* @param Guard $auth
*
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($this->auth->check() && !$request->isXmlHttpRequest() && App::environment() != 'testing') {
// get piggy banks without a repetition:
/** @var Collection $set */
$set = $this->auth->user()->piggybanks()
->leftJoin('piggy_bank_repetitions', 'piggy_banks.id', '=', 'piggy_bank_repetitions.piggy_bank_id')
->whereNull('piggy_bank_repetitions.id')
->get(['piggy_banks.id', 'piggy_banks.startdate', 'piggy_banks.targetdate']);
if ($set->count() > 0) {
/** @var PiggyBank $partialPiggy */
foreach ($set as $partialPiggy) {
$repetition = new PiggyBankRepetition;
$repetition->piggyBank()->associate($partialPiggy);
$repetition->startdate = is_null($partialPiggy->startdate) ? null : $partialPiggy->startdate;
$repetition->targetdate = is_null($partialPiggy->targetdate) ? null : $partialPiggy->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
}
unset($partialPiggy, $set, $repetition);
}
return $next($request);
}
}

View File

@@ -43,29 +43,27 @@ class Range
*
* @param \Illuminate\Http\Request $request
* @param \Closure $theNext
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return mixed
*/
public function handle(Request $request, Closure $theNext)
{
if ($this->auth->check() && App::environment() != 'testing') {
if ($this->auth->check()) {
// ignore preference. set the range to be the current month:
if (!Session::has('start') && !Session::has('end')) {
/** @var \FireflyIII\Models\Preference $viewRange */
$viewRange = Preferences::get('viewRange', '1M');
$viewRange = Preferences::get('viewRange', '1M')->data;
$start = new Carbon;
$start = Navigation::updateStartDate($viewRange->data, $start);
$end = Navigation::updateEndDate($viewRange->data, $start);
$start = Navigation::updateStartDate($viewRange, $start);
$end = Navigation::updateEndDate($viewRange, $start);
Session::put('start', $start);
Session::put('end', $end);
}
if (!Session::has('first')) {
/**
* Get helper thing.
*/
/** @var \FireflyIII\Repositories\Journal\JournalRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Journal\JournalRepositoryInterface');
$journal = $repository->first();
@@ -75,16 +73,12 @@ class Range
Session::put('first', Carbon::now()->startOfYear());
}
}
// set current / next / prev month.
$current = Carbon::now()->format('F Y');
$next = Carbon::now()->endOfMonth()->addDay()->format('F Y');
$prev = Carbon::now()->startOfMonth()->subDay()->format('F Y');
$current = Carbon::now()->formatLocalized('%B %Y');
$next = Carbon::now()->endOfMonth()->addDay()->formatLocalized('%B %Y');
$prev = Carbon::now()->startOfMonth()->subDay()->formatLocalized('%B %Y');
View::share('currentMonthName', $current);
View::share('previousMonthName', $prev);
View::share('nextMonthName', $next);
}
return $theNext($request);

View File

@@ -7,6 +7,7 @@ use Carbon\Carbon;
use Closure;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use View;
@@ -46,43 +47,35 @@ class Reminders
*/
public function handle(Request $request, Closure $next)
{
if ($this->auth->check() && !$request->isXmlHttpRequest() && App::environment() != 'testing') {
if ($this->auth->check() && !$request->isXmlHttpRequest()) {
// do reminders stuff.
$piggyBanks = $this->auth->user()->piggyBanks()->where('remind_me', 1)->get();
$today = new Carbon;
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */
$helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
$reminders = [];
if ($this->auth->user() instanceof User) {
$piggyBanks = $this->auth->user()->piggyBanks()->where('remind_me', 1)->get();
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */
$helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
/** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) {
$ranges = $helper->getReminderRanges($piggyBank);
/** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) {
$helper->createReminders($piggyBank, new Carbon);
}
// delete invalid reminders
// this is a construction SQLITE cannot handle :(
if (env('DB_CONNECTION') != 'sqlite') {
Reminder::whereUserId($this->auth->user()->id)
->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')
->whereNull('piggy_banks.id')
->delete();
}
foreach ($ranges as $range) {
if ($today < $range['end'] && $today > $range['start']) {
// create a reminder here!
$helper->createReminder($piggyBank, $range['start'], $range['end']);
// stop looping, we're done.
break;
// get and list active reminders:
$reminders = $this->auth->user()->reminders()->today()->get();
$reminders->each(
function (Reminder $reminder) use ($helper) {
$reminder->description = $helper->getReminderText($reminder);
}
}
);
}
// delete invalid reminders
$set = $this->auth->user()->reminders()->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->get(
['reminders.id']
);
foreach ($set as $reminder) {
$reminder->delete();
}
// get and list active reminders:
$reminders = $this->auth->user()->reminders()->today()->get();
$reminders->each(
function (Reminder $reminder) use ($helper) {
$reminder->description = $helper->getReminderText($reminder);
}
);
View::share('reminders', $reminders);
}

View File

@@ -2,6 +2,7 @@
namespace FireflyIII\Http\Requests;
use App;
use Auth;
use Carbon\Carbon;
use Exception;
@@ -50,12 +51,11 @@ class JournalFormRequest extends Request
/**
* @return array
* @throws Exception
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function rules()
{
// can we switch on the "what"?
$what = Input::get('what');
$what = Input::get('what');
$rules = [
'description' => 'required|min:1,max:255',
'what' => 'required|in:withdrawal,deposit,transfer',
@@ -74,8 +74,6 @@ class JournalFormRequest extends Request
if (intval(Input::get('budget_id')) != 0) {
$rules['budget_id'] = 'exists:budgets,id|belongsToUser:budgets';
}
break;
case 'deposit':
$rules['category'] = 'between:1,255';
@@ -88,12 +86,10 @@ class JournalFormRequest extends Request
$rules['category'] = 'between:1,255';
break;
default:
throw new Exception('Cannot handle ' . $what);
App::abort(500, 'Cannot handle ' . $what);
break;
}
return $rules;
}
}

View File

@@ -1,11 +1,4 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 27/04/15
* Time: 12:50
*/
namespace FireflyIII\Http\Requests;
use Auth;
@@ -48,6 +41,7 @@ class TagFormRequest extends Request
'date' => 'date',
'latitude' => 'numeric|min:-90|max:90',
'longitude' => 'numeric|min:-90|max:90',
'zoomLevel' => 'numeric|min:0|max:80',
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
];
}

View File

@@ -1,7 +1,6 @@
<?php
use Carbon\Carbon;
use DaveJamesMiller\Breadcrumbs\Generator;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
@@ -18,107 +17,104 @@ use FireflyIII\Models\TransactionJournal;
*/
Breadcrumbs::register(
'home',
function (Generator $breadcrumbs) {
function(Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
$breadcrumbs->push(trans('breadcrumbs.home'), route('index'));
}
);
Breadcrumbs::register(
'index',
function (Generator $breadcrumbs) {
function(Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
$breadcrumbs->push(trans('breadcrumbs.home'), route('index'));
}
);
//trans('breadcrumbs.')
// accounts
Breadcrumbs::register(
'accounts.index', function (Generator $breadcrumbs, $what) {
'accounts.index', function(Generator $breadcrumbs, $what) {
$breadcrumbs->parent('home');
$breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what));
}
);
Breadcrumbs::register(
'accounts.show', function (Generator $breadcrumbs, Account $account) {
switch ($account->accountType->type) {
default:
throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"');
break;
case 'Default account':
case 'Asset account':
$what = 'asset';
break;
case 'Cash account':
$what = 'cash';
break;
case 'Expense account':
case 'Beneficiary account':
$what = 'expense';
break;
case 'Revenue account':
$what = 'revenue';
break;
}
$breadcrumbs->parent('accounts.index', $what);
$breadcrumbs->push(e($account->name), route('accounts.show', $account->id));
}
);
Breadcrumbs::register(
'accounts.delete', function (Generator $breadcrumbs, Account $account) {
$breadcrumbs->parent('accounts.show', $account);
$breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id));
$breadcrumbs->push(trans('breadcrumbs.' . strtolower(e($what)) . '_accounts'), route('accounts.index', [$what]));
}
);
Breadcrumbs::register(
'accounts.edit', function (Generator $breadcrumbs, Account $account) {
'accounts.create', function(Generator $breadcrumbs, $what) {
$breadcrumbs->parent('accounts.index', $what);
$breadcrumbs->push(trans('breadcrumbs.new_' . strtolower(e($what)) . '_account'), route('accounts.create', [$what]));
}
);
Breadcrumbs::register(
'accounts.show', function(Generator $breadcrumbs, Account $account) {
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$breadcrumbs->parent('accounts.index', $what);
$breadcrumbs->push(e($account->name), route('accounts.show', [$account->id]));
}
);
Breadcrumbs::register(
'accounts.delete', function(Generator $breadcrumbs, Account $account) {
$breadcrumbs->parent('accounts.show', $account);
$breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id));
$breadcrumbs->push(trans('breadcrumbs.delete_account', ['name' => e($account->name)]), route('accounts.delete', [$account->id]));
}
);
Breadcrumbs::register(
'accounts.edit', function(Generator $breadcrumbs, Account $account) {
$breadcrumbs->parent('accounts.show', $account);
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$breadcrumbs->push(trans('breadcrumbs.edit_' . $what . '_account', ['name' => e($account->name)]), route('accounts.edit', [$account->id]));
}
);
// budgets.
Breadcrumbs::register(
'budgets.index', function (Generator $breadcrumbs) {
'budgets.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Budgets', route('budgets.index'));
$breadcrumbs->push(trans('breadcrumbs.budgets'), route('budgets.index'));
}
);
Breadcrumbs::register(
'budgets.create', function (Generator $breadcrumbs) {
'budgets.create', function(Generator $breadcrumbs) {
$breadcrumbs->parent('budgets.index');
$breadcrumbs->push('Create new budget', route('budgets.create'));
$breadcrumbs->push(trans('breadcrumbs.newBudget'), route('budgets.create'));
}
);
Breadcrumbs::register(
'budgets.edit', function (Generator $breadcrumbs, Budget $budget) {
'budgets.edit', function(Generator $breadcrumbs, Budget $budget) {
$breadcrumbs->parent('budgets.show', $budget);
$breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id));
$breadcrumbs->push(trans('breadcrumbs.edit_budget', ['name' => e($budget->name)]), route('budgets.edit', [$budget->id]));
}
);
Breadcrumbs::register(
'budgets.delete', function (Generator $breadcrumbs, Budget $budget) {
'budgets.delete', function(Generator $breadcrumbs, Budget $budget) {
$breadcrumbs->parent('budgets.show', $budget);
$breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id));
$breadcrumbs->push(trans('breadcrumbs.delete_budget', ['name' => e($budget->name)]), route('budgets.delete', [$budget->id]));
}
);
Breadcrumbs::register(
'budgets.noBudget', function (Generator $breadcrumbs, $subTitle) {
'budgets.noBudget', function(Generator $breadcrumbs, $subTitle) {
$breadcrumbs->parent('budgets.index');
$breadcrumbs->push($subTitle, route('budgets.noBudget'));
}
);
Breadcrumbs::register(
'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) {
'budgets.show', function(Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) {
$breadcrumbs->parent('budgets.index');
$breadcrumbs->push(e($budget->name), route('budgets.show', $budget->id));
$breadcrumbs->push(e($budget->name), route('budgets.show', [$budget->id]));
if (!is_null($repetition) && !is_null($repetition->id)) {
$breadcrumbs->push(
Navigation::periodShow($repetition->startdate, $repetition->budgetlimit->repeat_freq), route('budgets.show', $budget->id, $repetition->id)
Navigation::periodShow($repetition->startdate, $repetition->budgetLimit->repeat_freq), route('budgets.show', [$budget->id, $repetition->id])
);
}
}
@@ -126,41 +122,41 @@ Breadcrumbs::register(
// categories
Breadcrumbs::register(
'categories.index', function (Generator $breadcrumbs) {
'categories.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Categories', route('categories.index'));
$breadcrumbs->push(trans('breadcrumbs.categories'), route('categories.index'));
}
);
Breadcrumbs::register(
'categories.create', function (Generator $breadcrumbs) {
'categories.create', function(Generator $breadcrumbs) {
$breadcrumbs->parent('categories.index');
$breadcrumbs->push('Create new category', route('categories.create'));
$breadcrumbs->push(trans('breadcrumbs.newCategory'), route('categories.create'));
}
);
Breadcrumbs::register(
'categories.edit', function (Generator $breadcrumbs, Category $category) {
'categories.edit', function(Generator $breadcrumbs, Category $category) {
$breadcrumbs->parent('categories.show', $category);
$breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id));
$breadcrumbs->push(trans('breadcrumbs.edit_category', ['name' => e($category->name)]), route('categories.edit', [$category->id]));
}
);
Breadcrumbs::register(
'categories.delete', function (Generator $breadcrumbs, Category $category) {
'categories.delete', function(Generator $breadcrumbs, Category $category) {
$breadcrumbs->parent('categories.show', $category);
$breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id));
$breadcrumbs->push(trans('breadcrumbs.delete_category', ['name' => e($category->name)]), route('categories.delete', [$category->id]));
}
);
Breadcrumbs::register(
'categories.show', function (Generator $breadcrumbs, Category $category) {
'categories.show', function(Generator $breadcrumbs, Category $category) {
$breadcrumbs->parent('categories.index');
$breadcrumbs->push(e($category->name), route('categories.show', $category->id));
$breadcrumbs->push(e($category->name), route('categories.show', [$category->id]));
}
);
Breadcrumbs::register(
'categories.noCategory', function (Generator $breadcrumbs, $subTitle) {
'categories.noCategory', function(Generator $breadcrumbs, $subTitle) {
$breadcrumbs->parent('categories.index');
$breadcrumbs->push($subTitle, route('categories.noCategory'));
}
@@ -168,135 +164,135 @@ Breadcrumbs::register(
// currencies.
Breadcrumbs::register(
'currency.index', function (Generator $breadcrumbs) {
'currency.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Currencies', route('currency.index'));
$breadcrumbs->push(trans('breadcrumbs.currencies'), route('currency.index'));
}
);
Breadcrumbs::register(
'currency.edit', function (Generator $breadcrumbs, TransactionCurrency $currency) {
'currency.edit', function(Generator $breadcrumbs, TransactionCurrency $currency) {
$breadcrumbs->parent('currency.index');
$breadcrumbs->push('Edit ' . $currency->name, route('currency.edit', $currency->id));
$breadcrumbs->push(trans('breadcrumbs.edit_currency', ['name' => e($currency->name)]), route('currency.edit', [$currency->id]));
}
);
Breadcrumbs::register(
'currency.delete', function (Generator $breadcrumbs, TransactionCurrency $currency) {
'currency.delete', function(Generator $breadcrumbs, TransactionCurrency $currency) {
$breadcrumbs->parent('currency.index');
$breadcrumbs->push('Delete ' . $currency->name, route('currency.delete', $currency->id));
$breadcrumbs->push(trans('breadcrumbs.delete_currency', ['name' => e($currency->name)]), route('currency.delete', [$currency->id]));
}
);
// piggy banks
Breadcrumbs::register(
'piggy-banks.index', function (Generator $breadcrumbs) {
'piggy-banks.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Piggy banks', route('piggy-banks.index'));
$breadcrumbs->push(trans('breadcrumbs.piggyBanks'), route('piggy-banks.index'));
}
);
Breadcrumbs::register(
'piggy-banks.create', function (Generator $breadcrumbs) {
'piggy-banks.create', function(Generator $breadcrumbs) {
$breadcrumbs->parent('piggy-banks.index');
$breadcrumbs->push('Create new piggy bank', route('piggy-banks.create'));
$breadcrumbs->push(trans('breadcrumbs.newPiggyBank'), route('piggy-banks.create'));
}
);
Breadcrumbs::register(
'piggy-banks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
'piggy-banks.edit', function(Generator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
$breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggy-banks.edit', $piggyBank->id));
$breadcrumbs->push(trans('breadcrumbs.edit_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.edit', [$piggyBank->id]));
}
);
Breadcrumbs::register(
'piggy-banks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
'piggy-banks.delete', function(Generator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
$breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggy-banks.delete', $piggyBank->id));
$breadcrumbs->push(trans('breadcrumbs.delete_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', [$piggyBank->id]));
}
);
Breadcrumbs::register(
'piggy-banks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
'piggy-banks.show', function(Generator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.index');
$breadcrumbs->push(e($piggyBank->name), route('piggy-banks.show', $piggyBank->id));
$breadcrumbs->push(e($piggyBank->name), route('piggy-banks.show', [$piggyBank->id]));
}
);
// preferences
Breadcrumbs::register(
'preferences', function (Generator $breadcrumbs) {
'preferences', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Preferences', route('preferences'));
$breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences'));
}
);
// profile
Breadcrumbs::register(
'profile', function (Generator $breadcrumbs) {
'profile', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Profile', route('profile'));
$breadcrumbs->push(trans('breadcrumbs.profile'), route('profile'));
}
);
Breadcrumbs::register(
'change-password', function (Generator $breadcrumbs) {
'change-password', function(Generator $breadcrumbs) {
$breadcrumbs->parent('profile');
$breadcrumbs->push('Change your password', route('change-password'));
$breadcrumbs->push(trans('breadcrumbs.changePassword'), route('change-password'));
}
);
// bills
Breadcrumbs::register(
'bills.index', function (Generator $breadcrumbs) {
'bills.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Bills', route('bills.index'));
$breadcrumbs->push(trans('breadcrumbs.bills'), route('bills.index'));
}
);
Breadcrumbs::register(
'bills.create', function (Generator $breadcrumbs) {
'bills.create', function(Generator $breadcrumbs) {
$breadcrumbs->parent('bills.index');
$breadcrumbs->push('Create new bill', route('bills.create'));
$breadcrumbs->push(trans('breadcrumbs.newBill'), route('bills.create'));
}
);
Breadcrumbs::register(
'bills.edit', function (Generator $breadcrumbs, Bill $bill) {
'bills.edit', function(Generator $breadcrumbs, Bill $bill) {
$breadcrumbs->parent('bills.show', $bill);
$breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id));
$breadcrumbs->push(trans('breadcrumbs.edit_bill', ['name' => e($bill->name)]), route('bills.edit', [$bill->id]));
}
);
Breadcrumbs::register(
'bills.delete', function (Generator $breadcrumbs, Bill $bill) {
'bills.delete', function(Generator $breadcrumbs, Bill $bill) {
$breadcrumbs->parent('bills.show', $bill);
$breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id));
$breadcrumbs->push(trans('breadcrumbs.delete_bill', ['name' => e($bill->name)]), route('bills.delete', [$bill->id]));
}
);
Breadcrumbs::register(
'bills.show', function (Generator $breadcrumbs, Bill $bill) {
'bills.show', function(Generator $breadcrumbs, Bill $bill) {
$breadcrumbs->parent('bills.index');
$breadcrumbs->push(e($bill->name), route('bills.show', $bill->id));
$breadcrumbs->push(e($bill->name), route('bills.show', [$bill->id]));
}
);
// reminders
Breadcrumbs::register(
'reminders.index', function (Generator $breadcrumbs) {
'reminders.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Reminders', route('reminders.index'));
$breadcrumbs->push(trans('breadcrumbs.reminders'), route('reminders.index'));
}
);
// reminders
Breadcrumbs::register(
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
'reminders.show', function(Generator $breadcrumbs, Reminder $reminder) {
$breadcrumbs->parent('reminders.index');
$breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id));
$breadcrumbs->push(trans('breadcrumbs.reminder', ['id' => e($reminder->id)]), route('reminders.show', [$reminder->id]));
}
);
@@ -304,115 +300,115 @@ Breadcrumbs::register(
// reports
Breadcrumbs::register(
'reports.index', function (Generator $breadcrumbs) {
'reports.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Reports', route('reports.index'));
$breadcrumbs->push(trans('breadcrumbs.reports'), route('reports.index'));
}
);
Breadcrumbs::register(
'reports.year', function (Generator $breadcrumbs, Carbon $date) {
'reports.year', function(Generator $breadcrumbs, Carbon $date, $shared) {
$breadcrumbs->parent('reports.index');
$breadcrumbs->push($date->year, route('reports.year', $date->year));
if ($shared) {
$title = trans('breadcrumbs.yearly_report_shared', ['date' => $date->year]);
} else {
$title = trans('breadcrumbs.yearly_report', ['date' => $date->year]);
}
$breadcrumbs->push($title, route('reports.year', [$date->year]));
}
);
Breadcrumbs::register(
'reports.month', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.year', $date);
$breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', [$date->year, $date->month]));
}
);
'reports.month', function(Generator $breadcrumbs, Carbon $date, $shared) {
$breadcrumbs->parent('reports.year', $date, $shared);
Breadcrumbs::register(
'reports.budget', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index');
$breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', [$date->year, $date->month]));
if ($shared) {
$title = trans('breadcrumbs.monthly_report_shared', ['date' => $date->year]);
} else {
$title = trans('breadcrumbs.monthly_report', ['date' => $date->year]);
}
$breadcrumbs->push($title, route('reports.month', [$date->year, $date->month]));
}
);
// search
Breadcrumbs::register(
'search', function (Generator $breadcrumbs, $query) {
'search', function(Generator $breadcrumbs, $query) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Search for "' . e($query) . '"', route('search'));
$breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search'));
}
);
// transactions
Breadcrumbs::register(
'transactions.index', function (Generator $breadcrumbs, $what) {
'transactions.index', function(Generator $breadcrumbs, $what) {
$breadcrumbs->parent('home');
switch ($what) {
case 'expenses':
case 'withdrawal':
$subTitle = 'Expenses';
break;
case 'revenue':
case 'deposit':
$subTitle = 'Revenue, income and deposits';
break;
case 'transfer':
case 'transfers':
$subTitle = 'Transfers';
break;
case 'opening balance':
$subTitle = 'Opening balances';
break;
default:
throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs');
}
$breadcrumbs->push($subTitle, route('transactions.index', $what));
$breadcrumbs->push(trans('breadcrumbs.' . $what . '_list'), route('transactions.index', [$what]));
}
);
Breadcrumbs::register(
'transactions.create', function (Generator $breadcrumbs, $what) {
'transactions.create', function(Generator $breadcrumbs, $what) {
$breadcrumbs->parent('transactions.index', $what);
$breadcrumbs->push('Create new ' . e($what), route('transactions.create', $what));
$breadcrumbs->push(trans('breadcrumbs.create_' . e($what)), route('transactions.create', [$what]));
}
);
Breadcrumbs::register(
'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) {
'transactions.edit', function(Generator $breadcrumbs, TransactionJournal $journal) {
$breadcrumbs->parent('transactions.show', $journal);
$breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id));
$breadcrumbs->push(trans('breadcrumbs.edit_journal', ['description' => $journal->description]), route('transactions.edit', [$journal->id]));
}
);
Breadcrumbs::register(
'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) {
'transactions.delete', function(Generator $breadcrumbs, TransactionJournal $journal) {
$breadcrumbs->parent('transactions.show', $journal);
$breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id));
$breadcrumbs->push(trans('breadcrumbs.delete_journal', ['description' => e($journal->description)]), route('transactions.delete', [$journal->id]));
}
);
Breadcrumbs::register(
'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) {
'transactions.show', function(Generator $breadcrumbs, TransactionJournal $journal) {
$breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type));
$breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id));
$breadcrumbs->push($journal->description, route('transactions.show', [$journal->id]));
}
);
// tags
Breadcrumbs::register(
'tags.index', function (Generator $breadcrumbs) {
'tags.index', function(Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Tags', route('tags.index'));
$breadcrumbs->push(trans('breadcrumbs.tags'), route('tags.index'));
}
);
Breadcrumbs::register(
'tags.create', function (Generator $breadcrumbs) {
'tags.create', function(Generator $breadcrumbs) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push('Create tag', route('tags.create'));
$breadcrumbs->push(trans('breadcrumbs.createTag'), route('tags.create'));
}
);
Breadcrumbs::register(
'tags.show', function (Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push(e($tag->tag), route('tags.show', $tag->id));
'tags.edit', function(Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.show', $tag);
$breadcrumbs->push(trans('breadcrumbs.edit_tag', ['tag' => e($tag->tag)]), route('tags.edit', [$tag->id]));
}
);
Breadcrumbs::register(
'tags.delete', function(Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.show', $tag);
$breadcrumbs->push(trans('breadcrumbs.delete_tag', ['tag' => e($tag->tag)]), route('tags.delete', [$tag->id]));
}
);
Breadcrumbs::register(
'tags.show', function(Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push(e($tag->tag), route('tags.show', [$tag->id]));
}
);

View File

@@ -13,16 +13,15 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
// models
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'account',
function ($value, $route) {
function($value) {
if (Auth::check()) {
$object = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.editable', 1)
->where('accounts.id', $value)
->where('user_id', Auth::user()->id)
->first(['accounts.*']);
->where('account_types.editable', 1)
->where('accounts.id', $value)
->where('user_id', Auth::user()->id)
->first(['accounts.*']);
if ($object) {
return $object;
}
@@ -31,9 +30,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'tj', function ($value, $route) {
'tj', function($value) {
if (Auth::check()) {
$object = TransactionJournal::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
@@ -45,9 +43,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'currency', function ($value, $route) {
'currency', function($value) {
if (Auth::check()) {
$object = TransactionCurrency::find($value);
if ($object) {
@@ -58,9 +55,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'bill', function ($value, $route) {
'bill', function($value) {
if (Auth::check()) {
$object = Bill::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
@@ -72,9 +68,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'budget', function ($value, $route) {
'budget', function($value) {
if (Auth::check()) {
$object = Budget::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
@@ -86,9 +81,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'reminder', function ($value, $route) {
'reminder', function($value) {
if (Auth::check()) {
$object = Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
@@ -100,15 +94,14 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'limitrepetition', function ($value, $route) {
'limitrepetition', function($value) {
if (Auth::check()) {
$object = LimitRepetition::where('limit_repetitions.id', $value)
->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', Auth::user()->id)
->first(['limit_repetitions.*']);
->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', Auth::user()->id)
->first(['limit_repetitions.*']);
if ($object) {
return $object;
}
@@ -118,14 +111,13 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'piggyBank', function ($value, $route) {
'piggyBank', function($value) {
if (Auth::check()) {
$object = PiggyBank::where('piggy_banks.id', $value)
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('accounts.user_id', Auth::user()->id)
->first(['piggy_banks.*']);
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('accounts.user_id', Auth::user()->id)
->first(['piggy_banks.*']);
if ($object) {
return $object;
}
@@ -135,9 +127,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'category', function ($value, $route) {
'category', function($value) {
if (Auth::check()) {
$object = Category::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
@@ -151,7 +142,7 @@ Route::bind(
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'reminder', function ($value, $route) {
'reminder', function($value) {
if (Auth::check()) {
/** @var \FireflyIII\Models\Reminder $object */
$object = Reminder::find($value);
@@ -166,9 +157,8 @@ Route::bind(
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'tag', function ($value, $route) {
'tag', function($value) {
if (Auth::check()) {
$object = Tag::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
@@ -193,13 +183,14 @@ Route::controllers(
]
);
Route::get('/routes', ['uses' => 'HomeController@routes', 'as' => 'routes']);
/**
* Home Controller
*/
Route::group(
['middleware' => ['auth', 'range', 'reminders', 'piggybanks']], function () {
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
['middleware' => ['auth', 'range', 'reminders']], function() {
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index', 'middleware' => 'cleanup']);
Route::get('/home', ['uses' => 'HomeController@index', 'as' => 'home']);
Route::post('/daterange', ['uses' => 'HomeController@dateRange', 'as' => 'daterange']);
Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']);
@@ -223,7 +214,6 @@ Route::group(
Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching.
Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']);
Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']);
Route::get('/bills/add/{bill}', ['uses' => 'BillController@add', 'as' => 'bills.add']);
Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']);
Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']);
@@ -273,22 +263,41 @@ Route::group(
/**
* Google Chart Controller
* ALL CHART Controllers
*/
Route::get('/chart/home/account', ['uses' => 'GoogleChartController@allAccountsBalanceChart']);
Route::get('/chart/home/budgets', ['uses' => 'GoogleChartController@allBudgetsHomeChart']);
Route::get('/chart/home/categories', ['uses' => 'GoogleChartController@allCategoriesHomeChart']);
Route::get('/chart/home/bills', ['uses' => 'GoogleChartController@billsOverview']);
Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']);
Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']);
Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending'])->where(['year' => '[0-9]+']);
Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']);
Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']);
Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']);
Route::get('/chart/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']);
Route::get('/chart/piggy-history/{piggyBank}', ['uses' => 'GoogleChartController@piggyBankHistory']);
Route::get('/chart/category/{category}/period', ['uses' => 'GoogleChartController@categoryPeriodChart']);
Route::get('/chart/category/{category}/overview', ['uses' => 'GoogleChartController@categoryOverviewChart']);
// accounts:
Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']);
Route::get('/chart/account/month/{year}/{month}/{shared?}', ['uses' => 'Chart\AccountController@all'])->where(
['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared']
);
Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']);
// bills:
Route::get('/chart/bill/frontpage', ['uses' => 'Chart\BillController@frontpage']);
Route::get('/chart/bill/{bill}', ['uses' => 'Chart\BillController@single']);
// budgets:
Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']);
Route::get('/chart/budget/year/{year}/{shared?}', ['uses' => 'Chart\BudgetController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'Chart\BudgetController@budgetLimit']);
Route::get('/chart/budget/{budget}', ['uses' => 'Chart\BudgetController@budget']);
// categories:
Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']);
Route::get('/chart/category/year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/chart/category/{category}/month', ['uses' => 'Chart\CategoryController@month']); // should be period.
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
// piggy banks:
Route::get('/chart/piggyBank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']);
// reports:
Route::get('/chart/report/in-out/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOut'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/chart/report/in-out-sum/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOutSummarized'])->where(
['year' => '[0-9]{4}', 'shared' => 'shared']
);
/**
* Help Controller
@@ -306,10 +315,7 @@ Route::group(
Route::get('/json/box/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']);
Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']);
Route::get('/json/box/bills-paid', ['uses' => 'JsonController@boxBillsPaid', 'as' => 'json.box.unpaid']);
Route::get('/json/show-shared-reports', 'JsonController@showSharedReports');
Route::get('/json/transaction-journals/{what}', 'JsonController@transactionJournals');
Route::get('/json/show-shared-reports/set', 'JsonController@setSharedReports');
/**
* Piggy Bank Controller
@@ -355,19 +361,12 @@ Route::group(
* Report Controller
*/
Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']);
Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year']);
Route::get('/reports/{year}/{month}', ['uses' => 'ReportController@month', 'as' => 'reports.month']);
Route::get('/reports/budget/{year}/{month}', ['uses' => 'ReportController@budget', 'as' => 'reports.budget']);
Route::get('/reports/{year}/{shared?}', ['uses' => 'ReportController@year', 'as' => 'reports.year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/reports/{year}/{month}/{shared?}', ['uses' => 'ReportController@month', 'as' => 'reports.month'])->where(
['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared']
);
// pop ups for budget report:
Route::get('/reports/modal/{account}/{year}/{month}/no-budget', ['uses' => 'ReportController@modalNoBudget', 'as' => 'reports.no-budget']);
Route::get(
'/reports/modal/{account}/{year}/{month}/balanced-transfers',
['uses' => 'ReportController@modalBalancedTransfers', 'as' => 'reports.balanced-transfers']
);
Route::get(
'/reports/modal/{account}/{year}/{month}/left-unbalanced', ['uses' => 'ReportController@modalLeftUnbalanced', 'as' => 'reports.left-unbalanced']
);
/**
* Search Controller

View File

@@ -1,6 +1,5 @@
<?php namespace FireflyIII\Models;
use App;
use Crypt;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
@@ -12,12 +11,50 @@ use Watson\Validating\ValidatingTrait;
* Class Account
*
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property integer $user_id
* @property integer $account_type_id
* @property string $name
* @property boolean $active
* @property boolean $encrypted
* @property float $virtual_balance
* @property string $virtual_balance_encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\AccountMeta[] $accountMeta
* @property-read \FireflyIII\Models\AccountType $accountType
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBank[] $piggyBanks
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereAccountTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereVirtualBalance($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereVirtualBalanceEncrypted($value)
* @method static \FireflyIII\Models\Account accountTypeIn($types)
* @method static \FireflyIII\Models\Account hasMetaValue($name, $value)
* @property boolean joinedAccountTypes
* @property mixed startBalance
* @property mixed endBalance
* @property mixed lastActivityDate
* @property mixed piggyBalance
* @property mixed difference
* @propery mixed percentage
*
*/
class Account extends Model
{
use SoftDeletes, ValidatingTrait;
protected $fillable = ['user_id', 'account_type_id', 'name', 'active', 'virtual_balance'];
protected $hidden = ['virtual_balance_encrypted', 'encrypted'];
protected $rules
= [
'user_id' => 'required|exists:users,id',
@@ -28,7 +65,7 @@ class Account extends Model
/**
* @param array $fields
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return Account|null
*/
@@ -50,12 +87,6 @@ class Account extends Model
}
// create it!
$account = Account::create($fields);
if (is_null($account->id)) {
// could not create account:
App::abort(500, 'Could not create new account with data: ' . json_encode($fields) . ' because ' . json_encode($account->getErrors()));
}
return $account;
@@ -106,7 +137,7 @@ class Account extends Model
/**
* @codeCoverageIgnore
* @return array
* @return string[]
*/
public function getDates()
{
@@ -115,7 +146,9 @@ class Account extends Model
/**
*
* @param $fieldName
* @param string $fieldName
*
* @codeCoverageIgnore
*
* @return string|null
*/
@@ -133,6 +166,7 @@ class Account extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -144,9 +178,7 @@ class Account extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
/**
@@ -160,6 +192,7 @@ class Account extends Model
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param array $types
*/
@@ -174,6 +207,7 @@ class Account extends Model
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param string $name
* @param string $value
@@ -182,7 +216,7 @@ class Account extends Model
{
$joinName = str_replace('.', '_', $name);
$query->leftJoin(
'account_meta as ' . $joinName, function (JoinClause $join) use ($joinName, $name) {
'account_meta as ' . $joinName, function(JoinClause $join) use ($joinName, $name) {
$join->on($joinName . '.account_id', '=', 'accounts.id')->where($joinName . '.name', '=', $name);
}
);
@@ -191,6 +225,7 @@ class Account extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setNameAttribute($value)
@@ -199,6 +234,16 @@ class Account extends Model
$this->attributes['encrypted'] = true;
}
/**
* @param $value
*
* @codeCoverageIgnore
*/
public function setVirtualBalanceAttribute($value)
{
$this->attributes['virtual_balance'] = strval(round($value, 2));
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany

View File

@@ -6,8 +6,21 @@ use Watson\Validating\ValidatingTrait;
/**
* Class AccountMeta
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $account_id
* @property string $name
* @property string $data
* @property-read \FireflyIII\Models\Account $account
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereAccountId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereData($value)
*/
class AccountMeta extends Model
{
@@ -20,7 +33,7 @@ class AccountMeta extends Model
'name' => 'required|between:1,100',
'data' => 'required'
];
protected $table = 'account_meta';
protected $table = 'account_meta';
/**
*

View File

@@ -5,8 +5,19 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class AccountType
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $type
* @property boolean $editable
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Account[] $accounts
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereType($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereEditable($value)
*/
class AccountType extends Model
{

View File

@@ -4,15 +4,56 @@ use Crypt;
use Illuminate\Database\Eloquent\Model;
/**
* Class Bill
* FireflyIII\Models\Bill
*
* @codeCoverageIgnore Class Bill
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property string $name
* @property string $match
* @property float $amount_min
* @property string $amount_min_encrypted
* @property float $amount_max
* @property string $amount_max_encrypted
* @property \Carbon\Carbon $date
* @property boolean $active
* @property boolean $automatch
* @property string $repeat_freq
* @property integer $skip
* @property boolean $name_encrypted
* @property boolean $match_encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatch($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMin($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMinEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMax($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMaxEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAutomatch($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereRepeatFreq($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereSkip($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereNameEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatchEncrypted($value)
* @property mixed nextExpectedMatch
* @property mixed lastFoundMatch
*/
class Bill extends Model
{
protected $fillable
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip', 'automatch', 'active',];
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip', 'automatch', 'active', ];
protected $hidden = ['amount_min_encrypted', 'amount_max_encrypted', 'name_encrypted', 'match_encrypted'];
/**
* @return array
@@ -34,9 +75,7 @@ class Bill extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
/**
@@ -51,9 +90,23 @@ class Bill extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
/**
* @param $value
*/
public function setAmountMaxAttribute($value)
{
$this->attributes['amount_max'] = strval(round($value, 2));
}
/**
* @param $value
*/
public function setAmountMinAttribute($value)
{
$this->attributes['amount_min'] = strval(round($value, 2));
}
/**

View File

@@ -7,15 +7,35 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Budget
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property string $name
* @property integer $user_id
* @property boolean $active
* @property boolean $encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\BudgetLimit[] $budgetlimits
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereEncrypted($value)
*/
class Budget extends Model
{
use SoftDeletes;
protected $fillable = ['user_id', 'name'];
protected $fillable = ['user_id', 'name', 'active'];
protected $hidden = ['encrypted'];
/**
*
@@ -46,9 +66,7 @@ class Budget extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
/**

View File

@@ -5,12 +5,34 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class BudgetLimit
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $budget_id
* @property \Carbon\Carbon $startdate
* @property float $amount
* @property string $amount_encrypted
* @property boolean $repeats
* @property string $repeat_freq
* @property-read \FireflyIII\Models\Budget $budget
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\LimitRepetition[] $limitrepetitions
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereBudgetId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereAmount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereAmountEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeats($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeatFreq($value)
*/
class BudgetLimit extends Model
{
protected $hidden = ['amount_encrypted'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@@ -35,4 +57,12 @@ class BudgetLimit extends Model
return $this->hasMany('FireflyIII\Models\LimitRepetition');
}
/**
* @param $value
*/
public function setAmountAttribute($value)
{
$this->attributes['amount'] = strval(round($value, 2));
}
}

View File

@@ -1,6 +1,5 @@
<?php namespace FireflyIII\Models;
use App;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -8,37 +7,38 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Category
*
*
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property string $name
* @property integer $user_id
* @property boolean $encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereEncrypted($value)
* @property mixed spent
* @property mixed lastActivity
*/
class Category extends Model
{
use SoftDeletes;
protected $fillable = ['user_id', 'name'];
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at', 'deleted_at'];
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
{
return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'category_transaction_journal', 'category_id');
}
protected $hidden = ['encrypted'];
/**
* @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return Account|null
* @return Category
*/
public static function firstOrCreateEncrypted(array $fields)
{
@@ -58,11 +58,6 @@ class Category extends Model
}
// create it!
$category = Category::create($fields);
if (is_null($category->id)) {
// could not create account:
App::abort(500, 'Could not create new category with data: ' . json_encode($fields));
}
return $category;
@@ -70,25 +65,16 @@ class Category extends Model
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
* @return string[]
*/
public function user()
public function getDates()
{
return $this->belongsTo('FireflyIII\User');
}
/**
* @codeCoverageIgnore
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
return ['created_at', 'updated_at', 'deleted_at'];
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -103,4 +89,33 @@ class Category extends Model
return $value;
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
{
return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'category_transaction_journal', 'category_id');
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('FireflyIII\User');
}
}

View File

@@ -6,8 +6,22 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Component
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property string $name
* @property integer $user_id
* @property string $class
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereClass($value)
*/
class Component extends Model
{

View File

@@ -1,19 +1,36 @@
<?php namespace FireflyIII\Models;
use Auth;
use DB;
use Illuminate\Database\Eloquent\Model;
/**
* Class LimitRepetition
*
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $budget_limit_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $enddate
* @property float $amount
* @property string $amount_encrypted
* @property-read \FireflyIII\Models\BudgetLimit $budgetLimit
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereBudgetLimitId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereAmount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereAmountEncrypted($value)
*/
class LimitRepetition extends Model
{
protected $hidden = ['amount_encrypted'];
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function budgetLimit()
@@ -22,7 +39,6 @@ class LimitRepetition extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -31,24 +47,11 @@ class LimitRepetition extends Model
}
/**
* @return float
* @param $value
*/
public function spentInRepetition()
public function setAmountAttribute($value)
{
$sum = DB::table('transactions')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('transaction_journals.date', '>=', $this->startdate->format('Y-m-d'))
->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d'))
->where('transaction_journals.user_id', Auth::user()->id)
->whereNull('transactions.deleted_at')
->where('transactions.amount', '>', 0)
->where('limit_repetitions.id', '=', $this->id)
->sum('transactions.amount');
return floatval($sum);
$this->attributes['amount'] = strval(round($value, 2));
}
}

14
app/Models/Permission.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
namespace FireflyIII\Models;
use Zizaco\Entrust\EntrustPermission;
/**
* Class Permission
*
* @package FireflyIII\Models
*/
class Permission extends EntrustPermission
{
}

View File

@@ -7,17 +7,53 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class PiggyBank
*
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property integer $account_id
* @property string $name
* @property float $targetamount
* @property string $targetamount_encrypted
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate
* @property string $reminder
* @property integer $reminder_skip
* @property boolean $remind_me
* @property integer $order
* @property boolean $encrypted
* @property-read \FireflyIII\Models\Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Reminder[] $reminders
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereAccountId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamountEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
* @property PiggyBankRepetition currentRep
*/
class PiggyBank extends Model
{
use SoftDeletes;
protected $fillable
= ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
= ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
protected $hidden = ['targetamount_encrypted', 'encrypted'];
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function account()
@@ -45,7 +81,6 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBankRepetitions()
@@ -54,8 +89,7 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @return array
* @return string[]
*/
public function getDates()
{
@@ -63,46 +97,7 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @param $value
*
* @return int
*/
public function getRemindMeAttribute($value)
{
return intval($value) == 1;
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBankEvents()
{
return $this->hasMany('FireflyIII\Models\PiggyBankEvent');
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function reminders()
{
return $this->morphMany('FireflyIII\Models\Reminder', 'remindersable');
}
/**
* @codeCoverageIgnore
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
}
/**
* @codeCoverageIgnore
* @param $value
*
* @return string
@@ -114,8 +109,51 @@ class PiggyBank extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
/**
*
* @param $value
*
* @return boolean
*/
public function getRemindMeAttribute($value)
{
return intval($value) == 1;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBankEvents()
{
return $this->hasMany('FireflyIII\Models\PiggyBankEvent');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function reminders()
{
return $this->morphMany('FireflyIII\Models\Reminder', 'remindersable');
}
/**
*
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
}
/**
* @param $value
*/
public function setTargetamountAttribute($value)
{
$this->attributes['targetamount'] = strval(round($value, 2));
}
}

View File

@@ -5,13 +5,32 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class PiggyBankEvent
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $piggy_bank_id
* @property integer $transaction_journal_id
* @property \Carbon\Carbon $date
* @property float $amount
* @property string $amount_encrypted
* @property-read \FireflyIII\Models\PiggyBank $piggyBank
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent wherePiggyBankId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereTransactionJournalId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereAmount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereAmountEncrypted($value)
*/
class PiggyBankEvent extends Model
{
protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'amount'];
protected $hidden = ['amount_encrypted'];
/**
* @return array
@@ -29,6 +48,14 @@ class PiggyBankEvent extends Model
return $this->belongsTo('FireflyIII\Models\PiggyBank');
}
/**
* @param $value
*/
public function setAmountAttribute($value)
{
$this->attributes['amount'] = strval(round($value, 2));
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@@ -7,13 +7,33 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class PiggyBankRepetition
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $piggy_bank_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate
* @property float $currentamount
* @property string $currentamount_encrypted
* @property-read \FireflyIII\Models\PiggyBank $piggyBank
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition wherePiggyBankId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereTargetdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCurrentamount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCurrentamountEncrypted($value)
* @method static \FireflyIII\Models\PiggyBankRepetition onDates($start, $target)
* @method static \FireflyIII\Models\PiggyBankRepetition relevantOnDate($date)
*/
class PiggyBankRepetition extends Model
{
protected $fillable = ['piggy_bank_id', 'startdate', 'targetdate', 'currentamount'];
protected $hidden = ['currentamount_encrypted'];
/**
* @return array
@@ -57,13 +77,21 @@ class PiggyBankRepetition extends Model
$q->orWhereNull('startdate');
}
)
->where(
function (EloquentBuilder $q) use ($date) {
->where(
function (EloquentBuilder $q) use ($date) {
$q->where('targetdate', '>=', $date->format('Y-m-d 00:00:00'));
$q->orWhereNull('targetdate');
}
);
$q->where('targetdate', '>=', $date->format('Y-m-d 00:00:00'));
$q->orWhereNull('targetdate');
}
);
}
/**
* @param $value
*/
public function setCurrentamountAttribute($value)
{
$this->attributes['currentamount'] = strval(round($value, 2));
}
}

View File

@@ -1,17 +1,36 @@
<?php namespace FireflyIII\Models;
use Crypt;
use Illuminate\Database\Eloquent\Model;
/**
* Class Preference
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property string $name
* @property string $name_encrypted
* @property string $data
* @property string $data_encrypted
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereNameEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereData($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereDataEncrypted($value)
*/
class Preference extends Model
{
protected $fillable = ['user_id', 'data', 'name'];
protected $hidden = ['data_encrypted', 'name_encrypted'];
/**
* @param $value
@@ -20,7 +39,12 @@ class Preference extends Model
*/
public function getDataAttribute($value)
{
return json_decode($value);
if (is_null($this->data_encrypted)) {
return json_decode($value);
}
$data = Crypt::decrypt($this->data_encrypted);
return json_decode($data);
}
/**
@@ -31,12 +55,37 @@ class Preference extends Model
return ['created_at', 'updated_at'];
}
/**
* @param $value
*
* @return float|int
*/
public function getNameAttribute($value)
{
if (is_null($this->name_encrypted)) {
return $value;
}
$value = Crypt::decrypt($this->name_encrypted);
return $value;
}
/**
* @param $value
*/
public function setDataAttribute($value)
{
$this->attributes['data'] = json_encode($value);
$this->attributes['data'] = '';
$this->attributes['data_encrypted'] = Crypt::encrypt(json_encode($value));
}
/**
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name_encrypted'] = Crypt::encrypt($value);
$this->attributes['name'] = $value;
}
/**

View File

@@ -8,16 +8,47 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class Reminder
*
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $enddate
* @property boolean $active
* @property boolean $notnow
* @property integer $remindersable_id
* @property string $remindersable_type
* @property string $metadata
* @property boolean $encrypted
* @property-read \ $remindersable
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereNotnow($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereRemindersableId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereRemindersableType($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereMetadata($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereEncrypted($value)
* @method static \FireflyIII\Models\Reminder onDates($start, $end)
* @method static \FireflyIII\Models\Reminder today()
* @property string description
*/
class Reminder extends Model
{
protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type',];
protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type', ];
protected $hidden = ['encrypted'];
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return int
@@ -28,7 +59,6 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -37,7 +67,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return mixed
@@ -52,7 +82,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return bool
@@ -63,7 +93,6 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function remindersable()
@@ -72,7 +101,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $start
* @param Carbon $end
@@ -85,7 +114,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
*
* @return $this
@@ -95,11 +124,11 @@ class Reminder extends Model
$today = new Carbon;
return $query->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))->where('active', 1)
->where('notnow', 0);
->where('notnow', 0);
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setMetadataAttribute($value)
@@ -109,7 +138,6 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()

14
app/Models/Role.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
namespace FireflyIII\Models;
use Zizaco\Entrust\EntrustRole;
/**
* Class Role
*
* @package FireflyIII\Models
*/
class Role extends EntrustRole
{
}

View File

@@ -2,7 +2,6 @@
namespace FireflyIII\Models;
use App;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;
@@ -11,6 +10,32 @@ use Watson\Validating\ValidatingTrait;
* Class Tag
*
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $deleted_at
* @property integer $user_id
* @property string $tag
* @property string $tagMode
* @property \Carbon\Carbon $date
* @property string $description
* @property float $latitude
* @property float $longitude
* @property integer $zoomLevel
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereTag($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereTagMode($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereLatitude($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereLongitude($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereZoomLevel($value)
*/
class Tag extends Model
{
@@ -29,6 +54,8 @@ class Tag extends Model
/**
* @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*
* @return Tag|null
*/
@@ -55,12 +82,6 @@ class Tag extends Model
$fields['tagMode'] = 'nothing';
$fields['description'] = isset($fields['description']) && !is_null($fields['description']) ? $fields['description'] : '';
$tag = Tag::create($fields);
if (is_null($tag->id)) {
// could not create account:
App::abort(500, 'Could not create new tag with data: ' . json_encode($fields) . ' because ' . json_encode($tag->getErrors()));
}
return $tag;
@@ -68,7 +89,7 @@ class Tag extends Model
/**
* @codeCoverageIgnore
* @return array
* @return string[]
*/
public function getDates()
{
@@ -77,6 +98,7 @@ class Tag extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -88,6 +110,7 @@ class Tag extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -99,6 +122,7 @@ class Tag extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setDescriptionAttribute($value)
@@ -108,6 +132,7 @@ class Tag extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setTagAttribute($value)

View File

@@ -9,13 +9,38 @@ use Watson\Validating\ValidatingTrait;
/**
* Class Transaction
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property integer $account_id
* @property integer $transaction_journal_id
* @property string $description
* @property float $amount
* @property string $amount_encrypted
* @property-read \FireflyIII\Models\Account $account
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAccountId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereTransactionJournalId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAmount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAmountEncrypted($value)
* @method static \FireflyIII\Models\Transaction after($date)
* @method static \FireflyIII\Models\Transaction before($date)
* @property mixed before
* @property mixed after
*/
class Transaction extends Model
{
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount'];
protected $hidden = ['encrypted'];
protected $rules
= [
'account_id' => 'required|exists:accounts,id',
@@ -33,6 +58,24 @@ class Transaction extends Model
return $this->belongsTo('FireflyIII\Models\Account');
}
/**
* @param $value
*
* @return float|int
*/
public function getAmountAttribute($value)
{
return $value;
}
/**
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at', 'deleted_at'];
}
/**
* @param EloquentBuilder $query
* @param Carbon $date
@@ -56,11 +99,11 @@ class Transaction extends Model
}
/**
* @return array
* @param $value
*/
public function getDates()
public function setAmountAttribute($value)
{
return ['created_at', 'updated_at', 'deleted_at'];
$this->attributes['amount'] = strval(round($value, 2));
}
/**

View File

@@ -4,11 +4,25 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
*
* Class TransactionCurrency
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property string $code
* @property string $name
* @property string $symbol
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionJournals
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereCode($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereSymbol($value)
*/
class TransactionCurrency extends Model
{

View File

@@ -6,8 +6,22 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class TransactionGroup
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property integer $user_id
* @property string $relation
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereRelation($value)
*/
class TransactionGroup extends Model
{

View File

@@ -12,15 +12,70 @@ use Watson\Validating\ValidatingTrait;
* Class TransactionJournal
*
* @package FireflyIII\Models
* @SuppressWarnings (PHPMD.TooManyMethods)
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property integer $user_id
* @property integer $transaction_type_id
* @property integer $bill_id
* @property integer $transaction_currency_id
* @property string $description
* @property boolean $completed
* @property \Carbon\Carbon $date
* @property boolean $encrypted
* @property integer $order
* @property-read \FireflyIII\Models\Bill $bill
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories
* @property-read mixed $actual_amount
* @property-read mixed $amount
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Tag[] $tags
* @property-read mixed $asset_account
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
* @property-read mixed $corrected_actual_amount
* @property-read mixed $destination_account
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
* @property-read \FireflyIII\Models\TransactionCurrency $transactionCurrency
* @property-read \FireflyIII\Models\TransactionType $transactionType
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionGroup[] $transactiongroups
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTransactionTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereBillId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTransactionCurrencyId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereCompleted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereOrder($value)
* @method static \FireflyIII\Models\TransactionJournal accountIs($account)
* @method static \FireflyIII\Models\TransactionJournal after($date)
* @method static \FireflyIII\Models\TransactionJournal before($date)
* @method static \FireflyIII\Models\TransactionJournal onDate($date)
* @method static \FireflyIII\Models\TransactionJournal transactionTypes($types)
* @method static \FireflyIII\Models\TransactionJournal withRelevantData()
* @property-read mixed $expense_account
* @property string account_encrypted
* @property bool joinedTransactions
* @property bool joinedTransactionTypes
* @property mixed account_id
* @property mixed name
* @property mixed symbol
*/
class TransactionJournal extends Model
{
use SoftDeletes, ValidatingTrait;
protected $fillable = ['user_id', 'transaction_type_id', 'bill_id', 'transaction_currency_id', 'description', 'completed', 'date', 'encrypted'];
protected $hidden = ['encrypted'];
protected $rules
= [
= [
'user_id' => 'required|exists:users,id',
'transaction_type_id' => 'required|exists:transaction_types,id',
'bill_id' => 'exists:bills,id',
@@ -58,42 +113,110 @@ class TransactionJournal extends Model
return $this->belongsToMany('FireflyIII\Models\Category');
}
/**
* @return string
*/
public function getActualAmountAttribute()
{
$amount = '0';
/** @var Transaction $t */
foreach ($this->transactions as $t) {
if ($t->amount > 0) {
$amount = $t->amount;
}
}
return $amount;
}
/**
* @return float
*/
public function getAmountAttribute()
{
$amount = '0';
bcscale(2);
/** @var Transaction $t */
foreach ($this->transactions as $t) {
if ($t->amount > 0) {
return floatval($t->amount);
$amount = $t->amount;
}
}
return 0;
/*
* If the journal has tags, it gets complicated.
*/
if ($this->tags->count() == 0) {
return $amount;
}
// if journal is part of advancePayment AND journal is a withdrawal,
// then journal is being repaid by other journals, so the actual amount will lower:
/** @var Tag $advancePayment */
$advancePayment = $this->tags()->where('tagMode', 'advancePayment')->first();
if ($advancePayment && $this->transactionType->type == 'Withdrawal') {
// loop other deposits, remove from our amount.
$others = $advancePayment->transactionJournals()->transactionTypes(['Deposit'])->get();
foreach ($others as $other) {
$amount = bcsub($amount, $other->actual_amount);
}
return $amount;
}
// if this journal is part of an advancePayment AND the journal is a deposit,
// then the journal amount is correcting a withdrawal, and the amount is zero:
if ($advancePayment && $this->transactionType->type == 'Deposit') {
return '0';
}
// is balancing act?
$balancingAct = $this->tags()->where('tagMode', 'balancingAct')->first();
if ($balancingAct) {
// this is the expense:
if ($this->transactionType->type == 'Withdrawal') {
$transfer = $balancingAct->transactionJournals()->transactionTypes(['Transfer'])->first();
if ($transfer) {
$amount = bcsub($amount, $transfer->actual_amount);
return $amount;
}
} // @codeCoverageIgnore
} // @codeCoverageIgnore
return $amount;
}
/**
* @return Account|mixed
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('FireflyIII\Models\Tag');
}
/**
* @return Account
*/
public function getAssetAccountAttribute()
{
$positive = true; // the asset account is in the transaction with the positive amount.
if ($this->transactionType->type === 'Withdrawal') {
$positive = false;
}
/** @var Transaction $transaction */
foreach ($this->transactions()->get() as $transaction) {
if (floatval($transaction->amount) > 0 && $positive === true) {
return $transaction->account;
}
if (floatval($transaction->amount) < 0 && $positive === false) {
return $transaction->account;
}
// if it's a deposit, it's the one thats positive
// if it's a withdrawal, it's the one thats negative
// otherwise, it's either (return first one):
switch ($this->transactionType->type) {
case 'Deposit':
return $this->transactions()->where('amount', '>', 0)->first()->account;
case 'Withdrawal':
return $this->transactions()->where('amount', '<', 0)->first()->account;
}
return $this->transactions()->first();
return $this->transactions()->first()->account;
}
/**
@@ -107,7 +230,7 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
* @return array
* @return string[]
*/
public function getDates()
{
@@ -116,6 +239,7 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -129,6 +253,42 @@ class TransactionJournal extends Model
return $value;
}
/**
* @return Account
*/
public function getDestinationAccountAttribute()
{
/** @var Transaction $transaction */
foreach ($this->transactions()->get() as $transaction) {
if (floatval($transaction->amount) > 0) {
return $transaction->account;
}
}
return $this->transactions()->first()->account;
}
/**
* @return Account
*/
public function getExpenseAccountAttribute()
{
// if it's a deposit, it's the one thats negative
// if it's a withdrawal, it's the one thats positive
// otherwise, it's either (return first one):
switch ($this->transactionType->type) {
case 'Deposit':
return $this->transactions()->where('amount', '<', 0)->first()->account;
case 'Withdrawal':
return $this->transactions()->where('amount', '>', 0)->first()->account;
}
return $this->transactions()->first()->account;
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
@@ -140,6 +300,7 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Account $account
*/
@@ -154,10 +315,11 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $date
*
* @return mixed
* @return EloquentBuilder
*/
public function scopeAfter(EloquentBuilder $query, Carbon $date)
{
@@ -166,10 +328,11 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $date
*
* @return mixed
* @return EloquentBuilder
*/
public function scopeBefore(EloquentBuilder $query, Carbon $date)
{
@@ -178,27 +341,11 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
* @param EloquentBuilder $query
* @param $amount
*/
public function scopeLessThan(EloquentBuilder $query, $amount)
{
if (is_null($this->joinedTransactions)) {
$query->leftJoin(
'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
);
$this->joinedTransactions = true;
}
$query->where('transactions.amount', '<=', $amount);
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $date
*
* @return mixed
* @return EloquentBuilder
*/
public function scopeOnDate(EloquentBuilder $query, Carbon $date)
{
@@ -207,6 +354,7 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param array $types
*/
@@ -231,7 +379,7 @@ class TransactionJournal extends Model
public function scopeWithRelevantData(EloquentBuilder $query)
{
$query->with(
['transactions' => function (HasMany $q) {
['transactions' => function(HasMany $q) {
$q->orderBy('amount', 'ASC');
}, 'transactiontype', 'transactioncurrency', 'budgets', 'categories', 'transactions.account.accounttype', 'bill', 'budgets', 'categories']
);
@@ -239,6 +387,7 @@ class TransactionJournal extends Model
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setDescriptionAttribute($value)
@@ -247,15 +396,6 @@ class TransactionJournal extends Model
$this->attributes['encrypted'] = true;
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('FireflyIII\Models\Tag');
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo

View File

@@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class TransactionRelation
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class TransactionRelation extends Model

View File

@@ -6,8 +6,19 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class TransactionType
*
* @codeCoverageIgnore
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at
* @property string $type
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionJournals
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereType($value)
*/
class TransactionType extends Model
{

View File

@@ -6,6 +6,8 @@ use Illuminate\Support\ServiceProvider;
* Class AppServiceProvider
*
* @package FireflyIII\Providers
*
* @codeCoverageIgnore
*/
class AppServiceProvider extends ServiceProvider
{

View File

@@ -6,6 +6,8 @@ use Illuminate\Support\ServiceProvider;
/**
* Class BusServiceProvider
*
* @codeCoverageIgnore
*
* @package FireflyIII\Providers
*/
class BusServiceProvider extends ServiceProvider
@@ -21,7 +23,7 @@ class BusServiceProvider extends ServiceProvider
public function boot(Dispatcher $dispatcher)
{
$dispatcher->mapUsing(
function ($command) {
function($command) {
return Dispatcher::simpleMapping(
$command, 'FireflyIII\Commands', 'FireflyIII\Handlers\Commands'
);

View File

@@ -6,6 +6,8 @@ use Illuminate\Support\ServiceProvider;
* Class ConfigServiceProvider
*
* @package FireflyIII\Providers
* @codeCoverageIgnore
*
*/
class ConfigServiceProvider extends ServiceProvider
{
@@ -17,235 +19,13 @@ class ConfigServiceProvider extends ServiceProvider
* to overwrite any "vendor" or package configuration that you may want to
* modify before the application handles the incoming request / command.
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*
* @return void
*/
public function register()
{
config(
[
'twigbridge' => [
'twig' => [
/*
|--------------------------------------------------------------------------
| Extension
|--------------------------------------------------------------------------
|
| File extension for Twig view files.
|
*/
'extension' => 'twig',
/*
|--------------------------------------------------------------------------
| Accepts all Twig environment configuration options
|--------------------------------------------------------------------------
|
| http://twig.sensiolabs.org/doc/api.html#environment-options
|
*/
'environment' => [
// When set to true, the generated templates have a __toString() method
// that you can use to display the generated nodes.
// default: false
'debug' => config('app.debug', false),
// The charset used by the templates.
// default: utf-8
'charset' => 'utf-8',
// The base template class to use for generated templates.
// default: TwigBridge\Twig\Template
'base_template_class' => 'TwigBridge\Twig\Template',
// An absolute path where to store the compiled templates, or false to disable caching. If null
// then the cache file path is used.
// default: cache file storage path
'cache' => null,
// When developing with Twig, it's useful to recompile the template
// whenever the source code changes. If you don't provide a value
// for the auto_reload option, it will be determined automatically based on the debug value.
'auto_reload' => true,
// If set to false, Twig will silently ignore invalid variables
// (variables and or attributes/methods that do not exist) and
// replace them with a null value. When set to true, Twig throws an exception instead.
// default: false
'strict_variables' => false,
// If set to true, auto-escaping will be enabled by default for all templates.
// default: true
'autoescape' => true,
// A flag that indicates which optimizations to apply
// (default to -1 -- all optimizations are enabled; set it to 0 to disable)
'optimizations' => -1,
],
/*
|--------------------------------------------------------------------------
| Global variables
|--------------------------------------------------------------------------
|
| These will always be passed in and can be accessed as Twig variables.
| NOTE: these will be overwritten if you pass data into the view with the same key.
|
*/
'globals' => [],
],
'extensions' => [
/*
|--------------------------------------------------------------------------
| Extensions
|--------------------------------------------------------------------------
|
| Enabled extensions.
|
| `Twig_Extension_Debug` is enabled automatically if twig.debug is TRUE.
|
*/
'enabled' => [
'TwigBridge\Extension\Loader\Facades',
'TwigBridge\Extension\Loader\Filters',
'TwigBridge\Extension\Loader\Functions',
'TwigBridge\Extension\Laravel\Auth',
'TwigBridge\Extension\Laravel\Config',
'TwigBridge\Extension\Laravel\Dump',
'TwigBridge\Extension\Laravel\Input',
'TwigBridge\Extension\Laravel\Session',
'TwigBridge\Extension\Laravel\String',
'TwigBridge\Extension\Laravel\Translator',
'TwigBridge\Extension\Laravel\Url',
// 'TwigBridge\Extension\Laravel\Form',
// 'TwigBridge\Extension\Laravel\Html',
// 'TwigBridge\Extension\Laravel\Legacy\Facades',
],
/*
|--------------------------------------------------------------------------
| Facades
|--------------------------------------------------------------------------
|
| Available facades. Access like `{{ Config.get('foo.bar') }}`.
|
| Each facade can take an optional array of options. To mark the whole facade
| as safe you can set the option `'is_safe' => true`. Setting the facade as
| safe means that any HTML returned will not be escaped.
|
| It is advisable to not set the whole facade as safe and instead mark the
| each appropriate method as safe for security reasons. You can do that with
| the following syntax:
|
| <code>
| 'Form' => [
| 'is_safe' => [
| 'open'
| ]
| ]
| </code>
|
| The values of the `is_safe` array must match the called method on the facade
| in order to be marked as safe.
|
*/
'facades' => [
'Breadcrumbs' => [
'is_safe' => [
'renderIfExists'
]
],
'Session',
'Route',
'Auth',
'URL',
'Config',
'ExpandedForm' => [
'is_safe' => [
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
'multiRadio'
]
],
'Form' => [
'is_safe' => [
'input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea'
]
],
],
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| Available functions. Access like `{{ secure_url(...) }}`.
|
| Each function can take an optional array of options. These options are
| passed directly to `Twig_SimpleFunction`.
|
| So for example, to mark a function as safe you can do the following:
|
| <code>
| 'link_to' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| function differently in your Twig templates than what it's actually called.
|
| <code>
| 'link' => [
| 'callback' => 'link_to'
| ]
| </code>
|
*/
'functions' => [
'elixir',
'head',
'last',
'old'
],
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Available filters. Access like `{{ variable|filter }}`.
|
| Each filter can take an optional array of options. These options are
| passed directly to `Twig_SimpleFilter`.
|
| So for example, to mark a filter as safe you can do the following:
|
| <code>
| 'studly_case' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| filter differently in your Twig templates than what is actually called.
|
| <code>
| 'snake' => [
| 'callback' => 'snake_case'
| ]
| </code>
|
*/
'filters' => [],
],
]
]
);
}
}

View File

@@ -49,65 +49,16 @@ class EventServiceProvider extends ServiceProvider
public function boot(DispatcherContract $events)
{
parent::boot($events);
TransactionJournal::deleted(
function (TransactionJournal $journal) {
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
$transaction->delete();
}
}
);
PiggyBank::deleting(
function (PiggyBank $piggyBank) {
$reminders = $piggyBank->reminders()->get();
/** @var Reminder $reminder */
foreach ($reminders as $reminder) {
$reminder->delete();
}
}
);
Account::deleted(
function (Account $account) {
/** @var Transaction $transaction */
foreach ($account->transactions()->get() as $transaction) {
$journal = $transaction->transactionJournal()->first();
$journal->delete();
}
}
);
// move this routine to a filter
// in case of repeated piggy banks and/or other problems.
PiggyBank::created(
function (PiggyBank $piggyBank) {
$repetition = new PiggyBankRepetition;
$repetition->piggyBank()->associate($piggyBank);
$repetition->startdate = is_null($piggyBank->startdate) ? null : $piggyBank->startdate;
$repetition->targetdate = is_null($piggyBank->targetdate) ? null : $piggyBank->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
);
$this->registerDeleteEvents();
$this->registerCreateEvents();
BudgetLimit::saved(
function (BudgetLimit $budgetLimit) {
function(BudgetLimit $budgetLimit) {
$end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0);
$end->subDay();
$set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))
->get();
/*
* Create new LimitRepetition:
*/
->get();
if ($set->count() == 0) {
$repetition = new LimitRepetition;
$repetition->startdate = $budgetLimit->startdate;
$repetition->enddate = $end;
@@ -122,9 +73,6 @@ class EventServiceProvider extends ServiceProvider
}
} else {
if ($set->count() == 1) {
/*
* Update existing one.
*/
$repetition = $set->first();
$repetition->amount = $budgetLimit->amount;
$repetition->save();
@@ -137,4 +85,61 @@ class EventServiceProvider extends ServiceProvider
}
/**
*
*/
protected function registerDeleteEvents()
{
TransactionJournal::deleted(
function(TransactionJournal $journal) {
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
$transaction->delete();
}
}
);
PiggyBank::deleting(
function(PiggyBank $piggyBank) {
$reminders = $piggyBank->reminders()->get();
/** @var Reminder $reminder */
foreach ($reminders as $reminder) {
$reminder->delete();
}
}
);
Account::deleted(
function(Account $account) {
/** @var Transaction $transaction */
foreach ($account->transactions()->get() as $transaction) {
$journal = $transaction->transactionJournal()->first();
$journal->delete();
}
}
);
}
/**
*
*/
protected function registerCreateEvents()
{
// move this routine to a filter
// in case of repeated piggy banks and/or other problems.
PiggyBank::created(
function(PiggyBank $piggyBank) {
$repetition = new PiggyBankRepetition;
$repetition->piggyBank()->associate($piggyBank);
$repetition->startdate = is_null($piggyBank->startdate) ? null : $piggyBank->startdate;
$repetition->targetdate = is_null($piggyBank->targetdate) ? null : $piggyBank->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
);
}
}

View File

@@ -10,9 +10,9 @@ use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam;
use FireflyIII\Support\Twig\Budget;
use FireflyIII\Support\Twig\General;
use FireflyIII\Support\Twig\Translation;
use FireflyIII\Support\Twig\Journal;
use FireflyIII\Support\Twig\PiggyBank;
use FireflyIII\Support\Twig\Translation;
use FireflyIII\Validation\FireflyValidator;
use Illuminate\Support\ServiceProvider;
use Twig;
@@ -23,13 +23,14 @@ use Validator;
* Class FireflyServiceProvider
*
* @package FireflyIII\Providers
* @codeCoverageIgnore
*/
class FireflyServiceProvider extends ServiceProvider
{
public function boot()
{
Validator::resolver(
function ($translator, $data, $rules, $messages) {
function($translator, $data, $rules, $messages) {
return new FireflyValidator($translator, $data, $rules, $messages);
}
);
@@ -46,33 +47,36 @@ class FireflyServiceProvider extends ServiceProvider
Twig::addExtension(new Translation);
}
/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function register()
{
$this->app->bind(
'preferences', function () {
'preferences', function() {
return new Preferences;
}
);
$this->app->bind(
'navigation', function () {
'navigation', function() {
return new Navigation;
}
);
$this->app->bind(
'amount', function () {
'amount', function() {
return new Amount;
}
);
$this->app->bind(
'steam', function () {
'steam', function() {
return new Steam;
}
);
$this->app->bind(
'expandedform', function () {
'expandedform', function() {
return new ExpandedForm;
}
);

View File

@@ -7,6 +7,7 @@ use Illuminate\Routing\Router;
* Class RouteServiceProvider
*
* @package FireflyIII\Providers
* @codeCoverageIgnore
*/
class RouteServiceProvider extends ServiceProvider
{
@@ -43,7 +44,7 @@ class RouteServiceProvider extends ServiceProvider
public function map(Router $router)
{
$router->group(
['namespace' => $this->namespace], function ($router) {
['namespace' => $this->namespace], function($router) {
/** @noinspection PhpIncludeInspection */
require app_path('Http/routes.php');
}

View File

@@ -8,6 +8,7 @@ use Illuminate\Support\ServiceProvider;
/**
* Class TestingServiceProvider
*
* @codeCoverageIgnore
* @package FireflyIII\Providers
*/
class TestingServiceProvider extends ServiceProvider

View File

@@ -25,6 +25,8 @@ use Steam;
/**
* @SuppressWarnings(PHPMD.TooManyMethods)
*
* Class AccountRepository
*
* @package FireflyIII\Repositories\Account
@@ -62,7 +64,7 @@ class AccountRepository implements AccountRepositoryInterface
public function getAccounts(array $types)
{
$result = Auth::user()->accounts()->with(
['accountmeta' => function (HasMany $query) {
['accountmeta' => function(HasMany $query) {
$query->where('name', 'accountRole');
}]
)->accountTypeIn($types)->orderBy('accounts.name', 'ASC')->get(['accounts.*'])->sortBy('name');
@@ -77,15 +79,15 @@ class AccountRepository implements AccountRepositoryInterface
public function getCreditCards()
{
return Auth::user()->accounts()
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole'
]
);
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole'
]
);
}
/**
@@ -130,18 +132,18 @@ class AccountRepository implements AccountRepositoryInterface
public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end)
{
return Auth::user()
->transactionjournals()
->with(['transactions'])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->after($start)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->take(10)
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
->transactionjournals()
->with(['transactions'])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->after($start)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->take(10)
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
}
/**
@@ -154,16 +156,14 @@ class AccountRepository implements AccountRepositoryInterface
{
$offset = ($page - 1) * 50;
$query = Auth::user()
->transactionJournals()
->withRelevantData()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
->transactionJournals()
->withRelevantData()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
$query->before(Session::get('end', Carbon::now()->endOfMonth()));
$query->after(Session::get('start', Carbon::now()->startOfMonth()));
$count = $query->count();
$set = $query->take(50)->offset($offset)->get(['transaction_journals.*']);
$paginator = new LengthAwarePaginator($set, $count, 50, $page);
@@ -213,7 +213,7 @@ class AccountRepository implements AccountRepositoryInterface
}
$accounts->each(
function (Account $account) use ($start, $end) {
function(Account $account) use ($start, $end) {
$account->startBalance = Steam::balance($account, $start, true);
$account->endBalance = Steam::balance($account, $end, true);
$account->piggyBalance = 0;
@@ -251,7 +251,7 @@ class AccountRepository implements AccountRepositoryInterface
$end = clone Session::get('end', new Carbon);
$accounts->each(
function (Account $account) use ($start, $end) {
function(Account $account) use ($start, $end) {
$account->startBalance = Steam::balance($account, $start);
$account->endBalance = Steam::balance($account, $end);
@@ -289,31 +289,42 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function getTransfersInRange(Account $account, Carbon $start, Carbon $end)
{
return TransactionJournal::whereIn(
'id', function (Builder $q) use ($account, $start, $end) {
$set = TransactionJournal::whereIn(
'id', function(Builder $q) use ($account, $start, $end) {
$q->select('transaction_journals.id')
->from('transactions')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transactions.account_id', $account->id)
->where('transaction_journals.user_id', Auth::user()->id)
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transactions.amount', '>', 0)
->where('transaction_types.type', 'Transfer');
->from('transactions')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transactions.account_id', $account->id)
->where('transaction_journals.user_id', Auth::user()->id)
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_types.type', 'Transfer');
}
)->get();
$filtered = $set->filter(
function(TransactionJournal $journal) use ($account) {
if ($journal->destination_account->id == $account->id) {
return $journal;
}
return null;
}
);
return $filtered;
}
/**
* @param Account $account
* @param Carbon $date
*
* @return float
*/
public function leftOnAccount(Account $account)
public function leftOnAccount(Account $account, Carbon $date)
{
$balance = Steam::balance($account, null, true);
$balance = Steam::balance($account, $date, true);
/** @var PiggyBank $p */
foreach ($account->piggybanks()->get() as $p) {
$balance -= $p->currentRelevantRep()->currentamount;
@@ -331,15 +342,15 @@ class AccountRepository implements AccountRepositoryInterface
public function openingBalanceTransaction(Account $account)
{
return TransactionJournal::accountIs($account)
->orderBy('transaction_journals.date', 'ASC')
->orderBy('created_at', 'ASC')
->first(['transaction_journals.*']);
->orderBy('transaction_journals.date', 'ASC')
->orderBy('created_at', 'ASC')
->first(['transaction_journals.*']);
}
/**
* @param array $data
*
* @return Account;
* @return Account
*/
public function store(array $data)
{
@@ -357,7 +368,7 @@ class AccountRepository implements AccountRepositoryInterface
'name' => $data['name'] . ' initial balance',
'active' => false,
];
$opposing = $this->storeAccount($opposingData);
$opposing = $this->storeAccount($opposingData);
$this->storeInitialBalance($newAccount, $opposing, $data);
}
@@ -390,7 +401,6 @@ class AccountRepository implements AccountRepositoryInterface
// update meta data:
$this->updateMetadata($account, $data);
$openingBalance = $this->openingBalanceTransaction($account);
// if has openingbalance?
@@ -408,15 +418,13 @@ class AccountRepository implements AccountRepositoryInterface
'name' => $data['name'] . ' initial balance',
'active' => false,
];
$opposing = $this->storeAccount($opposingData);
$opposing = $this->storeAccount($opposingData);
$this->storeInitialBalance($account, $opposing, $data);
}
} else {
// opening balance is zero, should we delete it?
if ($openingBalance) {
// delete existing opening balance.
$openingBalance->delete();
if ($openingBalance) { // opening balance is zero, should we delete it?
$openingBalance->delete(); // delete existing opening balance.
}
}
@@ -443,7 +451,7 @@ class AccountRepository implements AccountRepositoryInterface
if (!$newAccount->isValid()) {
// does the account already exist?
$searchData = [
$searchData = [
'user_id' => $data['user'],
'account_type_id' => $accountType->id,
'name' => $data['name']

View File

@@ -115,10 +115,11 @@ interface AccountRepositoryInterface
/**
* @param Account $account
* @param Carbon $date
*
* @return float
*/
public function leftOnAccount(Account $account);
public function leftOnAccount(Account $account, Carbon $date);
/**
* @param Account $account

View File

@@ -5,14 +5,10 @@ namespace FireflyIII\Repositories\Bill;
use Auth;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Log;
use Navigation;
/**
@@ -22,6 +18,27 @@ use Navigation;
*/
class BillRepository implements BillRepositoryInterface
{
/**
* Returns the sum of all payments connected to this bill between the dates.
*
* @param Bill $bill
* @param Carbon $start
* @param Carbon $end
*
* @return integer
*/
public function billPaymentsInRange(Bill $bill, Carbon $start, Carbon $end)
{
$amount = 0;
$journals = $bill->transactionjournals()->before($end)->after($start)->get();
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$amount += $journal->amount;
}
return $amount;
}
/**
* Create a fake bill to help the chart controller.
*
@@ -50,7 +67,7 @@ class BillRepository implements BillRepositoryInterface
/**
* @param Bill $bill
*
* @return mixed
* @return boolean|null
*/
public function destroy(Bill $bill)
{
@@ -87,16 +104,10 @@ class BillRepository implements BillRepositoryInterface
public function getJournals(Bill $bill)
{
return $bill->transactionjournals()->withRelevantData()
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.amount', '>', 0);
}
)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->get(['transaction_journals.*', 'transactions.amount']);
->get(['transaction_journals.*']);
}
/**
@@ -198,7 +209,7 @@ class BillRepository implements BillRepositoryInterface
/**
* @param Bill $bill
*
* @return Carbon
* @return \Carbon\Carbon
*/
public function nextExpectedMatch(Bill $bill)
{
@@ -230,7 +241,7 @@ class BillRepository implements BillRepositoryInterface
$end = Navigation::endOfPeriod(clone $start, $bill->repeat_freq);
$journalCount = $bill->transactionjournals()->before($end)->after($start)->count();
if ($journalCount == 0) {
$finalDate = clone $start;
$finalDate = new Carbon($start->format('Y-m-d'));
break;
}
}
@@ -247,37 +258,15 @@ class BillRepository implements BillRepositoryInterface
* @param Bill $bill
* @param TransactionJournal $journal
*
* @return bool
* @return boolean|null
*/
public function scan(Bill $bill, TransactionJournal $journal)
{
/*
* Match words.
*/
$amountMatch = false;
$wordMatch = false;
$matches = explode(',', $bill->match);
$description = strtolower($journal->description);
Log::debug('Now scanning ' . $description);
/*
* Attach expense account to description for more narrow matching.
*/
$transactions = $journal->transactions()->get();
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
/** @var Account $account */
$account = $transaction->account()->first();
/** @var AccountType $type */
$type = $account->accountType()->first();
if ($type->type == 'Expense account' || $type->type == 'Beneficiary account') {
$description .= ' ' . strtolower($account->name);
}
}
Log::debug('Final description: ' . $description);
Log::debug('Matches searched: ' . join(':', $matches));
$count = 0;
$description = strtolower($journal->description) . ' ' . strtolower($journal->expense_account->name);
$count = 0;
foreach ($matches as $word) {
if (!(strpos($description, strtolower($word)) === false)) {
$count++;
@@ -285,38 +274,24 @@ class BillRepository implements BillRepositoryInterface
}
if ($count >= count($matches)) {
$wordMatch = true;
Log::debug('word match is true');
} else {
Log::debug('Count: ' . $count . ', count(matches): ' . count($matches));
}
/*
* Match amount.
*/
$amountMatch = false;
if (count($transactions) > 1) {
$amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount));
$min = floatval($bill->amount_min);
$max = floatval($bill->amount_max);
if ($amount >= $min && $amount <= $max) {
$amountMatch = true;
Log::debug('Amount match is true!');
}
if ($journal->amount >= $bill->amount_min && $journal->amount <= $bill->amount_max) {
$amountMatch = true;
}
/*
* If both, update!
*/
if ($wordMatch && $amountMatch) {
Log::debug('TOTAL match is true!');
$journal->bill()->associate($bill);
$journal->save();
} else {
if ((!$wordMatch || !$amountMatch) && $bill->id == $journal->bill_id) {
if ($bill->id == $journal->bill_id) {
// if no match, but bill used to match, remove it:
$journal->bill_id = null;
$journal->save();
@@ -356,7 +331,7 @@ class BillRepository implements BillRepositoryInterface
* @param Bill $bill
* @param array $data
*
* @return Bill|static
* @return Bill
*/
public function update(Bill $bill, array $data)
{

View File

@@ -15,6 +15,17 @@ use Illuminate\Support\Collection;
interface BillRepositoryInterface
{
/**
* Returns the sum of all payments connected to this bill between the dates.
*
* @param Bill $bill
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function billPaymentsInRange(Bill $bill, Carbon $start, Carbon $end);
/**
* Create a fake bill to help the chart controller.
*
@@ -92,7 +103,7 @@ interface BillRepositoryInterface
/**
* @param Bill $bill
*
* @return Carbon|null
* @return \Carbon\Carbon
*/
public function nextExpectedMatch(Bill $bill);

Some files were not shown because too many files have changed in this diff Show More