Compare commits

...

1043 Commits
3.3 ... 3.4.6.1

Author SHA1 Message Date
James Cole
fcb8b02da9 Merge branch 'release/3.4.6.1' 2015-07-03 10:32:31 +02:00
James Cole
c842113610 New read me. 2015-07-03 10:32:16 +02:00
James Cole
974a8b3b70 Merge branch 'master' of https://github.com/JC5/firefly-iii
# By Richard Ebbers
# Via James Cole (2) and Richard Ebbers (1)
* 'master' of https://github.com/JC5/firefly-iii:
  updated authentication pages to use dynamic urls
  use relative path in login screen
2015-07-03 10:30:57 +02:00
Richard Ebbers
2e20c99ada updated authentication pages to use dynamic urls 2015-07-03 10:30:32 +02:00
Richard Ebbers
aa88ff6f2c use relative path in login screen 2015-07-03 10:30:32 +02:00
James Cole
5e6aa63d03 Merge pull request #86 from ebbz/master
use relative path in login screen improved
2015-07-03 10:29:35 +02:00
Richard Ebbers
f08c6efb00 updated authentication pages to use dynamic urls 2015-07-03 09:37:59 +02:00
James Cole
1ffa8c5e72 Removed code coverage logic. 2015-07-03 07:33:43 +02:00
James Cole
d855ccb8a7 Removed help button for small layouts [skip ci] 2015-07-03 07:28:20 +02:00
James Cole
d88919474b Reversed codeception. 2015-07-03 07:27:01 +02:00
James Cole
e139664301 Revert "Some updates to unit tests."
This reverts commit 5adf5f6e3f.
2015-07-03 07:25:07 +02:00
James Cole
5adf5f6e3f Some updates to unit tests. 2015-07-03 07:24:34 +02:00
James Cole
aef2075c8e Cleanup test case. 2015-07-02 09:49:45 +02:00
James Cole
922b2962a3 Bootstrap codeception. 2015-07-02 09:45:21 +02:00
James Cole
b4a401700e Installed codeception. 2015-07-02 09:44:56 +02:00
James Cole
e9601bb9c1 Add codeception. 2015-07-02 09:36:43 +02:00
James Cole
58af3dc6ea Removed everything related to unit tests. Can restore later. 2015-07-02 08:51:53 +02:00
Richard Ebbers
074295df61 use relative path in login screen 2015-07-01 20:03:43 +02:00
James Cole
ec349b31c7 Fixed tests. 2015-07-01 16:41:59 +02:00
James Cole
5ae236e016 With tooltips. 2015-07-01 15:08:09 +02:00
James Cole
d7c5897aba Optimise bootstrap. [skip ci] 2015-07-01 15:04:56 +02:00
James Cole
5252e7efe7 Cleanup css [skip ci] 2015-07-01 15:02:27 +02:00
James Cole
fc7d65629a Reorder bill chart [skip ci] 2015-07-01 13:18:50 +02:00
James Cole
f28fdf8252 Fixed chart tooltip [skip ci] 2015-07-01 11:08:14 +02:00
James Cole
5d07c4a949 Add date format to category charts [skip ci] 2015-07-01 11:07:10 +02:00
James Cole
fdd9eaab4b Added a better date for some budget charts [skip ci] 2015-07-01 11:04:08 +02:00
James Cole
e0d863a46f Create bills in test data, sort them [skip ci] 2015-07-01 10:52:42 +02:00
James Cole
3aacb6f5f3 New packages, updated read me, new composer.lock 2015-06-29 16:42:38 +02:00
James Cole
428e331b3e Reinstated the help button. 2015-06-29 15:23:50 +02:00
James Cole
847e05e9a7 Small experimental fix [skip ci] 2015-06-29 12:34:31 +02:00
James Cole
087eb5dbe6 Merge branch 'release/3.4.6' into develop 2015-06-29 09:53:26 +02:00
James Cole
f15932b2ac Merge branch 'release/3.4.6' 2015-06-29 09:53:25 +02:00
James Cole
d3a4c3795d New version. 2015-06-29 09:53:10 +02:00
James Cole
b15d55e1d9 Ignore untestable stuff. 2015-06-29 09:23:39 +02:00
James Cole
4f5889cc5b New tests for navigation. 2015-06-29 09:14:39 +02:00
James Cole
bf2a104a4e Fixed some tests. 2015-06-29 07:59:06 +02:00
James Cole
0c6dd5cd16 Removed some dead code. 2015-06-29 07:22:51 +02:00
James Cole
5efb06a7aa Removed unused code. 2015-06-29 07:17:39 +02:00
James Cole
b13acef272 Removed some dead code. 2015-06-29 07:16:43 +02:00
James Cole
cfa67d6c0f Implemented google chart tests. 2015-06-28 21:33:39 +02:00
James Cole
e70444f19a Fixed the bug that would unintentionally not let you edit accounts without changing their name. Closed #83 2015-06-28 21:13:08 +02:00
James Cole
0258982e60 Implemented two google chart tests. 2015-06-28 20:56:04 +02:00
James Cole
70eed5cb5e New tests. 2015-06-28 18:00:11 +02:00
James Cole
a650fa51f7 Implemented bill chart JS test. 2015-06-28 16:41:12 +02:00
James Cole
cb205580d8 First test for chartJS. 2015-06-28 16:20:14 +02:00
James Cole
f9329aac00 Removed unnecessary html tags. [skip ci] 2015-06-28 13:09:20 +02:00
James Cole
745f4a7523 Small chart and layout fixes [skip ci] 2015-06-28 13:07:23 +02:00
James Cole
60254dafd7 Implemented a forgotten chart. 2015-06-28 12:41:58 +02:00
James Cole
a8d60388ba New (empty) tests. 2015-06-28 10:38:51 +02:00
James Cole
83ec60254c New tests. 2015-06-28 10:03:34 +02:00
James Cole
c15c45f765 Some small fixes. 2015-06-28 08:42:06 +02:00
James Cole
cbe52b5089 Optimised chart generation. 2015-06-28 08:33:23 +02:00
James Cole
e4e2921f3e Fixed some tests. 2015-06-28 08:24:12 +02:00
James Cole
4673170531 Restored some cache [skip ci] 2015-06-27 22:22:27 +02:00
James Cole
2c2ed26c38 Optimise some charts [skip ci] 2015-06-27 22:11:03 +02:00
James Cole
94be5244fe Final chart. First version. 2015-06-27 20:52:06 +02:00
James Cole
f137a08493 Implemented some more charts. 2015-06-27 20:39:50 +02:00
James Cole
48624d0a34 A new chart, single count. 2015-06-27 17:38:16 +02:00
James Cole
4cceb3ddaa Completed the index. 2015-06-27 17:32:52 +02:00
James Cole
f728395603 Added some more charts 2015-06-27 17:05:39 +02:00
James Cole
3e82d43807 Expand some code to generate chartJS charts. 2015-06-27 16:01:06 +02:00
James Cole
2194c4e0a9 Expand some layouts to accept chartJS charts. 2015-06-27 16:00:50 +02:00
James Cole
c581080f3f Added option for other charts (chartJS currently). 2015-06-27 12:21:04 +02:00
James Cole
f6b1ec27e5 Renamed google chart methods and data. 2015-06-27 12:04:53 +02:00
James Cole
368b183230 Fixed category chart [skip ci] 2015-06-27 11:46:14 +02:00
James Cole
9028ad36ad Moved charts to separate generators. 2015-06-27 11:44:18 +02:00
James Cole
6cc041cd39 Fixed the chart generator. 2015-06-27 08:38:27 +02:00
James Cole
63ff01e78d Outsourced a chart to a specialised Google chart thing. 2015-06-27 08:18:47 +02:00
James Cole
9e5484937e Code cleanup [skip ci] 2015-06-27 08:06:24 +02:00
James Cole
b8ed489b14 Updated the read me [skip ci] 2015-06-27 07:55:59 +02:00
James Cole
765152d04b Reimplemented GA code. [skip ci] 2015-06-26 05:19:11 +02:00
James Cole
14934367d8 Simplified account name for cash accounts. 2015-06-26 04:57:30 +02:00
James Cole
04164500c8 Optimised some layout things. 2015-06-25 17:06:20 +02:00
James Cole
5160f2c298 Some new tests and a bug fix for piggy banks. 2015-06-24 21:02:34 +02:00
James Cole
124c9303b9 This should fix the tests. 2015-06-23 22:13:13 +02:00
James Cole
cd27f0ad69 Some database and css fixes. [skip ci] 2015-06-23 21:14:21 +02:00
James Cole
a7555bcce3 Some layout and file updates. 2015-06-23 19:07:37 +02:00
James Cole
6b5c4fd3f4 Merge branch 'master' of https://github.com/JC5/firefly-iii into develop
* 'master' of https://github.com/JC5/firefly-iii:
  New images [skip ci]
2015-06-23 07:40:50 +02:00
James Cole
cc55e2acee Lets see if this fixes the database. 2015-06-23 07:38:48 +02:00
James Cole
1511f75a80 Fixed tests. Broke database. 2015-06-22 22:04:46 +02:00
James Cole
f01bbefc1f Fixed tests. 2015-06-22 21:45:32 +02:00
James Cole
1d1eb5ffa8 Fix migration thing. 2015-06-22 21:37:02 +02:00
James Cole
a465cb2191 Remove all references to reminders. 2015-06-22 21:31:12 +02:00
James Cole
42d13e02ef New images [skip ci] 2015-06-22 21:04:31 +02:00
James Cole
d00786c43f Merge branch 'release/3.4.5' into develop 2015-06-22 19:12:05 +02:00
James Cole
4b47f99829 Merge branch 'release/3.4.5' 2015-06-22 19:12:04 +02:00
James Cole
35aaf40003 Updated composer file. 2015-06-22 19:11:17 +02:00
James Cole
cc5b4a1e02 Actually fix version [skip ci] 2015-06-22 19:03:03 +02:00
James Cole
7079521e8c Fix version in develop. 2015-06-22 19:02:28 +02:00
James Cole
b5025560a5 Merge branch 'feature/admin-lte' into develop 2015-06-22 18:59:36 +02:00
James Cole
3f4bdd7f0e Remove unnecessary code. 2015-06-22 18:58:19 +02:00
James Cole
e94bb9b549 Fixed some html errors [skip ci] 2015-06-22 18:50:54 +02:00
James Cole
1ddaacbef5 Some updated templates [skip ci] 2015-06-22 17:55:37 +02:00
James Cole
e8b40518e0 Hide boxes [skip ci] 2015-06-22 17:23:02 +02:00
James Cole
0f88cbb41b Fixed some layouts [skip ci] 2015-06-22 07:24:44 +02:00
James Cole
780d137b76 Fixed tests. 2015-06-21 16:10:32 +02:00
James Cole
ad8a9717d1 Fixed some views. [skip ci] 2015-06-21 15:09:10 +02:00
James Cole
9d6ea6b2f6 Some view updates [skip ci] 2015-06-21 11:59:35 +02:00
James Cole
7559383089 Cleaned up lots of views. 2015-06-21 10:50:45 +02:00
James Cole
f84381c927 Fixed search [skip ci] 2015-06-21 05:58:05 +02:00
James Cole
cb0122a43f Different colour scheme. [skip ci] 2015-06-21 05:48:47 +02:00
James Cole
6776b20989 Cleaned up tag views [skip ci] 2015-06-21 05:48:07 +02:00
James Cole
e98d556022 Some new templates and a bug fix [skip ci] 2015-06-20 22:18:54 +02:00
James Cole
5bf18b69d7 Smaller css footprint [skip ci] 2015-06-20 21:57:54 +02:00
James Cole
ea17f045a7 Added language stuff [skip ci] 2015-06-20 21:57:03 +02:00
James Cole
526f565ea7 Updated stuff from the control list. 2015-06-20 21:55:55 +02:00
James Cole
4aff9d6e73 Some more stuff done. Layout mostly. 2015-06-20 18:22:33 +02:00
James Cole
bf516d4d21 Fix some things. 2015-06-20 09:54:01 +02:00
James Cole
ae92e409d9 First functional run of new layout. 2015-06-20 07:48:44 +02:00
James Cole
4d017dc8a9 Updated boxes and what-not. 2015-06-20 07:29:25 +02:00
James Cole
707f4e2965 First implementation of new template. 2015-06-19 20:59:14 +02:00
James Cole
1c3bffdc50 Trigger a build. 2015-06-19 08:38:21 +02:00
James Cole
e54ddcb8b0 Small fix in edit form. [skip ci] 2015-06-18 18:12:57 +02:00
James Cole
ddefb0debc Improved tag view [skip ci] 2015-06-18 18:05:06 +02:00
James Cole
92d8dde90d Fixed sort commands [skip ci] 2015-06-17 06:11:35 +02:00
James Cole
1bb0508ddf Fix balance report [skip ci] 2015-06-16 18:34:19 +02:00
James Cole
a280a326b9 Fix report [skip ci] 2015-06-16 18:32:34 +02:00
James Cole
683e9b7c2c Small bugs in transaction controller [skip ci] 2015-06-16 18:26:17 +02:00
James Cole
a44e5da421 Add save routine to each transaction. [skip ci] 2015-06-16 06:52:30 +02:00
James Cole
8cd2c90ad7 Fixed menu in mobile [skip ci] 2015-06-15 20:24:58 +02:00
James Cole
5e57a390a2 Fixed tests. 2015-06-15 19:25:54 +02:00
James Cole
620848272e Implement tag count and fix a count thing. 2015-06-14 21:27:04 +02:00
James Cole
1e86794416 Add tag count to journal for easier amount calculations [skip ci] 2015-06-14 11:52:07 +02:00
James Cole
e36717259b Put tags in test data [skip ci] 2015-06-14 11:51:47 +02:00
James Cole
75b9238b90 Code cleanup [skip ci] 2015-06-14 11:51:33 +02:00
James Cole
ce5b20027e Newlines [skip ci] 2015-06-14 11:22:41 +02:00
James Cole
0de1242c83 Some cleaning up [skip ci] 2015-06-14 08:22:02 +02:00
James Cole
8bd445ab19 Some code cleanup [skip ci] 2015-06-13 10:02:36 +02:00
James Cole
fdef0de163 Increased test coverage. 2015-06-13 08:17:38 +02:00
James Cole
b1b03a4325 Upgrade to laravel 5.1 2015-06-11 21:19:40 +02:00
James Cole
0587d96474 Fixed tests [skip ci] 2015-06-11 20:14:15 +02:00
James Cole
c2241567e4 New translations. [skip ci] 2015-06-11 18:32:31 +02:00
James Cole
7ac24ba418 Some new translations [skip ci] 2015-06-09 17:56:08 +02:00
James Cole
c933ffec66 Quick fix in budget edit. [skip ci] 2015-06-09 16:20:37 +02:00
James Cole
e587d934b1 Switch menu around [skip ci] 2015-06-09 15:47:10 +02:00
James Cole
f354e90656 Some small menu optimisations. [skip ci] 2015-06-09 15:46:13 +02:00
James Cole
1b0bc7ec6e Clean up language. [skip ci] 2015-06-08 21:36:54 +02:00
James Cole
ee1acb9c00 Merge branch 'hotfix/3.4.4.2' 2015-06-08 18:52:30 +02:00
James Cole
06862a2812 Merge branch 'hotfix/3.4.4.2' into develop 2015-06-08 18:52:30 +02:00
James Cole
5fa87e18db Fix tag bug. (again) 2015-06-08 18:51:45 +02:00
James Cole
77989e2720 Fix read me. 2015-06-08 18:50:48 +02:00
James Cole
3a1102fa4e New code for auth controller [skip ci] 2015-06-08 18:42:19 +02:00
James Cole
8a9974ce53 New menu and new boxes [skip ci] 2015-06-08 18:41:47 +02:00
James Cole
4be8f1ca03 New email messages [skip ci] 2015-06-08 18:41:36 +02:00
James Cole
1ec2970ee3 Merge branch 'hotfix/3.4.4.1' 2015-06-08 18:41:02 +02:00
James Cole
81b3a22606 Merge branch 'hotfix/3.4.4.1' into develop 2015-06-08 18:41:02 +02:00
James Cole
f81a475cc9 Fixed a bug where the source and destination account could be the same one. 2015-06-08 18:40:52 +02:00
Sander Dorigo
d7ee03d4f9 New HTML view. 2015-06-08 09:48:53 +02:00
Sander Dorigo
c1c06410c2 Add HTML view. 2015-06-08 09:47:02 +02:00
James Cole
657d16bb60 Merge branch 'release/3.4.4' 2015-06-07 18:24:40 +02:00
James Cole
e65a4c1010 Merge branch 'release/3.4.4' into develop 2015-06-07 18:24:40 +02:00
James Cole
e23d3f5661 Mark a new release. 2015-06-07 18:24:23 +02:00
James Cole
e13611f7af Stupid faker messes up again. 2015-06-07 16:58:49 +02:00
James Cole
596cd09489 With a little luck this will cover a lot. 2015-06-07 15:32:01 +02:00
James Cole
0be5b27d34 Fixed some test coverage. 2015-06-07 10:28:26 +02:00
James Cole
a27471ae55 Fixed test. [skip ci] 2015-06-07 09:30:24 +02:00
James Cole
e27e3622a8 Fixed translation [skip ci] 2015-06-07 09:10:44 +02:00
James Cole
e95273b72b Simplified (or tried to) some code. [skip ci] 2015-06-07 09:09:27 +02:00
James Cole
583d4f3249 Cleanup scan method. [skip ci] 2015-06-07 08:13:19 +02:00
James Cole
d6967c4516 Cleaning up the relevantTags thing [skip ci] 2015-06-07 07:48:53 +02:00
James Cole
40b3097374 Lots of cleanup and stuff. 2015-06-06 23:09:12 +02:00
James Cole
1a1f127993 Cleanup code. 2015-06-06 17:40:41 +02:00
James Cole
a0f34a7ce1 Fix tests. 2015-06-06 16:26:26 +02:00
James Cole
db020db34b Fix tests and fix coverage. 2015-06-06 15:36:12 +02:00
James Cole
681167bc1b Some code cleanup. 2015-06-05 19:02:23 +02:00
James Cole
40e49ffc37 Some bug fixes and cleanup. 2015-06-05 16:49:16 +02:00
James Cole
834b1afb38 Updated some code [skip ci] 2015-06-05 13:39:24 +02:00
James Cole
62d5a1da87 Cleaning up [skip ci] 2015-06-05 12:48:58 +02:00
James Cole
8d8308e557 Cleanup another validator [skip ci] 2015-06-05 12:34:45 +02:00
James Cole
e1aa63487a Optimized a validator. [skip ci] 2015-06-05 12:18:20 +02:00
Sander Dorigo
b7fbe110d4 Merge pull request #82 from JC5/scrutinizer-patch-5
Scrutinizer Auto-Fixes
2015-06-05 11:39:08 +02:00
Scrutinizer Auto-Fixer
58859eb35a Scrutinizer Auto-Fixes
This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com
2015-06-05 08:40:26 +00:00
James Cole
4b7e1ae1c6 Removed duplicate code. 2015-06-05 10:02:40 +02:00
James Cole
3a06a6ac07 Removed unnecessary code. 2015-06-05 09:51:52 +02:00
James Cole
db0f269dc8 Fix class reference. 2015-06-05 09:50:59 +02:00
James Cole
3cabe6ca5a Improved test coverage. 2015-06-05 08:39:23 +02:00
James Cole
d483005219 Expanded some tests. 2015-06-05 07:49:07 +02:00
James Cole
fea9bc4e7e Increased coverage and fixed a nasty bug. 2015-06-05 07:10:51 +02:00
James Cole
d579992c98 Slightly improved test coverage. 2015-06-04 23:08:44 +02:00
James Cole
ad1c61d959 Improved test coverage. 2015-06-04 21:35:36 +02:00
James Cole
bb1da31830 Increase test coverage. 2015-06-04 17:43:50 +02:00
James Cole
a50949e554 Cache preferences. 2015-06-03 22:11:50 +02:00
James Cole
14dce8a10b Optimized preferences. 2015-06-03 21:58:06 +02:00
James Cole
1240c8f685 Update models [skip ci] 2015-06-03 21:27:36 +02:00
James Cole
cc7c2e952c Code cleanup [skip ci] 2015-06-03 21:25:11 +02:00
James Cole
409ec2e086 Should fix tests. 2015-06-03 21:15:52 +02:00
James Cole
a7f6848e53 Lots of stuff gets cached now. 2015-06-03 18:22:47 +02:00
James Cole
4b0b79199d Some cleanup. 2015-06-03 17:32:50 +02:00
Sander Dorigo
d1d6c48d9b Update GA code 2015-06-03 11:27:47 +02:00
James Cole
21631780bb Fix some tests 2015-06-02 22:22:47 +02:00
James Cole
b935e32340 Fix amount in tag list [skip ci] 2015-06-02 22:07:38 +02:00
James Cole
72dd064932 Fix count in transaction search [skip ci] 2015-06-02 21:58:30 +02:00
James Cole
2e75446665 Fixed some JS bugs [skip ci] 2015-06-02 18:13:23 +02:00
James Cole
be17e4481e Cache boxes. 2015-06-02 18:05:42 +02:00
James Cole
616c849b1f Fixed tests. 2015-06-02 17:58:30 +02:00
James Cole
71947c097f Some experiments with a cache control thing. [skip ci] 2015-06-02 17:44:50 +02:00
James Cole
546787802d Some code cleanup [skip ci] 2015-06-02 17:14:03 +02:00
James Cole
294d0e388a Add cache to main chart. 2015-06-01 18:41:18 +02:00
James Cole
193a1b0325 Basic tutorial for new users. 2015-06-01 18:13:54 +02:00
James Cole
12743217a2 Merge branch 'release/3.4.3' into develop 2015-06-01 17:37:03 +02:00
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
7b4bc23815 Merge branch 'release/3.4.0.5' 2015-05-10 19:18:57 +02:00
James Cole
9ca79f767c Merge branch 'release/3.4.0.5' into develop 2015-05-10 19:18:57 +02:00
James Cole
274dba7408 Update read me. 2015-05-10 19:18:49 +02:00
James Cole
31708ca29e Ignore some code. 2015-05-10 19:18:43 +02:00
James Cole
671b025588 More ignore stuff. 2015-05-10 13:40:29 +02:00
James Cole
a7956e4856 Adding lots of ignore statements because testing the models is pointless. 2015-05-10 13:22:00 +02:00
James Cole
355862025a Auth and password controller. 2015-05-10 13:06:02 +02:00
James Cole
a2a39ee0f8 Ignore piggy bank part. 2015-05-10 09:35:42 +02:00
James Cole
ec8e39c16f Fixed currency tests. 2015-05-10 09:26:44 +02:00
James Cole
88f714999e Add test to get full coverage. 2015-05-10 08:53:49 +02:00
James Cole
c0c2aa3be0 Fixed one test. 2015-05-10 08:49:15 +02:00
James Cole
822044820e Ignored more files. 2015-05-10 08:26:42 +02:00
James Cole
6ffc182142 Ignore lots of code in test coverage. 2015-05-10 08:08:07 +02:00
James Cole
3d54a78573 Tag repository tests 2015-05-10 07:48:33 +02:00
James Cole
8ddf7d953a Ignore constructor. 2015-05-10 07:09:21 +02:00
James Cole
8b9e9ad103 Tests for reminder repository. 2015-05-10 07:07:17 +02:00
James Cole
5737224c40 Simplified translations [skip ci] 2015-05-09 22:42:45 +02:00
James Cole
ec9aacbcae More new tests. 2015-05-09 22:30:16 +02:00
James Cole
9395454997 Small optimalizations [skip ci] 2015-05-09 19:27:25 +02:00
James Cole
66198a8d98 Expanded bread crumb [skip ci] 2015-05-09 19:23:37 +02:00
James Cole
96ed9a4256 Finished journal repository. 2015-05-09 18:30:58 +02:00
James Cole
10e54b2263 Tested part of the journal repository. 2015-05-09 18:11:48 +02:00
James Cole
cf00922ad2 Merge branch 'release/3.4.0.4' 2015-05-09 15:13:20 +02:00
James Cole
84e8e007a5 Merge branch 'release/3.4.0.4' into develop 2015-05-09 15:13:20 +02:00
James Cole
d07b2e773b Update read me 2015-05-09 15:13:14 +02:00
James Cole
506ef7b0b9 Covered currency repository. 2015-05-09 15:11:12 +02:00
James Cole
2cd5dae8e2 New read me [skip ci] 2015-05-09 15:08:56 +02:00
James Cole
a1cd49c111 First attempt at translations. 2015-05-09 13:56:03 +02:00
James Cole
aca2973aef Experimental chart [skip ci] 2015-05-09 13:55:07 +02:00
James Cole
0a7a691c95 Experimental chart [skip ci] 2015-05-09 13:53:58 +02:00
James Cole
72906a7afd Experimental chart [skip ci] 2015-05-09 13:52:33 +02:00
James Cole
d1a4a83570 Covered category repository. 2015-05-09 13:14:02 +02:00
James Cole
e0396b29e8 Add GA beacon [skip ci] 2015-05-09 10:43:37 +02:00
James Cole
536833cfe0 Fixed tests. 2015-05-09 10:25:52 +02:00
James Cole
317b02d1b9 Finished budget repository tests. 2015-05-09 10:23:13 +02:00
James Cole
75e279ea0d Update read me [skip ci] 2015-05-09 09:17:09 +02:00
James Cole
dc2ad21f4c Updated read me [skip ci] 2015-05-09 09:15:39 +02:00
James Cole
484d49aae1 Fixed tests 2015-05-09 09:15:27 +02:00
James Cole
ca39438ad4 Small update to the read me. [skip ci] 2015-05-09 09:11:54 +02:00
James Cole
49a65ebff4 New budget repository tests. 2015-05-09 09:05:37 +02:00
James Cole
befdc05084 Rewrote read me. [skip ci] 2015-05-08 19:34:03 +02:00
James Cole
1fbffe761b Merge branch 'release/3.4.0.3' into develop 2015-05-08 17:35:03 +02:00
James Cole
36aad379ff Merge branch 'release/3.4.0.3' 2015-05-08 17:35:02 +02:00
James Cole
540cfa072e Update read me. 2015-05-08 17:34:54 +02:00
James Cole
3b049c15cc Updated composer.json [skip ci] 2015-05-08 17:15:16 +02:00
James Cole
3e93ed0a17 Small JS fix. [skip ci] 2015-05-08 17:13:49 +02:00
James Cole
d7d9358136 Fix sorting [skip ci] 2015-05-08 17:04:24 +02:00
James Cole
5cf0939ff9 Fixed sorting [skip ci] 2015-05-08 17:03:20 +02:00
James Cole
8dc6f91d3c Add sort options. [skip ci] 2015-05-08 17:00:39 +02:00
James Cole
a3a25db230 New tests. 2015-05-08 16:44:57 +02:00
James Cole
c06f18c815 Some new tests 2015-05-08 14:00:49 +02:00
James Cole
6802f04036 First two tests for bill repository. 2015-05-08 12:50:39 +02:00
James Cole
beeccdf345 New (incomplete) tests [skip ci] 2015-05-08 12:44:42 +02:00
James Cole
58241ed39d Covered account repository. 2015-05-08 12:42:12 +02:00
James Cole
31128020f0 Merge branch 'release/3.4.0.2' 2015-05-08 07:57:06 +02:00
James Cole
6c48afc37b Merge branch 'release/3.4.0.2' into develop 2015-05-08 07:57:06 +02:00
James Cole
7a2f169dfc Push new version. 2015-05-08 07:56:55 +02:00
James Cole
ed910b99a7 Update travis configuration [skip ci] 2015-05-08 07:48:04 +02:00
James Cole
54195c0826 Updated tests. 2015-05-08 07:39:05 +02:00
James Cole
cefbbcd1df Fixed some tests. 2015-05-08 07:27:29 +02:00
James Cole
cc01592085 Cover some more account repository. 2015-05-08 06:01:39 +02:00
James Cole
5a98a5252d Added tests. 2015-05-07 21:26:00 +02:00
James Cole
184e8b1132 Some new tests. 2015-05-07 20:56:27 +02:00
James Cole
2b6b896c2e Some more coverage. 2015-05-06 18:09:45 +02:00
James Cole
96d06b7a93 Added incomplete tests. 2015-05-05 22:46:28 +02:00
James Cole
f54f1611b5 First tests for account repository. 2015-05-05 20:46:13 +02:00
James Cole
69ad757e8b Lazily remove todo's [skip ci] 2015-05-05 13:03:39 +02:00
James Cole
e0beb796ad Some cleaning up [skip ci] 2015-05-05 13:03:04 +02:00
James Cole
f331e7d820 Removed unnecessary imports (use statements) [skip ci] 2015-05-05 12:57:27 +02:00
James Cole
cbb62d3d78 Added new line at the end of files. [skip ci] 2015-05-05 12:51:57 +02:00
James Cole
c85bc59c1d Merge branch 'release/3.4.0.1' into develop 2015-05-05 12:35:23 +02:00
James Cole
8081eeb007 Merge branch 'release/3.4.0.1' 2015-05-05 12:35:22 +02:00
James Cole
56f91bd10d Increment version. 2015-05-05 12:35:11 +02:00
James Cole
8e20b78731 Cleanup. 2015-05-05 10:30:39 +02:00
James Cole
23a09b7081 Code cleanup. 2015-05-05 10:23:01 +02:00
James Cole
67fdd27499 Various code cleanup [skip ci] 2015-05-05 07:51:02 +02:00
James Cole
e1941daedd Updated phpdoc. [skip ci] 2015-05-05 07:48:34 +02:00
James Cole
f28bc568a4 Some cleanup [skip ci] 2015-05-05 07:43:16 +02:00
James Cole
f24cfe39aa Expanded some tests. 2015-05-05 07:41:30 +02:00
James Cole
59d2bf3f79 Covered transaction controller. 2015-05-05 07:28:04 +02:00
James Cole
3176e54614 Partial coverage of the transaction controller. 2015-05-04 23:46:14 +02:00
James Cole
eb090f7265 Better factory. 2015-05-04 22:33:52 +02:00
James Cole
6d3a9bfd18 Some cleaning up 2015-05-04 22:33:03 +02:00
James Cole
76f08b7acb Full coverage for chart controller. 2015-05-04 19:28:49 +02:00
James Cole
1ff99346aa Update chart [skip ci] 2015-05-04 18:51:51 +02:00
James Cole
369695ab32 Update chart [skip ci] 2015-05-04 18:51:38 +02:00
James Cole
7e23dd1d66 Update composer.lock [skip ci] 2015-05-04 18:45:32 +02:00
James Cole
0205d3fc5c Overspent transactions have a separate colour [skip ci] 2015-05-04 18:45:20 +02:00
James Cole
4660cf2ad5 Fixed a bug in the display of the current currency code. 2015-05-03 16:16:43 +02:00
James Cole
e26d08d674 Update git ignore. [skip ci] 2015-05-03 16:14:15 +02:00
James Cole
0932bf2797 Don't need these files [skip ci] 2015-05-03 16:13:38 +02:00
James Cole
f560fc6d76 Covered search controller. 2015-05-03 15:55:19 +02:00
James Cole
aa6209af00 Covered tag controller. 2015-05-03 15:00:39 +02:00
James Cole
4a51176193 General cleanup. 2015-05-03 12:58:55 +02:00
James Cole
bb84f7a434 Fixed parameter order [skip ci] 2015-05-03 12:54:39 +02:00
James Cole
48168b1ef0 Covered report controller. 2015-05-03 11:02:34 +02:00
James Cole
8281c7c83e Don't escape currency symbol [skip ci] 2015-05-03 10:11:16 +02:00
James Cole
a07c1e3c71 See code. [skip ci] 2015-05-03 10:07:18 +02:00
James Cole
0766bb31fe Better amount formatting [skip ci] 2015-05-03 10:03:50 +02:00
James Cole
ff4472c1a5 FormatAmountPlain is HTML safe [skip ci] 2015-05-03 10:01:38 +02:00
James Cole
17424740e5 Show plain amount instead of coloured amounts. [skip ci] 2015-05-03 10:00:47 +02:00
James Cole
dad0b2fcd3 Show plain amount instead of coloured amounts. [skip ci] 2015-05-03 10:00:03 +02:00
James Cole
c48dbf030f Covered the reminder controller. 2015-05-03 09:55:22 +02:00
James Cole
617808d603 Covered profile controller with tests. 2015-05-03 09:19:14 +02:00
James Cole
845149deee Boxes are empty, so even when it's zero, place the amount. 2015-05-03 08:56:44 +02:00
James Cole
1a9e009327 Merge branch 'release/3.4' into develop 2015-05-02 23:51:45 +02:00
James Cole
ae90815708 Merge branch 'release/3.4' 2015-05-02 23:51:44 +02:00
James Cole
1c460343b7 New version! 2015-05-02 23:51:34 +02:00
James Cole
26079622f9 Fixed JSON controller tests. 2015-05-02 23:39:39 +02:00
James Cole
06c6d6096f Fixed coverage. 2015-05-02 23:28:04 +02:00
James Cole
c8183aea51 Format amount [skip ci] 2015-05-02 22:50:40 +02:00
James Cole
7531134ad2 Some tag related fine tuning. 2015-05-02 22:41:32 +02:00
James Cole
cd0c6439c2 Delete tags now possible. 2015-05-02 22:30:59 +02:00
James Cole
c918c93f51 Forget me own head next. [skip ci] 2015-05-02 22:13:37 +02:00
James Cole
97d3bd68ed Show balance act tags. 2015-05-02 22:12:26 +02:00
James Cole
75f1e034ae Fixed menu. [skip ci] 2015-05-02 22:09:21 +02:00
James Cole
8e72f218f1 Show HTML 2015-05-02 22:05:57 +02:00
James Cole
d643e05c5a Basic amount format fix. 2015-05-02 22:05:18 +02:00
James Cole
fea44834d0 Fixed test to match fixed controller. 2015-05-02 21:22:27 +02:00
James Cole
195a2d7523 Removed all the old views. 2015-05-02 21:18:04 +02:00
James Cole
b2fd346ef8 Merge branch 'feature/twig' into develop 2015-05-02 21:16:21 +02:00
James Cole
1ff8b62cb7 And now with actual coverage. 2015-05-02 19:44:31 +02:00
James Cole
c7ae15a41a This should fix all twig tests. Let's find out! 2015-05-02 19:44:12 +02:00
James Cole
efe6f59f79 Last templates. Should cover everything. [skip ci] 2015-05-02 19:19:47 +02:00
James Cole
8e31d0491d Fixed search [skip ci] 2015-05-02 18:30:59 +02:00
James Cole
73d4a10351 Fixed reports [skip ci] 2015-05-02 18:26:55 +02:00
James Cole
81d9d4dbc7 Various files updated to twig [skip ci] 2015-05-02 13:20:49 +02:00
James Cole
184ec13f99 Fixed bills [skip ci] 2015-05-02 12:51:02 +02:00
James Cole
dee0422eff Fix preferences [skip ci] 2015-05-02 12:22:19 +02:00
James Cole
81a2975f1a Show piggy banks [skip ci] 2015-05-02 11:32:45 +02:00
James Cole
5cd2ef4a5e Some generic templates and the first piggy bank ones [skip ci] 2015-05-02 10:53:54 +02:00
James Cole
466c2a68c2 Add delete form [skip ci] 2015-05-02 10:42:41 +02:00
James Cole
0fb9fba531 New currency routes 2015-05-02 10:40:20 +02:00
James Cole
356dd2c6cd Creat / edit / index [skip ci] 2015-05-02 10:37:16 +02:00
James Cole
32c4661233 Fixed no budget / no category bread crumb [skip ci] 2015-05-02 09:49:37 +02:00
James Cole
a245b504ec Fixed bread crumbs. 2015-05-02 09:31:57 +02:00
James Cole
a2f5fbdfd3 Working on two more views [skip ci] 2015-05-02 09:29:34 +02:00
James Cole
04be26adc5 Fixed title [skip ci] 2015-05-02 09:26:20 +02:00
James Cole
be0adb7cf2 Create / edit category 2015-05-02 09:25:45 +02:00
James Cole
84fd92bf5a Categories [skip ci] 2015-05-02 09:21:42 +02:00
James Cole
ee4e061739 Removed code from budget index [skip ci] 2015-05-02 09:21:32 +02:00
James Cole
4a2b01cd9a Menu fixes [skip ci] 2015-05-02 09:16:17 +02:00
James Cole
efdd6460fb Fixed injection. 2015-05-02 09:08:41 +02:00
James Cole
803827e05c Fixed more views. [skip ci] 2015-05-02 09:06:07 +02:00
James Cole
a41d5e9ab3 New budget [skip ci] 2015-05-02 08:32:20 +02:00
James Cole
e94333f877 Can view budgets [skip ci] 2015-05-02 08:28:24 +02:00
James Cole
6dbb80d687 Optimisations [skip ci] 2015-05-02 08:09:54 +02:00
James Cole
31a1031624 And delete is fixed. 2015-05-01 23:39:45 +02:00
James Cole
f8e9ce0d52 Can edit as well. 2015-05-01 23:35:35 +02:00
James Cole
11baa968cd Can create accounts. 2015-05-01 23:17:17 +02:00
James Cole
3e5e5b376f Made it almost to the accounts. 2015-05-01 22:44:35 +02:00
James Cole
bda18f296d Optimised Twig extensions. 2015-05-01 20:17:06 +02:00
James Cole
287d110c84 Small bug fix in budget chart. 2015-05-01 18:45:42 +02:00
James Cole
c98275e73a More templates converted to twig. 2015-05-01 18:44:49 +02:00
James Cole
aa573cc951 Fix redirect 2015-05-01 14:32:31 +02:00
James Cole
883d3d86e3 Update a test. 2015-05-01 14:32:26 +02:00
James Cole
fb047bd5f4 Fix migration. 2015-05-01 08:34:53 +02:00
James Cole
66a04d8365 Slightly different chart on index. 2015-05-01 08:34:44 +02:00
James Cole
a0e501f9fd First attempt at implementing Twig. 2015-05-01 08:29:41 +02:00
James Cole
8b40d3346d An attempt at showing tag info. 2015-05-01 06:47:24 +02:00
James Cole
eddf5cd250 Fix button, close #74 2015-05-01 06:38:48 +02:00
James Cole
ee5c534ca3 Took the time to fix the tests. 2015-04-30 17:32:00 +02:00
James Cole
fd4e77ae0f Catch empty tags. 2015-04-28 21:01:54 +02:00
James Cole
b747c50aa3 Fix method to return object, not key. 2015-04-28 21:00:26 +02:00
James Cole
deebdd86a6 And another small JS fix [skip ci] 2015-04-28 20:20:16 +02:00
James Cole
b2db79cc10 Fixed some small CSS / JS problems. 2015-04-28 20:17:31 +02:00
James Cole
bbab370b1e Some new code. 2015-04-28 17:10:52 +02:00
James Cole
db4adf399d Cleaning up. 2015-04-28 15:26:30 +02:00
James Cole
0683c87e52 Small check in tags. 2015-04-28 14:08:58 +02:00
James Cole
3f62b647fc Removed code related to "related transactions". 2015-04-28 13:50:53 +02:00
James Cole
2562a5b30d Don't save all tags unconditionally. 2015-04-28 13:47:13 +02:00
James Cole
e232f2e223 Delete tags 2015-04-28 11:04:46 +02:00
James Cole
21644ff4dd Routes will throw 404's 2015-04-28 11:04:38 +02:00
James Cole
be96a4fce5 Show tags in transaction. 2015-04-28 10:51:56 +02:00
James Cole
a1cabcbed3 Show tag icons. 2015-04-28 10:50:43 +02:00
James Cole
ce933b1f06 Edit and update tags. 2015-04-28 10:36:13 +02:00
James Cole
51ae130922 Fixed the build by adding new migrations for each step. 2015-04-28 09:54:22 +02:00
James Cole
da1bc18a47 Better list for piggy banks. 2015-04-28 09:15:31 +02:00
James Cole
e7165a526b First attempt at basic tag functionality. 2015-04-28 08:58:01 +02:00
James Cole
6081cc399f Small bug fixes and cleaning up. 2015-04-28 08:12:12 +02:00
James Cole
7c5c24e15d Moved edit buttons. 2015-04-26 07:42:55 +02:00
James Cole
e3e55b4347 Moved all create-buttons lower. 2015-04-26 07:39:49 +02:00
James Cole
40d8e7d1ad Fixed a bug where transfers away from a piggy bank's account would not properly reflect the piggy bank. 2015-04-24 12:06:13 +02:00
James Cole
59e23b89f2 Removed unnecessary sort. 2015-04-24 11:54:23 +02:00
James Cole
cc33af8193 Could not set order. 2015-04-24 10:00:56 +02:00
James Cole
0e1e7eb2a9 Merge branch 'release/3.3.9' 2015-04-22 08:08:14 +02:00
James Cole
52a28a7758 Merge branch 'release/3.3.9' into develop 2015-04-22 08:08:14 +02:00
James Cole
3f752d6832 New read me. 2015-04-22 08:08:05 +02:00
James Cole
fe714e9989 Built a routine that will allow you to completely delete an account. 2015-04-22 07:54:56 +02:00
James Cole
0d3213a379 Covered the preferences controller. 2015-04-21 17:19:14 +02:00
James Cole
44056629e8 Use local db instead of constant migrating. 2015-04-20 22:08:24 +02:00
James Cole
54125c05d3 New tests and prep for future runs. 2015-04-20 21:57:20 +02:00
James Cole
7d32e50f25 Mentioned wrong amount. 2015-04-20 20:56:28 +02:00
James Cole
4af9ff49a0 Fixed a bug in the report controller that grouped transactions wrong. 2015-04-20 20:54:55 +02:00
James Cole
23faef845c Merge branch 'release/3.3.8' 2015-04-20 18:07:02 +02:00
James Cole
41dad4091a Merge branch 'release/3.3.8' into develop 2015-04-20 18:07:02 +02:00
James Cole
daf859b977 Updated read me. 2015-04-20 18:06:37 +02:00
James Cole
f47ba6c977 Update example file. 2015-04-20 18:06:21 +02:00
James Cole
4b9b207d92 Removed development references. 2015-04-20 17:59:04 +02:00
James Cole
875cbf66af 1 should be 0 2015-04-19 19:10:53 +02:00
James Cole
412d6d4fd7 Small CSS fix for piggy banks [skip ci] 2015-04-19 17:43:04 +02:00
James Cole
91c6deeb1f Renamed another field. 2015-04-19 14:28:17 +02:00
James Cole
6d1978fd9a Showed the wrong value. 2015-04-19 14:27:08 +02:00
James Cole
52d23b6ef5 Referred to an id which turned out to be a index. 2015-04-19 14:19:25 +02:00
James Cole
0656ccbdd9 Fixed a bug where the query would include deleted transactions. 2015-04-19 13:57:43 +02:00
James Cole
e774ebd0a3 Possible bug in account create thing. [skip ci] 2015-04-18 16:04:21 +02:00
James Cole
edbda32a84 Fix balance. 2015-04-13 21:13:05 +02:00
James Cole
721fa04e3c Added home screen information about piggy banks. 2015-04-13 20:43:58 +02:00
James Cole
9fd8d8915d amount > queryAmount 2015-04-12 10:53:53 +02:00
James Cole
7a9f5ebdd1 Added "what" variable. 2015-04-12 10:22:15 +02:00
James Cole
a3423f0321 Add the correct path to category overview. 2015-04-12 10:19:37 +02:00
James Cole
c37e9a4467 Covered the JSON controller. 2015-04-11 19:59:41 +02:00
James Cole
6157d82a0b time format 2015-04-11 18:52:03 +02:00
James Cole
38b27fec92 Without moment.js 2015-04-11 18:49:57 +02:00
James Cole
c43439bb68 Test for date. 2015-04-11 18:47:37 +02:00
James Cole
8d9561d7a5 Removed data-value. 2015-04-11 18:45:01 +02:00
James Cole
2a72cce3b7 Included date format. 2015-04-11 15:11:45 +02:00
James Cole
d3bbb6fb1f Removed date value. 2015-04-11 15:11:19 +02:00
James Cole
7b6723e9a2 Update date format. 2015-04-11 15:10:29 +02:00
James Cole
1ee741460d Updated empty entries as well. 2015-04-11 15:09:48 +02:00
James Cole
967b0b493b Switched dates around. 2015-04-11 15:07:42 +02:00
James Cole
b53aaf7dde Fixed sort format. 2015-04-11 15:06:10 +02:00
James Cole
714c13bdbf Include moment.js 2015-04-11 15:04:16 +02:00
James Cole
651a4fd3cc Sortable accounts. 2015-04-11 15:01:42 +02:00
James Cole
505aee22bb Sortable categories. 2015-04-11 14:53:22 +02:00
James Cole
ca3d59dc33 Another fix. 2015-04-11 12:51:58 +02:00
James Cole
13890e32a1 Fixed a view and a botched include. 2015-04-11 12:50:56 +02:00
James Cole
df8976eabe Journals that no longer match a bill will be removed. 2015-04-11 12:40:47 +02:00
James Cole
3e01daa172 Query & loop optimizations. 2015-04-11 12:36:17 +02:00
James Cole
f6999f355b Some foreach loop cleaning up. 2015-04-11 12:27:56 +02:00
James Cole
5c06b45eb1 Code cleanup. 2015-04-11 07:32:11 +02:00
James Cole
1802bb967a Moved JSON money boxes to individual functions. 2015-04-11 07:24:07 +02:00
James Cole
d8d92f147f Removed logging, found bug. 2015-04-10 07:29:36 +02:00
James Cole
4a95bdd8ba Added temporary debug to google chart. 2015-04-10 07:25:24 +02:00
James Cole
db5d94d956 Added temporary debug entries. 2015-04-10 07:19:45 +02:00
James Cole
06f2e34bb5 Renamed the amount variable so it stops interfering with another variable 2015-04-10 06:57:39 +02:00
James Cole
2ef7a01945 Fixed a bug where the bill chart and boxes would inaccurately reflect the amount of bills yet to pay. 2015-04-10 06:52:36 +02:00
James Cole
d3f642551d Fixed a small bug in the bill-chart and simplified yet another Json box. 2015-04-09 21:36:58 +02:00
James Cole
490997157e Switched two queries around. 2015-04-09 21:30:35 +02:00
James Cole
2432af7883 Simplified the in and out-box. 2015-04-09 21:29:58 +02:00
James Cole
7abeece3f0 Simplified the "out"-box. 2015-04-09 21:27:35 +02:00
James Cole
3851652821 Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. 2015-04-09 21:18:18 +02:00
James Cole
1d67d2250a Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. 2015-04-09 21:16:35 +02:00
James Cole
37f40d8637 Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. 2015-04-09 21:14:15 +02:00
James Cole
0224d1d59b Accidentally commented out date limits in query. 2015-04-09 21:01:08 +02:00
James Cole
587b94153d Removed some foreach() routines that are no longer necessary now that getAmountAttribute() exists. 2015-04-09 20:58:57 +02:00
James Cole
5124ce0302 Fixed a bug where getAmountAttribute would interfere with queries that contained a "amount"-field. 2015-04-09 20:52:47 +02:00
James Cole
950c4045b0 Fix total savings to accurately reflect end of current period. 2015-04-09 19:10:24 +02:00
James Cole
9c8ba66873 Order categories by name. 2015-04-09 17:54:24 +02:00
James Cole
25d1d1be1b Merge pull request #72 from vbali/feature/savings-total
Add savings total for savings widget on dashboard
2015-04-09 17:47:24 +02:00
James Cole
339c352505 Fixed a bug where categories would be created even though they already existed. 2015-04-09 17:46:47 +02:00
Balazs Varkonyi
c587081fe4 Add savings total for savings widget on dashboard 2015-04-09 11:52:35 +02:00
James Cole
8f9b1b866b Included full home controller tests. 2015-04-07 20:54:43 +02:00
James Cole
ff5ecf6182 More tests. 2015-04-07 19:58:49 +02:00
James Cole
05670cf393 Optimize test code. 2015-04-07 18:52:15 +02:00
James Cole
f10f5d30bf Mock previously unmocked calls. 2015-04-07 18:48:34 +02:00
James Cole
0d336727e8 Automated code cleanup. 2015-04-07 18:26:14 +02:00
James Cole
bf354275b3 Some general cleaning up. 2015-04-07 18:25:21 +02:00
James Cole
1932bf277a More tests 2015-04-07 17:51:22 +02:00
James Cole
192db4bb6e Accidentally included JS twice. 2015-04-07 10:14:20 +02:00
James Cole
701efb943d Lots of new tests. 2015-04-07 10:14:10 +02:00
James Cole
b2674971f1 Updated composer.lock. 2015-04-06 09:20:45 +02:00
James Cole
c907cb4cf1 General cleanup and new (incomplete) tests. 2015-04-06 09:15:59 +02:00
James Cole
bb1462b4d9 Merge branch 'release/3.3.7' 2015-04-05 21:15:01 +02:00
James Cole
1035f0e139 Merge branch 'release/3.3.7' into develop 2015-04-05 21:15:01 +02:00
James Cole
8475757716 Removed iconv() commented code. See other commit. 2015-04-05 21:14:41 +02:00
James Cole
20ffd8d61b New read me. 2015-04-05 21:14:25 +02:00
James Cole
8601428c4c Fixed a bug in the form request that wouldn't accept fairly long names. 2015-04-05 21:12:54 +02:00
James Cole
59998573ee Removed iconv thing that doesn't seem to matter. See screenshot at https://imgur.com/8r26ZZu 2015-04-05 21:12:31 +02:00
James Cole
293cd72001 Add currency tests. 2015-04-05 20:47:19 +02:00
James Cole
22ab9ebb2f Included tests for the category controller. 2015-04-05 19:43:20 +02:00
James Cole
9136e592d3 Included bill controller. 2015-04-05 18:20:06 +02:00
James Cole
ed8e392616 Fixed budget controller tests. 2015-04-05 15:53:03 +02:00
James Cole
e57ce6e644 Test now works. 2015-04-05 15:25:35 +02:00
James Cole
8204e46086 Removed inspiring quotes. 2015-04-05 10:38:53 +02:00
James Cole
9e365d9f80 Mar tests. 2015-04-05 10:36:28 +02:00
James Cole
6b40a933e9 And.. completed the account controller. 2015-04-04 22:53:49 +02:00
James Cole
8520a5002f Another attempt at fixing some tests. I'm probably searching in the wrong direction with this. 2015-04-04 22:27:51 +02:00
James Cole
b38ed06f6e New tests. 2015-04-04 21:52:56 +02:00
James Cole
48427b1143 A mediocre fix for the database failures. 2015-04-04 21:33:36 +02:00
James Cole
5d505f4ed0 Fixed more tests but the factories are not perfect yet. 2015-04-04 21:23:37 +02:00
James Cole
0c02a08954 Merge pull request #65 from vbali/master
Fixes for chart and account creation
2015-04-04 06:50:30 +02:00
Balazs Varkonyi
0221bd0f80 Merge branch 'hotfix/diff–fix' 2015-04-04 01:56:25 +02:00
Balazs Varkonyi
28216cbcb5 Removed merge conflict from CategoryController 2015-04-04 01:56:19 +02:00
Balazs Varkonyi
3e08a8cd6b Merge branch 'hotfix/account-fix' 2015-04-04 01:37:05 +02:00
Balazs Varkonyi
67fafdeef7 Return the new account from firstOrCreateEncrypted 2015-04-04 01:36:55 +02:00
Balazs Varkonyi
cc82505b66 Merge branch 'hotfix/chart-fix' 2015-04-04 01:33:36 +02:00
Balazs Varkonyi
fd5f075f63 Chart fix for accounts with accented letters 2015-04-04 01:31:57 +02:00
James Cole
a115960411 Merge branch 'release/3.3.6'
Conflicts:
	app/Http/Controllers/CategoryController.php
2015-04-03 23:31:29 +02:00
James Cole
e9fa4ca816 New version in read me. 2015-04-03 23:30:54 +02:00
James Cole
75d92bc7f0 Allow FF to send events. 2015-04-03 23:22:23 +02:00
James Cole
74aa6e911e Make boxes respond to unpaid / paid credit card bills. 2015-04-03 23:10:51 +02:00
James Cole
9d000c1898 Added amount because debug. 2015-04-03 23:05:50 +02:00
James Cole
b2254875b2 Expanded to credit cards. 2015-04-03 22:54:21 +02:00
James Cole
78d04230d5 New CC help text. 2015-04-03 21:25:04 +02:00
James Cole
1c04477393 Support credit cards (in name only). 2015-04-03 21:12:54 +02:00
James Cole
2a9679c94e Textual fix in bill [skip ci] 2015-04-03 21:05:41 +02:00
James Cole
6009f8ecde Better chart for bills. 2015-04-03 21:05:01 +02:00
James Cole
35cdbec70a Clean up for budget limits. 2015-04-03 19:39:36 +02:00
James Cole
0faef542c1 Fixed a bug in the budget controller. 2015-04-03 19:11:55 +02:00
James Cole
8b085af6a1 First attempt at account controller::index. 2015-04-03 12:14:40 +02:00
James Cole
e3b11a9eb2 New test for edit form that is more inclusive. 2015-04-03 09:30:44 +02:00
James Cole
72fc88f3c6 Even more tests. 2015-04-03 08:55:24 +02:00
James Cole
a5b759f268 Updates TestCase.php 2015-04-03 08:37:53 +02:00
James Cole
6a9ffae25d New tests and factories. 2015-04-03 08:31:50 +02:00
James Cole
64c031c7fe Small updates [skip ci] 2015-04-03 07:44:44 +02:00
James Cole
720926c50d Tests now run without a database, as they should. 2015-04-03 07:33:18 +02:00
James Cole
36ec974284 Add heavy but working migrate routine. Will fix the tests but must be optimised. Also, should not be necessary. 2015-04-02 22:51:00 +02:00
James Cole
cff77c39e2 Update travis-ci and composer.lock and composer.json 2015-04-02 22:46:50 +02:00
James Cole
056a0a1736 Smaller boxes. 2015-04-02 22:43:12 +02:00
James Cole
f301da83c6 Fixed the tests. 2015-04-02 22:39:31 +02:00
James Cole
5362231efa Ignore virtual balance in select places. 2015-04-01 19:46:16 +02:00
James Cole
4bb14cad73 Allow virtual balance to be ignored. 2015-04-01 19:45:13 +02:00
James Cole
7f5188f5a4 Added something fancy called "virtual balance". 2015-04-01 19:42:14 +02:00
James Cole
a80b7aac6c Fix more redirections. 2015-04-01 18:59:34 +02:00
James Cole
83f32478fa Fixed more redirections. 2015-04-01 09:43:19 +02:00
James Cole
7578ec6801 Fix redirections in budget. 2015-04-01 09:40:19 +02:00
James Cole
e14a32f76f Also fix delete/destroy redirection routine. 2015-04-01 09:23:51 +02:00
James Cole
58faa189ac Can now actually store transactions without an expense / revenue account. 2015-04-01 09:17:07 +02:00
James Cole
9b4f87d44a Fix checkbox for edit screen. 2015-04-01 09:16:51 +02:00
James Cole
7830a64170 Fix redirect. 2015-04-01 09:16:41 +02:00
James Cole
8f0fa02107 Better redirection for new transactions. 2015-04-01 09:12:49 +02:00
James Cole
e000fb5d80 Optimized decryption. 2015-03-31 22:46:11 +02:00
James Cole
566fadad15 Add decryption routine. 2015-03-31 21:18:22 +02:00
James Cole
cf23858c10 Gokje. 2015-03-31 20:52:48 +02:00
James Cole
216a223617 Fix in year list. 2015-03-31 20:49:02 +02:00
James Cole
638f38d823 New flush method. 2015-03-31 20:46:37 +02:00
James Cole
98ee70f04e Fix range thing. 2015-03-31 20:45:06 +02:00
James Cole
b365db5a4b New hidden id field. 2015-03-31 20:39:28 +02:00
James Cole
02e55496df Remove reminders when piggy bank is reminded. 2015-03-31 20:22:51 +02:00
James Cole
e11e53913a Some new code + GA 2015-03-31 19:21:49 +02:00
James Cole
f8a5fb4225 Fixed tests. 2015-03-31 17:49:47 +02:00
James Cole
3a49450461 Made sure migrations can be rolled back. 2015-03-31 15:38:44 +02:00
James Cole
3c375fb955 Remove build stuff because sqlite does not work with change things. 2015-03-31 15:24:13 +02:00
James Cole
011fea2cc6 Fix encryption in home chart. 2015-03-31 15:10:22 +02:00
James Cole
a079eec2cb Better unicity for objects. 2015-03-31 14:16:25 +02:00
James Cole
776b37f4ea Clean up some code, optimise the 503 error. 2015-03-30 21:24:56 +02:00
James Cole
a4d8bbe3da Fixed a bug where certain types of accounts could not be validated. 2015-03-30 20:16:33 +02:00
James Cole
72166743fa Merge branches 'develop' and 'develop' of https://github.com/JC5/firefly-iii into develop 2015-03-30 20:08:40 +02:00
James Cole
c4312c0b11 Extra large code cleanup. 2015-03-30 20:08:27 +02:00
James Cole
38ba645415 Add hidden-xs class. 2015-03-30 09:23:18 +02:00
James Cole
ac12a47071 Hide inactive budgets when there are none. 2015-03-29 21:29:37 +02:00
James Cole
bea321939e Code rearrange and optimise. 2015-03-29 21:27:51 +02:00
James Cole
210f84b6ea Allow edit from budget overview, and allow changing of active setting. 2015-03-29 21:27:13 +02:00
James Cole
d4c642741f Fixed division by zero. 2015-03-29 21:09:33 +02:00
James Cole
e6b1b58379 Enable inactive budgets. 2015-03-29 19:50:29 +02:00
James Cole
8d982c1a90 Some extensions. 2015-03-29 19:44:59 +02:00
James Cole
be10e836dc Updated composer.lock 2015-03-29 19:40:22 +02:00
James Cole
9be05e7e17 Small optimisations. 2015-03-29 18:28:49 +02:00
James Cole
bd96b2819f Removed double code. 2015-03-29 12:32:00 +02:00
James Cole
f601af3da0 Cleaned up report controller. 2015-03-29 12:25:46 +02:00
James Cole
70a01c082b Removed some double code. 2015-03-29 12:12:06 +02:00
James Cole
bcf066ead7 Cleaned up some double code. 2015-03-29 11:51:26 +02:00
James Cole
24dd3578ed Merge branch 'release/3.3.5' into develop 2015-03-29 08:43:55 +02:00
James Cole
d5c39d54d8 Merge branch 'release/3.3.5' 2015-03-29 08:43:54 +02:00
James Cole
6e3f6abc67 New read me. 2015-03-29 08:43:46 +02:00
James Cole
463201df2c New gitignore. 2015-03-29 08:43:03 +02:00
James Cole
a7501c396f Renamed some methods. 2015-03-29 08:24:56 +02:00
James Cole
4c8bc49a7e Add newlines. 2015-03-29 08:22:48 +02:00
James Cole
f254674f88 Add newlines. 2015-03-29 08:21:33 +02:00
James Cole
a97c267378 Added new lines 2015-03-29 08:20:37 +02:00
James Cole
eaa947894b Updated composer.son 2015-03-29 08:20:30 +02:00
James Cole
fb3a26510b Removed some unused use statements. 2015-03-29 08:20:20 +02:00
James Cole
bfe8b14e49 Cleaned up. 2015-03-29 08:18:15 +02:00
James Cole
afb47eb742 Add newlines. 2015-03-29 08:14:32 +02:00
James Cole
ba97f96288 Removed unused use statements. 2015-03-29 08:03:53 +02:00
James Cole
ecbafb8f4b Removed commented out code. 2015-03-29 07:59:18 +02:00
James Cole
12d3800d67 Removed unused use statements. 2015-03-29 07:51:56 +02:00
James Cole
d586b82372 New composer.son file. 2015-03-29 07:45:14 +02:00
James Cole
ba9877c9b4 Add typehints to object parameters 2015-03-29 07:43:20 +02:00
James Cole
907933f3df Removed debug logic and bad operators. 2015-03-29 07:32:24 +02:00
James Cole
2e91d21a88 Add return to form routine to budgets. 2015-03-28 18:22:36 +01:00
James Cole
dca395a018 Merge branch 'release/3.3.4' 2015-03-28 17:45:56 +01:00
James Cole
625070a5b9 Merge branch 'release/3.3.4' into develop 2015-03-28 17:45:56 +01:00
James Cole
f875c7cbf5 Updated read me file. 2015-03-28 17:45:46 +01:00
James Cole
eed88fc103 Don't fail on repeated piggy banks, just log it. 2015-03-28 17:45:15 +01:00
James Cole
6fc54d1d27 Fixed the tests 2015-03-28 07:00:53 +01:00
James Cole
0ef52bf909 Remove recurring transactions [skip ci] 2015-03-28 06:59:43 +01:00
James Cole
95e34af6ef Update script [skip ci] 2015-03-28 06:51:54 +01:00
James Cole
650b99ead2 Ignore apple files. [skip ci] 2015-03-28 06:50:26 +01:00
James Cole
57941a19de Excutable. 2015-03-28 06:48:54 +01:00
James Cole
6157db0b6a Some new tests 2015-03-28 06:48:38 +01:00
James Cole
c9358acf5d Update tests and token replace routine. 2015-03-28 06:25:36 +01:00
James Cole
ed29eb8a5d New lock file. 2015-03-28 06:19:37 +01:00
James Cole
bcf7452312 Some new tests. 2015-03-28 06:19:09 +01:00
James Cole
b9000519e4 Fixed unique piggy check. 2015-03-27 20:20:52 +01:00
James Cole
2694297466 Fixed a bug where start / end would be used incorrectly. 2015-03-27 19:48:55 +01:00
James Cole
53ff5c1490 Wrong operator, 2015-03-27 19:47:31 +01:00
James Cole
32a036b076 Add certainty to chart. 2015-03-27 19:45:47 +01:00
James Cole
aae2ab2693 Unnecessary if statement. 2015-03-27 19:43:53 +01:00
James Cole
4ef23e28a3 Update year report. 2015-03-27 19:43:20 +01:00
James Cole
38beb7f8d2 Fallback. 2015-03-27 19:42:35 +01:00
James Cole
0129a66906 Debug hidden accounts in year reports. 2015-03-27 19:37:00 +01:00
James Cole
45bced7b34 Hide accounts with no activity during a year. 2015-03-27 19:34:37 +01:00
James Cole
7f5a55dffb Small updates to read me. 2015-03-27 19:21:51 +01:00
James Cole
80289df6d3 Capital letter 2015-03-27 18:58:28 +01:00
James Cole
2115c3ced8 Read me 2015-03-27 18:58:11 +01:00
James Cole
1c2d0e6618 Updated read me file 2015-03-27 18:57:49 +01:00
James Cole
ea4f7f79ce Removed more references. 2015-03-27 18:17:15 +01:00
James Cole
b17f8ac311 Removed references to repeated expenses. 2015-03-27 18:15:10 +01:00
James Cole
6870d13b72 Removed repeated expenses. 2015-03-27 18:14:17 +01:00
James Cole
81fa304fd2 Removed repeated expenses. 2015-03-27 18:13:53 +01:00
James Cole
a663ddb0d9 Hide accounts with no activity. 2015-03-27 13:39:12 +01:00
James Cole
f7969afc22 Hide accounts with no activity in budget report. 2015-03-27 13:36:33 +01:00
James Cole
52ce4cd313 Resort array. 2015-03-27 13:25:46 +01:00
James Cole
247175881f Moved some code. 2015-03-27 13:24:04 +01:00
James Cole
fcf5009338 Moved some code around. 2015-03-27 13:20:48 +01:00
James Cole
12542d8f63 Auto fill transaction descriptions. 2015-03-27 13:16:14 +01:00
James Cole
e94194e28b New favicon. 2015-03-27 13:04:53 +01:00
James Cole
115499f3b2 New favicon. 2015-03-27 11:59:07 +01:00
James Cole
12af05b94f Only display budgets when there's money in the envelope or when there's money spent. 2015-03-27 09:43:29 +01:00
James Cole
88b83d8164 Merge branch 'release/3.3.3' into develop 2015-03-27 09:36:04 +01:00
James Cole
fcc22c692a Merge branch 'release/3.3.3' 2015-03-27 09:36:03 +01:00
James Cole
a876e8005c New version. 2015-03-27 09:35:52 +01:00
James Cole
2288e3705a Fixed order view. 2015-03-27 09:29:14 +01:00
James Cole
e8b58154e0 Bug fix. 2015-03-27 09:24:26 +01:00
James Cole
4393475af3 Remove debug. 2015-03-27 09:22:08 +01:00
James Cole
3fc560597c Validation bug. 2015-03-27 09:21:09 +01:00
James Cole
9f9af0b693 Moved to account list. 2015-03-27 08:11:13 +01:00
James Cole
a83fe2caea Correct ordering (everywhere). 2015-03-27 07:32:06 +01:00
James Cole
30c5376217 Fix order. 2015-03-27 07:29:01 +01:00
James Cole
6dddd6629d Thing with order and should fix Travis. 2015-03-27 07:20:32 +01:00
James Cole
f80de12cb5 Fix sorting. 2015-03-26 22:53:34 +01:00
James Cole
544ffca3a5 Sortable transactions. 2015-03-26 22:52:49 +01:00
James Cole
e0730c7b39 Fixed double named accounts. 2015-03-26 18:05:23 +01:00
James Cole
3d59d141c4 Push! 2015-03-26 17:46:08 +01:00
James Cole
ccddc2623d Merge branch 'develop' of github.com:JC5/firefly-iii into develop 2015-03-26 17:45:58 +01:00
James Cole
fcc47b58b4 Return to edit / create screen when user indicates. 2015-03-26 17:45:03 +01:00
James Cole
f67ac2e25e Update AccountController.php 2015-03-26 14:50:49 +01:00
James Cole
26127c9ccf Update AccountController.php 2015-03-26 14:49:02 +01:00
James Cole
d624efa799 Fix registration bug. 2015-03-25 22:30:36 +01:00
James Cole
ed3d40a4e0 Whoops. 2015-03-25 22:29:32 +01:00
James Cole
6e90ce5496 Cant dismiss reminders again. 2015-03-25 19:12:33 +01:00
James Cole
ab851b1be4 Fixed transfers 2015-03-25 17:44:06 +01:00
James Cole
340de53825 Use normal logging. 2015-03-25 17:42:33 +01:00
James Cole
a867b60af0 Update CategoryController.php 2015-03-25 16:14:28 +01:00
James Cole
26eafb0bd2 Update CategoryController.php 2015-03-25 16:13:39 +01:00
James Cole
0dbe44764b Update GoogleChartController.php 2015-03-25 16:00:06 +01:00
James Cole
2159df6802 Update GoogleChartController.php
Fixed chart.
2015-03-25 15:58:37 +01:00
James Cole
23389b9f17 Update FireflyValidator.php
Update uniqueForUser.
2015-03-25 15:56:32 +01:00
James Cole
6d3e3b894a Update AccountFormRequest.php
Update rules to include belongsToUser.
2015-03-25 15:55:39 +01:00
James Cole
55340aefa3 Remove code. 2015-03-24 21:06:45 +01:00
James Cole
94bc751e41 Sum starts at 0. 2015-03-24 21:05:15 +01:00
James Cole
89259c11e2 Fix chart. 2015-03-24 21:04:53 +01:00
James Cole
6bbaf1523c Fixed a bug in relevantOnDate 2015-03-24 21:00:42 +01:00
James Cole
fa3f18b60f Expand log for event. 2015-03-24 20:56:58 +01:00
James Cole
3dc794002f This should catch the missing piggy bank events. 2015-03-24 20:54:25 +01:00
James Cole
f50b133f2e Cleaned up some icons, improved routine for repeated expenses. 2015-03-21 21:33:52 +01:00
James Cole
1d6f6d28c9 Update font in calendar. 2015-03-21 10:29:25 +01:00
James Cole
c913de3c8b Fix percentage. 2015-03-21 08:56:24 +01:00
James Cole
bbc7b54a38 Catch 0 start balance. 2015-03-21 08:55:55 +01:00
James Cole
05fa1b40d1 Support > 100% 2015-03-21 08:53:43 +01:00
James Cole
6a88c8634d Added a block with savings. 2015-03-21 08:51:34 +01:00
James Cole
8ae1efa230 Added type savings account. 2015-03-20 23:17:59 +01:00
James Cole
ab8df4c8ab Fixed css reference. 2015-03-20 22:50:50 +01:00
James Cole
c259a46ed3 Clean up sql codes. 2015-03-20 22:39:07 +01:00
James Cole
5dc0677599 Fixed search sort 2015-03-20 18:30:17 +01:00
James Cole
7ed662ecc2 Fixed search in encrypted entries. 2015-03-20 18:21:14 +01:00
James Cole
4361cc69d4 Update font options in charts. 2015-03-20 15:54:40 +01:00
James Cole
461cbcbc28 Update to use Roboto font. 2015-03-20 13:34:59 +01:00
James Cole
09ae6c488b Fixed a bug where the session date would be edited by a chart. 2015-03-20 08:16:16 +01:00
James Cole
271a0ade26 Add code coverage to phpunit. 2015-03-18 22:24:54 +01:00
James Cole
4b076d227a Touch db so it can be created. 2015-03-18 22:17:18 +01:00
James Cole
3c4e7158a1 Config for test database. 2015-03-18 22:16:00 +01:00
James Cole
0b16765f37 Add sudo: false to enable container based builds. 2015-03-18 21:51:56 +01:00
James Cole
20c2ff3443 Add debug output to phpunit. 2015-03-18 21:43:19 +01:00
James Cole
96f2e598f4 Better position for titles. 2015-03-16 19:03:52 +01:00
James Cole
7374f0f9dd Removed Material Design. 2015-03-16 18:02:52 +01:00
James Cole
ccc44a74a0 Removed debug information. 2015-03-15 19:02:33 +01:00
James Cole
66cd63a68d Fixed a bug. 2015-03-15 18:08:52 +01:00
James Cole
decf7e5485 Set order in title. 2015-03-15 18:02:40 +01:00
James Cole
063c8025aa Allow piggy banks to be ordered. 2015-03-15 18:00:33 +01:00
James Cole
2fa7d2bd56 Add some text alignments. 2015-03-15 14:24:25 +01:00
James Cole
e55e7bce74 Misspelled a class name. 2015-03-15 14:23:26 +01:00
James Cole
f572445a65 Small updates. 2015-03-15 09:34:57 +01:00
James Cole
8b4f656d90 Switched to Google Material design line charts. 2015-03-15 08:38:12 +01:00
James Cole
6c1e093ebd Merge branch 'release/3.3.2' into develop 2015-03-14 22:06:12 +01:00
James Cole
6dd1b4537a Merge branch 'release/3.3.2' 2015-03-14 22:06:11 +01:00
James Cole
39ca9bea72 Update read me. 2015-03-14 22:06:01 +01:00
James Cole
999103277e Updated composer. 2015-03-14 22:05:36 +01:00
James Cole
3cc57ab89c Remove hash routine from user model. 2015-03-14 22:00:57 +01:00
James Cole
4e830079de New icon. 2015-03-14 17:31:17 +01:00
James Cole
ea7231e9fe Update mail config. 2015-03-14 17:25:35 +01:00
James Cole
ddfaca6d0c Cleanup and added some icons. 2015-03-14 17:21:43 +01:00
James Cole
3b11bd0593 Fixed some basic tests. 2015-03-13 08:44:07 +01:00
James Cole
3f89057528 Fixed a bug where the home budget chart would not actually list transactions without a budget. 2015-03-13 07:10:26 +01:00
James Cole
2f1073712f Merge pull request #63 from niekvanderkooy/fix-migrations
Fix migrations
2015-03-13 07:00:55 +01:00
James Cole
678e504c48 Fix charts to match report. 2015-03-10 20:26:52 +01:00
James Cole
e69545fd95 Include shared accounts. 2015-03-10 20:07:02 +01:00
James Cole
a7ed025cd6 Fine tune query. 2015-03-10 20:05:27 +01:00
James Cole
3d8e1f2484 Forgot the javascript. 2015-03-10 20:03:44 +01:00
James Cole
c38c9608da Fine tune query. 2015-03-10 20:01:49 +01:00
James Cole
2396b75e3c Fine tune income. 2015-03-10 20:00:43 +01:00
James Cole
e5c19b7562 Small fixes. 2015-03-10 19:58:05 +01:00
James Cole
114788567d More code for previous. 2015-03-10 19:57:20 +01:00
James Cole
17ae4b7d2a See if we can easily generate reports with shared accounts. 2015-03-10 19:51:24 +01:00
Niek van der Kooy
12d652bd0e We cannot entirely drop the foreign key constraint, since it is originally created (and dropped) in v3.2.1. 2015-03-10 18:25:23 +01:00
Niek van der Kooy
ff1bed97b8 We need to include models we use
Probably some left over L5 migration stuff, since you wouldn't notice it until reversing a migration
2015-03-10 18:24:28 +01:00
Niek van der Kooy
56490f0e84 Fix error when reverting changed migration.
When reverting changed migration, the down would fail because the foreign key constraint has to be dropped before you are able to rename the column.
2015-03-10 18:04:31 +01:00
James Cole
0b028a8923 Correctly order account names. 2015-03-10 17:26:31 +01:00
James Cole
43ac541cb8 Add reminders to top right menu. 2015-03-08 20:27:07 +01:00
James Cole
5218443678 Can now successfully act on reminders. 2015-03-08 20:20:58 +01:00
James Cole
d9028ed9b7 Small optimizations to the reminders 2015-03-08 09:00:04 +01:00
James Cole
9b9bd11ebb Small fix to table fix. 2015-03-07 19:42:45 +01:00
James Cole
07011ec5f7 Tiny chart improvement because I said so 2015-03-07 19:41:56 +01:00
James Cole
c3990ac32f Small updates to icons and code. 2015-03-07 12:34:03 +01:00
James Cole
081ff3ff55 View single reminder. 2015-03-07 09:29:43 +01:00
James Cole
93996ada96 Expanded reminders. 2015-03-07 09:21:06 +01:00
James Cole
a60671d4c1 First stuff for acting on reminders. 2015-03-06 20:33:23 +01:00
James Cole
3f716cc369 First new display of piggy bank reminders. 2015-03-06 17:23:29 +01:00
James Cole
9f23cffd1b Clean up code. 2015-03-06 15:26:21 +01:00
James Cole
07c416cfbf Fix set reminder. 2015-03-06 15:24:36 +01:00
James Cole
389fcc1c8d Update reminder in database. 2015-03-06 15:21:44 +01:00
James Cole
fa07811375 Add logging for debug purposes. 2015-03-06 15:18:07 +01:00
James Cole
fc91a50979 Reimplemented a routine that creates reminders. Cannot act on them yet. 2015-03-06 15:12:07 +01:00
James Cole
f9c518f321 Smaller font for boxes. 2015-03-06 10:10:07 +01:00
James Cole
015b439f0d New icons. 2015-03-06 08:30:15 +01:00
James Cole
0675622508 Experiment with boxes. 2015-03-06 08:20:27 +01:00
James Cole
e9969bdd5f Update the ranges to reflect the current dates. 2015-03-05 21:13:38 +01:00
James Cole
1139f950ed Fixed some views. 2015-03-04 21:11:47 +01:00
James Cole
284732c7a6 Better list for bills. 2015-03-04 20:58:57 +01:00
James Cole
0cb0720d8b No popup when the amount is zero. 2015-03-04 20:57:40 +01:00
James Cole
8ad1ede0c5 Popups in the reports as we've always promised. 2015-03-04 20:47:00 +01:00
James Cole
a349aac8a4 Fix balance thing. 2015-03-04 19:09:57 +01:00
James Cole
83b169c6ef Search related transfers, cleanup. 2015-03-04 16:04:17 +01:00
James Cole
49c37baac5 Update to related manager. 2015-03-04 15:30:44 +01:00
James Cole
8d62088576 Order bills. 2015-03-04 09:44:48 +01:00
James Cole
f5437a17f8 Lots of changes. 2015-03-04 09:42:47 +01:00
James Cole
92af4e5c96 Layout tweaks. 2015-03-04 05:12:05 +01:00
James Cole
0619adb0cd Support any bill in any range. 2015-03-03 17:40:17 +01:00
James Cole
65a5107854 Small layout updates. 2015-03-03 09:35:06 +01:00
James Cole
0fcc1e252b Mail user registration confirmation. 2015-03-03 09:29:02 +01:00
James Cole
4b7f817475 Removed panel for table. 2015-03-03 09:19:16 +01:00
James Cole
0439599971 Layout update. 2015-03-03 09:15:28 +01:00
James Cole
fa344d5308 Do not update when no event connected. 2015-03-03 08:46:14 +01:00
James Cole
f0316f09ed Do not over / undercorrect 2015-03-02 20:29:10 +01:00
James Cole
b1af6bab28 Cleaning up and bug fixing. 2015-03-02 20:05:28 +01:00
James Cole
ad2aebb54d Sort account list. 2015-03-02 15:46:31 +01:00
James Cole
23fc652092 Table border. 2015-03-02 15:45:24 +01:00
James Cole
f0a5756f25 Add a panel-body for the layout. 2015-03-02 15:45:00 +01:00
James Cole
14c7ad201a Paginated the account list. 2015-03-02 15:44:06 +01:00
James Cole
08ca3c89d3 Expanded account view. 2015-03-02 15:27:36 +01:00
James Cole
edda470bf8 Add everything range 2015-03-02 13:19:13 +01:00
James Cole
7183d72e5c Update chart to include other budget repetitions. 2015-03-02 12:50:51 +01:00
James Cole
5e38ebfce5 Merge branch 'feature/date-range' into develop 2015-03-02 12:35:34 +01:00
James Cole
56e36847a5 New code for new date range thing. 2015-03-02 12:35:14 +01:00
James Cole
6dba916d02 New code & css for date range. 2015-03-02 12:04:40 +01:00
James Cole
fd57086ffd Better mostly report lists. 2015-03-02 11:54:20 +01:00
James Cole
d98d366eea Some small bug fixes in the account views. 2015-03-02 11:42:27 +01:00
James Cole
b261b0b447 Shared expense should of course be shared asset. 2015-03-02 11:27:46 +01:00
James Cole
c6042a9053 Try to fix modal dialog for piggy banks. 2015-03-01 19:47:42 +01:00
James Cole
ae1245abec Fixed update transactions. 2015-03-01 19:31:00 +01:00
James Cole
e26d2376fc Fixed piggy bank delete routine. 2015-03-01 19:26:30 +01:00
James Cole
bb36ad64a7 Moved the form. 2015-03-01 13:39:16 +01:00
James Cole
262d4f92d4 Fixed a bug where consecutive payments from one source would not be summed up. 2015-03-01 10:55:20 +01:00
James Cole
675530458c Account show didn't show anything. 2015-03-01 10:44:10 +01:00
James Cole
19e34b460f Update event. 2015-03-01 08:34:59 +01:00
James Cole
dddb8cdbc0 This loops. 2015-03-01 08:25:12 +01:00
James Cole
0d0df5f143 Scan bills when editing and creating journals. 2015-03-01 08:15:24 +01:00
James Cole
d1cf683f57 Some layout and content updates 2015-03-01 07:50:26 +01:00
James Cole
d099c33e5b No more code climate for now. 2015-02-27 21:40:49 +01:00
James Cole
21fb41545b Now with son_path variable. 2015-02-27 21:24:14 +01:00
James Cole
4c56814785 Do code coverage from phpunit. 2015-02-27 21:15:21 +01:00
James Cole
cffe05e22b Add coveralls to composer.json 2015-02-27 21:01:18 +01:00
James Cole
4237850299 Restoring code coverage 2015-02-27 20:52:49 +01:00
James Cole
b5fc36a8e1 Clean up test stuff. 2015-02-27 20:46:39 +01:00
James Cole
4586c1ef52 Removed all test cases. 2015-02-27 20:45:17 +01:00
James Cole
2722f0b749 Merge branch 'release/3.3.1' 2015-02-27 20:42:12 +01:00
James Cole
d6cf7c4872 Merge branch 'release/3.3.1' into develop 2015-02-27 20:42:12 +01:00
James Cole
3aedfed432 Updated version. 2015-02-27 20:42:04 +01:00
James Cole
edeaf13259 New CSS / JS code. 2015-02-27 18:05:40 +01:00
James Cole
c1290c4e9b Forgot to commit one view. 2015-02-27 16:53:06 +01:00
James Cole
b2c1527b17 Lost a lot of stuff along the way. 2015-02-27 16:48:33 +01:00
James Cole
a4a65ea56e Merge branch 'release/3.3' into develop 2015-02-27 16:15:30 +01:00
707 changed files with 40822 additions and 46303 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 @@
src_dir: .
coverage_clover: tests/_output/coverage.xml
json_path: tests/_output/coveralls-upload.json
src_dir: .

View File

@@ -1,5 +1,5 @@
APP_ENV=local
APP_DEBUG=true
APP_ENV=production
APP_DEBUG=false
APP_KEY=SomeRandomString
DB_CONNECTION=mysql
@@ -12,5 +12,10 @@ CACHE_DRIVER=file
SESSION_DRIVER=file
EMAIL_SMTP=
EMAIL_DRIVER=smtp
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=
EMAIL_PRETEND=false
RUNCLEANUP=true
SITE_OWNER=mail@example.com

View File

@@ -8,6 +8,11 @@ DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
CACHE_DRIVER=file
SESSION_DRIVER=file
CACHE_DRIVER=array
SESSION_DRIVER=array
EMAIL_SMTP=
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=ABC
EMAIL_PRETEND=true

8
.gitignore vendored
View File

@@ -25,3 +25,11 @@ c3.php
db.sqlite-journal
tests/_output/*
.env
clover.xml
node_modules/
addNewLines.php
.phpstorm.meta.php
.env.backup
.env.local
tests/_output/*

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"
]
}

3
.scrutinizer.yml Normal file
View File

@@ -0,0 +1,3 @@
# .scrutinizer.yml
tools:
external_code_coverage: false

View File

@@ -1,26 +1,15 @@
language: php
sudo: false
php:
- 5.5
- 5.6
addons:
code_climate:
repo_token: 26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61
install:
- rm composer.lock
- composer install
- composer update
- php artisan env
- mv -v .env.testing .env
script:
- ./tests/_data/db.sh
- php vendor/bin/codecept build
- php vendor/bin/codecept run --coverage --coverage-xml --no-exit
after_script:
- cp -v tests/_output/coverage.xml build/logs/clover.xml
- php vendor/bin/coveralls
- 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"
- phpunit

143
README.md
View File

@@ -1,76 +1,115 @@
Firefly III (v3.3)
===========
# Firefly III
[![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)
[![Test Coverage](https://codeclimate.com/github/JC5/firefly-iii/badges/coverage.svg)](https://codeclimate.com/github/JC5/firefly-iii)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![Latest Unstable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/unstable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![License](https://poser.pugx.org/grumpydictator/firefly-iii/license.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![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)
[![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)
Firefly III is a tool to help you manage your finances. Please read the full description [in the wiki](https://github.com/JC5/firefly-iii/wiki/full-description).
## About
Firefly Mark III is a new version of Firefly built upon best practices and lessons learned
from building [Firefly](https://github.com/JC5/Firefly). It's Mark III since the original Firefly never made it outside of my
laptop and [Firefly II](https://github.com/JC5/Firefly) is live.
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared
household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
_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 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:
- The screenshots below on this very page.
- The featurelist below, also on this very page.
- The [full description](https://github.com/JC5/firefly-iii/wiki/full-description), which will tell you how Firefly works,
and the philosophy behind it.
#### About the name (should you care)
It's III, or 3, because [version 2](https://github.com/JC5/Firefly) and version 1 (not online) preceded it. It has been growing steadily ever since.
## Current features
- [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system);
- You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management;
- It's possible to create, change and manage money using _budgets_;
- [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;
- [Asset](https://en.wikipedia.org/wiki/Asset) accounts
- Shared [asset accounts](https://en.wikipedia.org/wiki/Asset) ([household accounts](https://en.wikipedia.org/wiki/Household))
- Saving accounts
- Credit cards
- It's possible to create, change and manage money using _[budgets](https://en.wikipedia.org/wiki/Envelope_system)_;
- Organize transactions using categories;
- Save towards a goal using piggy banks;
- Predict and anticipate large expenses using "repeated expenses" (ie. yearly taxes);
- Predict and anticipate bills using "recurring transactions" (rent for example);
- View basic income / expense reports.
- Lots of help text in case you don't get it;
- Save towards a goal using [piggy banks](https://en.wikipedia.org/wiki/Piggy_bank);
- Predict and anticipate [bills](https://en.wikipedia.org/wiki/Invoice);
- View income / expense [reports](https://en.wikipedia.org/wiki/Financial_statement);
- Organize expenses using tags;
- Lots of help text in case you don't get it.
Everything is organised:
- Clear views that should show you how you're doing;
- Easy navigation through your records;
- Browse back and forth to see previous months or even years;
- Lots of charts because we all love them.
- Financial reporting showing you how well you are doing;
## Changes
Firefly III will feature, but does not feature yet:
- More control over other resources outside of personal finance
- Accounts shared with a partner (household accounts)
- Debts
- Credit cards
- More test-coverage;
- Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control.
- Firefly will be able to join transactions.
- Any other features I might not have thought of.
Some stuff has been removed:
- The nesting of budgets, categories and beneficiaries is removed because it was pretty pointless.
- Firefly will not encrypt the content of the (MySQL) tables. Old versions of Firefly had this capability but it sucks when searching, sorting and organizing entries.
- Lots of charts because we all love them;
- Financial reporting showing you how well you are doing.
## Screenshots
![Index](http://i.imgur.com/TkZNIer.png)
_Please note that everything in these screenshots is fictional and may not be realistic._
![Accounts](http://i.imgur.com/YE8WavP.png)
![Index](https://i.nder.be/gdryw73q)
![Budgets](http://i.imgur.com/Go0M6Nd.png)
![Accounts](https://i.nder.be/hmpkq8q0)
![Budgets](https://i.nder.be/cbq2n5g9)
![Reports 1](https://i.nder.be/cmwvqrds)
![Reports 2](https://i.nder.be/cv4dqbp4)
![Bills](https://i.nder.be/gmkxqdw7)
![Piggy banks](https://i.nder.be/cc5u6h3b)
## 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.
## Credits
Firefly III uses the following libraries and tools:
* The AdminLTE template by [Almsaseed Studio](https://almsaeedstudio.com/)
* The [Google charts](https://developers.google.com/chart/) library.
* [Bootstrap](http://getbootstrap.com/)
* [Laravel](http://laravel.com/)
* [Twig](http://twig.sensiolabs.org/)
* For development, some of the excellent tools made by [Barry van den Heuvel](https://github.com/barryvdh)
* [Bootstrap sortable](https://github.com/drvic10k/bootstrap-sortable) by [Matúš Brliť](https://github.com/drvic10k).
* [Date range picker](https://github.com/dangrossman/bootstrap-daterangepicker/) by [Dan Grossman](https://github.com/dangrossman)
* The [real favicon generator](http://realfavicongenerator.net/)
* Various other open source components (see [composer.json](https://github.com/JC5/firefly-iii/blob/master/composer.json))
![Reports](http://i.imgur.com/EnEIyQI.png)
## Current state
I have the basics up and running. Test coverage is currently coming, slowly.
Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all
views escape all characters by default. Will be fixed.
Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. Translations are a work in progress.
Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
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

@@ -2,6 +2,7 @@
/**
* Class Command
*
* @codeCoverageIgnore
* @package FireflyIII\Commands
*/
abstract class Command

View File

@@ -1,37 +0,0 @@
<?php namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Foundation\Inspiring;
/**
* Class Inspire
*
* @package FireflyIII\Console\Commands
*/
class Inspire extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Display an inspiring quote';
/**
* The console command name.
*
* @var string
*/
protected $name = 'inspire';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->comment(PHP_EOL . Inspiring::quote() . PHP_EOL);
}
}

View File

@@ -6,6 +6,7 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
/**
* Class Kernel
*
* @codeCoverageIgnore
* @package FireflyIII\Console
*/
class Kernel extends ConsoleKernel
@@ -18,7 +19,6 @@ class Kernel extends ConsoleKernel
*/
protected $commands
= [
'FireflyIII\Console\Commands\Inspire',
];
/**
@@ -26,12 +26,12 @@ class Kernel extends ConsoleKernel
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('inspire')
->hourly();
}
}

View File

@@ -3,6 +3,7 @@
/**
* Class Event
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
abstract class Event

View File

@@ -0,0 +1,34 @@
<?php namespace FireflyIII\Events;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
/**
* Class JournalCreated
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
class JournalCreated extends Event
{
use SerializesModels;
public $journal;
public $piggyBankId;
/**
* Create a new event instance.
*
* @param TransactionJournal $journal
* @param $piggyBankId
*/
public function __construct(TransactionJournal $journal, $piggyBankId)
{
//
$this->journal = $journal;
$this->piggyBankId = $piggyBankId;
}
}

View File

@@ -2,6 +2,12 @@
use Illuminate\Queue\SerializesModels;
/**
* Class JournalDeleted
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
class JournalDeleted extends Event
{
@@ -10,7 +16,6 @@ class JournalDeleted extends Event
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{

View File

@@ -0,0 +1,30 @@
<?php namespace FireflyIII\Events;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
/**
* Class JournalSaved
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
class JournalSaved extends Event
{
use SerializesModels;
public $journal;
/**
* Create a new event instance.
*
* @param TransactionJournal $journal
*/
public function __construct(TransactionJournal $journal)
{
//
$this->journal = $journal;
}
}

View File

@@ -6,6 +6,7 @@ namespace FireflyIII\Exceptions;
/**
* Class FireflyException
*
* @codeCoverageIgnore
* @package FireflyIII\Exceptions
*/
class FireflyException extends \Exception

View File

@@ -2,10 +2,12 @@
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Class Handler
*
* @codeCoverageIgnore
* @package FireflyIII\Exceptions
*/
class Handler extends ExceptionHandler
@@ -26,12 +28,13 @@ class Handler extends ExceptionHandler
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @SuppressWarnings(PHPMD.ShortVariable)
*
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($this->isHttpException($e)) {
if ($e instanceof HttpException) {
return $this->renderHttpException($e);
} else {
return parent::render($request, $e);
@@ -42,6 +45,7 @@ class Handler extends ExceptionHandler
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
* @SuppressWarnings(PHPMD.ShortVariable)
*
* @param \Exception $e
*
@@ -49,8 +53,7 @@ class Handler extends ExceptionHandler
*/
public function report(Exception $e)
{
/** @noinspection PhpInconsistentReturnPointsInspection */
return parent::report($e);
parent::report($e);
}
}

View File

@@ -5,6 +5,7 @@ namespace FireflyIII\Exceptions;
/**
* Class NotImplementedException
*
* @codeCoverageIgnore
* @package FireflyIII\Exceptions
*/
class NotImplementedException extends \Exception

View File

@@ -4,6 +4,7 @@ namespace FireflyIII\Exceptions;
/**
* Class ValidationExceptions
*
* @codeCoverageIgnore
* @package FireflyIII\Exception
*/
class ValidationException extends \Exception

View File

@@ -0,0 +1,43 @@
<?php
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
/**
* Interface AccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
interface AccountChartGenerator
{
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function all(Collection $accounts, Carbon $start, Carbon $end);
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end);
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end);
}

View File

@@ -0,0 +1,114 @@
<?php
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use Config;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
use Preferences;
use Steam;
/**
* Class ChartJsAccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
class ChartJsAccountChartGenerator implements AccountChartGenerator
{
/**
* @codeCoverageIgnore
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function all(Collection $accounts, Carbon $start, Carbon $end)
{
return $this->frontpage($accounts, $start, $end);
}
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.monthAndDay.' . $language);
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
$current = clone $start;
while ($current <= $end) {
$data['labels'][] = $current->formatLocalized($format);
$current->addDay();
}
foreach ($accounts as $account) {
$set = [
'label' => $account->name,
'fillColor' => 'rgba(220,220,220,0.2)',
'strokeColor' => 'rgba(220,220,220,1)',
'pointColor' => 'rgba(220,220,220,1)',
'pointStrokeColor' => '#fff',
'pointHighlightFill' => '#fff',
'pointHighlightStroke' => 'rgba(220,220,220,1)',
'data' => [],
];
$current = clone $start;
while ($current <= $end) {
$set['data'][] = Steam::balance($account, $current);
$current->addDay();
}
$data['datasets'][] = $set;
}
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.monthAndDay.' . $language);
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => $account->name,
'data' => []
]
],
];
$current = clone $start;
while ($end >= $current) {
$data['labels'][] = $current->formatLocalized($format);
$data['datasets'][0]['data'][] = Steam::balance($account, $current);
$current->addDay();
}
return $data;
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Steam;
/**
* Class GoogleAccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
class GoogleAccountChartGenerator implements AccountChartGenerator
{
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function all(Collection $accounts, Carbon $start, Carbon $end)
{
// make chart (original code):
$chart = new GChart;
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$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 $chart->getData();
}
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$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 $chart->getData();
}
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end)
{
$current = clone $start;
$today = new Carbon;
$chart = new GChart;
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty(1);
while ($end >= $current) {
$certain = $current < $today;
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
$current->addDay();
}
$chart->generate();
return $chart->getData();
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace FireflyIII\Generator\Chart\Bill;
use FireflyIII\Models\Bill;
use Illuminate\Support\Collection;
/**
* Interface BillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
interface BillChartGenerator
{
/**
* @param Collection $paid
* @param Collection $unpaid
*
* @return array
*/
public function frontpage(Collection $paid, Collection $unpaid);
/**
* @param Bill $bill
* @param Collection $entries
*
* @return array
*/
public function single(Bill $bill, Collection $entries);
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 27/06/15
* Time: 17:21
*/
namespace FireflyIII\Generator\Chart\Bill;
use Config;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class ChartJsBillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
class ChartJsBillChartGenerator implements BillChartGenerator
{
/**
* @param Collection $paid
* @param Collection $unpaid
*
* @return array
*/
public function frontpage(Collection $paid, Collection $unpaid)
{
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @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);
}
$data = [
[
'value' => $unpaidAmount,
'color' => 'rgba(53, 124, 165,0.7)',
'highlight' => 'rgba(53, 124, 165,0.9)',
'label' => trans('firefly.unpaid'),
],
[
'value' => $paidAmount,
'color' => 'rgba(0, 141, 76, 0.7)',
'highlight' => 'rgba(0, 141, 76, 0.9)',
'label' => trans('firefly.paid'),
]
];
return $data;
}
/**
* @param Bill $bill
* @param Collection $entries
*
* @return array
*/
public function single(Bill $bill, Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 3,
'labels' => [],
'datasets' => [],
];
// dataset: max amount
// dataset: min amount
// dataset: actual amount
$minAmount = [];
$maxAmount = [];
$actualAmount = [];
foreach ($entries as $entry) {
$data['labels'][] = $entry->date->formatLocalized($format);
$minAmount[] = round($bill->amount_min, 2);
$maxAmount[] = round($bill->amount_max, 2);
$actualAmount[] = round($entry->amount, 2);
}
$data['datasets'][] = [
'label' => trans('firefly.minAmount'),
'data' => $minAmount,
];
$data['datasets'][] = [
'label' => trans('firefly.billEntry'),
'data' => $actualAmount,
];
$data['datasets'][] = [
'label' => trans('firefly.maxAmount'),
'data' => $maxAmount,
];
$data['count'] = count($data['datasets']);
return $data;
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace FireflyIII\Generator\Chart\Bill;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleBillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
class GoogleBillChartGenerator implements BillChartGenerator
{
/**
* @param Collection $paid
* @param Collection $unpaid
*
* @return array
*/
public function frontpage(Collection $paid, Collection $unpaid)
{
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @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 = new GChart;
$chart->addColumn(trans('firefly.name'), 'string');
$chart->addColumn(trans('firefly.amount'), 'number');
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
$chart->generate();
return $chart->getData();
}
/**
* @param Bill $bill
* @param Collection $entries
*
* @return mixed
*/
public function single(Bill $bill, Collection $entries)
{
// make chart:
$chart = new GChart;
$chart->addColumn(trans('firefly.date'), 'date');
$chart->addColumn(trans('firefly.maxAmount'), 'number');
$chart->addColumn(trans('firefly.minAmount'), 'number');
$chart->addColumn(trans('firefly.billEntry'), 'number');
/** @var TransactionJournal $result */
foreach ($entries as $result) {
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
return $chart->getData();
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace FireflyIII\Generator\Chart\Budget;
use Illuminate\Support\Collection;
/**
* Interface BudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
interface BudgetChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function budget(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function budgetLimit(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries);
/**
* @param Collection $budgets
* @param Collection $entries
*
* @return array
*/
public function year(Collection $budgets, Collection $entries);
}

View File

@@ -0,0 +1,144 @@
<?php
namespace FireflyIII\Generator\Chart\Budget;
use Config;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class ChartJsBudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
class ChartJsBudgetChartGenerator implements BudgetChartGenerator
{
/**
* @param Collection $entries
* @param string $dateFormat
*
* @return array
*/
public function budget(Collection $entries, $dateFormat = 'month')
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.' . $dateFormat . '.' . $language);
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => 'Amount',
'data' => [],
]
],
];
/** @var array $entry */
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized($format);
$data['datasets'][0]['data'][] = $entry[1];
}
return $data;
}
/**
* @codeCoverageIgnore
*
* @param Collection $entries
*
* @return array
*/
public function budgetLimit(Collection $entries)
{
return $this->budget($entries, 'monthAndDay');
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries)
{
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
// dataset: left
// dataset: spent
// dataset: overspent
$left = [];
$spent = [];
$overspent = [];
foreach ($entries as $entry) {
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
$data['labels'][] = $entry[0];
$left[] = round($entry[1], 2);
$spent[] = round($entry[2], 2);
$overspent[] = round($entry[3], 2);
}
}
$data['datasets'][] = [
'label' => trans('firefly.left'),
'data' => $left,
];
$data['datasets'][] = [
'label' => trans('firefly.spent'),
'data' => $spent,
];
$data['datasets'][] = [
'label' => trans('firefly.overspent'),
'data' => $overspent,
];
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @param Collection $budgets
* @param Collection $entries
*
* @return array
*/
public function year(Collection $budgets, Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
foreach ($budgets as $budget) {
$data['labels'][] = $budget->name;
}
/** @var array $entry */
foreach ($entries as $entry) {
$array = [
'label' => $entry[0]->formatLocalized($format),
'data' => [],
];
array_shift($entry);
$array['data'] = $entry;
$data['datasets'][] = $array;
}
$data['count'] = count($data['datasets']);
return $data;
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace FireflyIII\Generator\Chart\Budget;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleBudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
class GoogleBudgetChartGenerator implements BudgetChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function budget(Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
/** @var array $entry */
foreach ($entries as $entry) {
$chart->addRow($entry[0], $entry[1]);
}
$chart->generate();
return $chart->getData();
}
/**
* @codeCoverageIgnore
* @param Collection $entries
*
* @return array
*/
public function budgetLimit(Collection $entries)
{
return $this->budget($entries);
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.budget'), 'string');
$chart->addColumn(trans('firefly.left'), 'number');
$chart->addColumn(trans('firefly.spent'), 'number');
$chart->addColumn(trans('firefly.overspent'), 'number');
/** @var array $entry */
foreach ($entries 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 $chart->getData();
}
/**
* @param Collection $budgets
* @param Collection $entries
*
* @return array
*/
public function year(Collection $budgets, Collection $entries)
{
$chart = new GChart;
// add columns:
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
/** @var array $entry */
foreach ($entries as $entry) {
$chart->addRowArray($entry);
}
$chart->generate();
return $chart->getData();
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace FireflyIII\Generator\Chart\Category;
use Illuminate\Support\Collection;
/**
* Interface CategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
interface CategoryChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function month(Collection $entries);
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function year(Collection $categories, Collection $entries);
}

View File

@@ -0,0 +1,122 @@
<?php
namespace FireflyIII\Generator\Chart\Category;
use Config;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class ChartJsCategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
class ChartJsCategoryChartGenerator implements CategoryChartGenerator
{
/**
* @param Collection $entries
* @param string $dateFormat
*
* @return array
*/
public function all(Collection $entries, $dateFormat = 'month')
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.' . $dateFormat . '.' . $language);
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => []
]
],
];
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized($format);
$data['datasets'][0]['data'][] = round($entry[1], 2);
}
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries)
{
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => []
]
],
];
foreach ($entries as $entry) {
if ($entry['sum'] != 0) {
$data['labels'][] = $entry['name'];
$data['datasets'][0]['data'][] = round($entry['sum'], 2);
}
}
return $data;
}
/**
* @codeCoverageIgnore
* @param Collection $entries
*
* @return array
*/
public function month(Collection $entries)
{
return $this->all($entries, 'monthAndDay');
}
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function year(Collection $categories, Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
foreach ($categories as $category) {
$data['labels'][] = $category->name;
}
foreach ($entries as $entry) {
$date = $entry[0]->formatLocalized($format);
array_shift($entry);
$data['count']++;
$data['datasets'][] = ['label' => $date, 'data' => $entry];
}
return $data;
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace FireflyIII\Generator\Chart\Category;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleCategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
class GoogleCategoryChartGenerator implements CategoryChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
/** @var array $entry */
foreach ($entries as $entry) {
$chart->addRow($entry[0], $entry[1]);
}
$chart->generate();
return $chart->getData();
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.category'), 'string');
$chart->addColumn(trans('firefly.spent'), 'number');
/** @var array $entry */
foreach ($entries as $entry) {
$sum = $entry['sum'];
if ($sum != 0) {
$chart->addRow($entry['name'], $sum);
}
}
$chart->generate();
return $chart->getData();
}
/**
* @param Collection $entries
*
* @return array
*/
public function month(Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
/** @var array $entry */
foreach ($entries as $entry) {
$chart->addRow($entry[0], $entry[1]);
}
$chart->generate();
return $chart->getData();
}
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function year(Collection $categories, Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($categories as $category) {
$chart->addColumn($category->name, 'number');
}
/** @var array $entry */
foreach ($entries as $entry) {
$chart->addRowArray($entry);
}
$chart->generate();
return $chart->getData();
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace FireflyIII\Generator\Chart\PiggyBank;
use Carbon\Carbon;
use Config;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class GooglePiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => 'Diff',
'data' => []
]
],
];
$sum = '0';
bcscale(2);
foreach ($set as $entry) {
$date = new Carbon($entry->date);
$sum = bcadd($sum, $entry->sum);
$data['labels'][] = $date->formatLocalized($format);
$data['datasets'][0]['data'][] = round($sum, 2);
}
return $data;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace FireflyIII\Generator\Chart\PiggyBank;
use Carbon\Carbon;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GooglePiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
class GooglePiggyBankChartGenerator implements PiggyBankChartGenerator
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.date'), 'date');
$chart->addColumn(trans('firefly.balance'), 'number');
$sum = '0';
bcscale(2);
foreach ($set as $entry) {
$sum = bcadd($sum, $entry->sum);
$chart->addRow(new Carbon($entry->date), $sum);
}
$chart->generate();
return $chart->getData();
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FireflyIII\Generator\Chart\PiggyBank;
use Illuminate\Support\Collection;
/**
* Interface PiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
interface PiggyBankChartGenerator
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set);
}

View File

@@ -0,0 +1,83 @@
<?php
namespace FireflyIII\Generator\Chart\Report;
use Config;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class GoogleReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
class ChartJsReportChartGenerator implements ReportChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => []
],
[
'label' => trans('firefly.expenses'),
'data' => []
]
],
];
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized($format);
$data['datasets'][0]['data'][] = round($entry[1], 2);
$data['datasets'][1]['data'][] = round($entry[2], 2);
}
return $data;
}
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized($income, $expense, $count)
{
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => []
],
[
'label' => trans('firefly.expenses'),
'data' => []
]
],
];
$data['datasets'][0]['data'][] = round($income, 2);
$data['datasets'][1]['data'][] = round($expense, 2);
$data['datasets'][0]['data'][] = round(($income / $count), 2);
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
return $data;
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace FireflyIII\Generator\Chart\Report;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
class GoogleReportChartGenerator implements ReportChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.month'), 'date');
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
/** @var array $entry */
foreach ($entries as $entry) {
$chart->addRowArray($entry);
}
$chart->generate();
return $chart->getData();
}
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized($income, $expense, $count)
{
$chart = new GChart;
$chart->addColumn(trans('firefly.summary'), 'string');
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
$chart->addRow(trans('firefly.sum'), $income, $expense);
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
$chart->generate();
return $chart->getData();
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace FireflyIII\Generator\Chart\Report;
use Illuminate\Support\Collection;
/**
* Interface ReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
interface ReportChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries);
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized($income, $expense, $count);
}

View File

@@ -0,0 +1,73 @@
<?php namespace FireflyIII\Handlers\Events;
use Auth;
use FireflyIII\Events\JournalCreated;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\TransactionJournal;
/**
* Class ConnectJournalToPiggyBank
*
* @package FireflyIII\Handlers\Events
*/
class ConnectJournalToPiggyBank
{
/**
* Create the event handler.
*
* @codeCoverageIgnore
*
*/
public function __construct()
{
//
}
/**
* Handle the event when journal is saved.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @param JournalCreated $event
*
* @return boolean
*/
public function handle(JournalCreated $event)
{
/** @var TransactionJournal $journal */
$journal = $event->journal;
$piggyBankId = $event->piggyBankId;
/** @var PiggyBank $piggyBank */
$piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
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)) {
return false;
}
bcscale(2);
$amount = $journal->actual_amount;
// if piggy account matches source account, the amount is positive
if ($piggyBank->account_id == $journal->source_account->id) {
$amount = $amount * -1;
}
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
$repetition->save();
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
return true;
}
}

View File

@@ -1,33 +0,0 @@
<?php namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\JournalDeleted;
use Illuminate\Contracts\Queue\ShouldBeQueued;
use Illuminate\Queue\InteractsWithQueue;
class JournalDeletedHandler
{
/**
* Create the event handler.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param JournalDeleted $event
*
* @return void
*/
public function handle(JournalDeleted $event)
{
//
}
}

View File

@@ -0,0 +1,53 @@
<?php namespace FireflyIII\Handlers\Events;
use App;
use FireflyIII\Events\JournalSaved;
use Log;
/**
* Class RescanJournal
*
* @codeCoverageIgnore
* @package FireflyIII\Handlers\Events
*/
class RescanJournal
{
/**
* Create the event handler.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param JournalSaved $event
*
* @return void
*/
public function handle(JournalSaved $event)
{
$journal = $event->journal;
Log::debug('Triggered saved event for journal #' . $journal->id . ' (' . $journal->description . ')');
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
$list = $journal->user->bills()->where('active', 1)->where('automatch', 1)->get();
Log::debug('Found ' . $list->count() . ' bills to check.');
/** @var \FireflyIII\Models\Bill $bill */
foreach ($list as $bill) {
Log::debug('Now calling bill #' . $bill->id . ' (' . $bill->name . ')');
$repository->scan($bill, $journal);
}
Log::debug('Done!');
}
}

View File

@@ -0,0 +1,63 @@
<?php namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\JournalSaved;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
/**
* Class UpdateJournalConnection
*
* @codeCoverageIgnore
* @package FireflyIII\Handlers\Events
*/
class UpdateJournalConnection
{
/**
* Create the event handler.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param JournalSaved $event
*
* @return void
*/
public function handle(JournalSaved $event)
{
$journal = $event->journal;
// get the event connected to this journal:
/** @var PiggyBankEvent $event */
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
if (is_null($event)) {
return;
}
$piggyBank = $event->piggyBank()->first();
$repetition = 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
$repetition->currentamount += $diff;
$repetition->save();
$event->amount = $amount;
$event->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,173 @@
<?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';
bcscale(2);
/** @var BalanceEntry $balanceEntry */
foreach ($this->getBalanceEntries() as $balanceEntry) {
$sum = bcadd($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()
{
$set = $this->bills->sortBy(
function (BillLine $bill) {
$active = intval($bill->getBill()->active) == 0 ? 1 : 0;
$name = $bill->getBill()->name;
return $active . $name;
}
);
return $set;
}
}

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 string */
protected $amount;
/** @var BillModel */
protected $bill;
/** @var bool */
protected $hit;
/** @var string */
protected $max;
/** @var string */
protected $min;
/**
* @return string
*/
public function getAmount()
{
return $this->amount;
}
/**
* @param string $amount
*/
public function setAmount($amount)
{
$this->amount = $amount;
}
/**
* @return BillModel
*/
public function getBill()
{
return $this->bill;
}
/**
* @param BillModel $bill
*/
public function setBill($bill)
{
$this->bill = $bill;
}
/**
* @return string
*/
public function getMax()
{
return $this->max;
}
/**
* @param string $max
*/
public function setMax($max)
{
$this->max = $max;
}
/**
* @return string
*/
public function getMin()
{
return $this->min;
}
/**
* @param string $min
*/
public function setMin($min)
{
$this->min = $min;
}
/**
* @return boolean
*/
public function isActive()
{
return $this->active;
}
/**
* @param boolean $active
*/
public function setActive($active)
{
$this->active = $active;
}
/**
* @return boolean
*/
public function isHit()
{
return $this->hit;
}
/**
* @param boolean $hit
*/
public function setHit($hit)
{
$this->hit = $hit;
}
}

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()
{
$set = $this->categories->sortByDesc(
function (CategoryModel $category) {
return $category->spent;
}
);
return $set;
}
/**
* @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()
{
$set = $this->expenses->sortByDesc(
function (stdClass $object) {
return $object->amount;
}
);
return $set;
}
/**
* @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()
{
$set = $this->incomes->sortByDesc(
function (stdClass $object) {
return $object->amount;
}
);
return $set;
}
/**
* @return string
*/
public function getTotal()
{
return strval(round($this->total, 2));
}
}

99
app/Helpers/Help/Help.php Normal file
View File

@@ -0,0 +1,99 @@
<?php
namespace FireflyIII\Helpers\Help;
use Cache;
use ErrorException;
use League\CommonMark\CommonMarkConverter;
use Log;
use Route;
/**
* Class Help
*
* @package FireflyIII\Helpers\Help
*/
class Help implements HelpInterface
{
/**
* @codeCoverageIgnore
*
* @param $key
*
* @return string
*/
public function getFromCache($key)
{
return Cache::get($key);
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return array
*/
public function getFromGithub($route)
{
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md';
$routeIndex = str_replace('.', '-', $route);
$title = trans('help.' . $routeIndex);
$content = [
'text' => '<p>There is no help for this route!</p>',
'title' => $title,
];
try {
$content['text'] = file_get_contents($uri);
} catch (ErrorException $e) {
Log::error(trim($e->getMessage()));
}
if (strlen(trim($content['text'])) == 0) {
$content['text'] = '<p>There is no help for this route.</p>';
}
$converter = new CommonMarkConverter();
$content['text'] = $converter->convertToHtml($content['text']);
return $content;
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return bool
*/
public function hasRoute($route)
{
return Route::has($route);
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return bool
*/
public function inCache($route)
{
return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text');
}
/**
* @codeCoverageIgnore
*
* @param $route
* @param array $content
*
* @internal param $title
*/
public function putInCache($route, array $content)
{
Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week.
Cache::put('help.' . $route . '.title', $content['title'], 10080);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace FireflyIII\Helpers\Help;
/**
* Interface HelpInterface
*
* @package FireflyIII\Helpers\Help
*/
interface HelpInterface
{
/**
* @param $key
*
* @return string
*/
public function getFromCache($key);
/**
* @param $route
*
* @return array
*/
public function getFromGithub($route);
/**
* @param $route
*
* @return bool
*/
public function hasRoute($route);
/**
* @param $route
*
* @return bool
*/
public function inCache($route);
/**
* @param $route
* @param array $content
*
* @return void
*/
public function putInCache($route, array $content);
}

View File

@@ -2,11 +2,24 @@
namespace FireflyIII\Helpers\Report;
use Auth;
use App;
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 FireflyIII\Models\Bill;
use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
/**
* Class ReportHelper
@@ -16,76 +29,352 @@ use Illuminate\Support\Collection;
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;
}
/**
* @return Carbon
*/
public function firstDate()
{
$journal = Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first();
if ($journal) {
return $journal->date;
}
return Carbon::now();
}
/**
* This method gets some kind of list for a monthly overview.
* 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 Collection
* @return AccountCollection
*/
public function getBudgetsForMonth(Carbon $date)
public function getAccountReport(Carbon $date, Carbon $end, $shared)
{
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
// all budgets
$set = \Auth::user()->budgets()
->leftJoin(
'budget_limits', function (JoinClause $join) use ($date) {
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
}
)
->get(['budgets.*', 'budget_limits.amount as amount']);
$budgets = $this->_helper->makeArray($set);
$amountSet = $this->_queries->journalsByBudget($start, $end);
$amounts = $this->_helper->makeArray($amountSet);
$combined = $this->_helper->mergeArrays($budgets, $amounts);
$combined[0]['spent'] = isset($combined[0]['spent']) ? $combined[0]['spent'] : 0.0;
$combined[0]['amount'] = isset($combined[0]['amount']) ? $combined[0]['amount'] : 0.0;
$combined[0]['name'] = 'No budget';
$accounts = $this->query->getAllAccounts($date, $end, $shared);
$start = 0;
$end = 0;
$diff = 0;
// find transactions to shared expense accounts, which are without a budget by default:
$transfers = $this->_queries->sharedExpenses($start, $end);
foreach ($transfers as $transfer) {
$combined[0]['spent'] += floatval($transfer->amount) * -1;
// 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);
}
return $combined;
$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);
bcscale(2);
$diff = bcsub($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($bill->amount_min);
$billLine->setMax($bill->amount_max);
// is hit in period?
bcscale(2);
$set = $repository->getJournalsInRange($bill, $start, $end);
if ($set->count() == 0) {
$billLine->setHit(false);
} else {
$billLine->setHit(true);
$amount = '0';
foreach ($set as $entry) {
$amount = bcadd($amount, $entry->amount);
}
$billLine->setAmount($amount);
}
$collection->addBill($billLine);
}
return $collection;
}
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return BudgetCollection
*/
public function getBudgetReport(Carbon $start, Carbon $end, $shared)
{
$object = new BudgetCollection;
/** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$set = $repository->getBudgets();
foreach ($set as $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);
}
}
// 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;
}
/**
@@ -95,81 +384,20 @@ class ReportHelper implements ReportHelperInterface
*/
public function listOfMonths(Carbon $date)
{
$start = clone $date;
$end = Carbon::now();
$months = [];
while ($start <= $end) {
$months[] = [
'formatted' => $start->format('F Y'),
'month' => intval($start->format('m')),
'year' => intval($start->format('Y')),
$year = $start->year;
$months[$year][] = [
'formatted' => $start->formatLocalized('%B %Y'),
'month' => $start->month,
'year' => $year,
];
$start->addMonth();
}
return $months;
}
/**
* @param Carbon $date
*
* @return array
*/
public function listOfYears(Carbon $date)
{
$start = clone $date;
$end = Carbon::now();
$years = [];
while ($start <= $end) {
$years[] = $start->format('Y');
$start->addYear();
}
return $years;
}
/**
* @param Carbon $date
*
* @return array
*/
public function yearBalanceReport(Carbon $date)
{
$start = clone $date;
$end = clone $date;
$sharedAccounts = [];
$sharedCollection = \Auth::user()->accounts()
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('account_meta.name', '=', 'accountRole')
->where('account_meta.data', '=', json_encode('sharedExpense'))
->get(['accounts.id']);
foreach ($sharedCollection as $account) {
$sharedAccounts[] = $account->id;
}
$accounts = \Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->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) {
$report[] = [
'start' => \Steam::balance($account, $start),
'end' => \Steam::balance($account, $end),
'account' => $account,
'shared' => $account->accountRole == 'sharedExpense'
];
}
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\Bill as BillCollection;
use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
use FireflyIII\Helpers\Collection\Category as CategoryCollection;
use FireflyIII\Helpers\Collection\Expense;
use FireflyIII\Helpers\Collection\Income;
/**
* Interface ReportHelperInterface
@@ -13,11 +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);
/**
* @return Carbon
* 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 firstDate();
public function getBillReport(Carbon $start, Carbon $end, $shared);
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Balance
*/
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
@@ -26,37 +99,4 @@ interface ReportHelperInterface
*/
public function listOfMonths(Carbon $date);
/**
* @param Carbon $date
*
* @return array
*/
public function listOfYears(Carbon $date);
/**
* @param Carbon $date
*
* @return array
*/
public function yearBalanceReport(Carbon $date);
/**
* This methods fails to take in account transfers FROM shared accounts.
*
* @param Carbon $start
* @param Carbon $end
* @param int $limit
*
* @return Collection
*/
public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15);
/**
* This method gets some kind of list for a monthly overview.
*
* @param Carbon $date
*
* @return Collection
*/
public function getBudgetsForMonth(Carbon $date);
}
}

View File

@@ -1,17 +1,12 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 22/02/15
* Time: 18:30
*/
namespace FireflyIII\Helpers\Report;
use Auth;
use Carbon\Carbon;
use DB;
use Crypt;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
@@ -25,79 +20,64 @@ use Steam;
*/
class ReportQuery implements ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
* See ReportQueryInterface::incomeInPeriodCorrected
*
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*/
public function accountList()
{
return Auth::user()->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
}
)
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
->where('active', 1)
->where(
function (Builder $query) {
$query->where('account_meta.data', '!=', '"sharedExpense"');
$query->orWhereNull('account_meta.data');
}
)
->get(['accounts.*']);
}
/**
* This method will get a list of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end)
public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false)
{
$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)
->whereNotNull('transaction_group_transaction_journal.transaction_group_id')
->first(
[
DB::Raw('SUM(`transactions`.`amount`) as `amount`')
]
);
$sum = 0;
if (!is_null($set)) {
$sum = floatval($set->amount);
$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->orderBy('transaction_journals.date');
return $sum;
// 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']
);
$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;
}
);
return $data;
}
/**
@@ -105,29 +85,42 @@ class ReportQuery implements ReportQueryInterface
*
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*/
public function getAllAccounts(Carbon $start, Carbon $end)
public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false)
{
$set = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')
->accountTypeIn(['Default account', 'Asset account', 'Cash account'])
->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', '!=', '"sharedExpense"');
$query->orWhereNull('account_meta.data');
}
)
->get(['accounts.*']);
$query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')
->accountTypeIn(['Default account', 'Asset account', 'Cash account']);
if ($includeShared === 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');
}
);
}
$set = $query->get(['accounts.*']);
$set->each(
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
* day.
*/
$yesterday = clone $start;
$yesterday->subDay();
/** @noinspection PhpParamsInspection */
$account->startBalance = Steam::balance($account, $start);
$account->startBalance = Steam::balance($account, $yesterday);
$account->endBalance = Steam::balance($account, $end);
}
);
@@ -135,376 +128,156 @@ 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)
{
$set = TransactionJournal::
leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->before($end)
->after($start)
->where('accounts.id', $account->id)
->where('transaction_journals.user_id', Auth::user()->id)
->where('transaction_types.type', 'Withdrawal')
->groupBy('budgets.id')
->orderBy('budgets.name', 'ASC')
->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `amount`')]);
return $set;
}
/**
* 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.
*
* 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 $includeShared
*
* @return Collection
*/
public function incomeByPeriod(Carbon $start, Carbon $end)
public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false)
{
return TransactionJournal::
$query = $this->queryJournalsWithTransactions($start, $end);
if ($includeShared === false) {
// only get deposits not to a shared account
// and transfers to a shared account.
$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"');
}
);
}
);
} else {
// any deposit is fine.
$query->where('transaction_types.type', 'Deposit');
}
$query->orderBy('transaction_journals.date');
// get everything
$data = $query->get(
['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 (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;
}
);
return $data;
}
/**
* Covers tags
*
* @param Account $account
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end)
{
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 string
*/
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false)
{
return
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');
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Builder
*/
protected function queryJournalsWithTransactions(Carbon $start, Carbon $end)
{
$query = TransactionJournal::
leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
->leftJoin(
'account_meta as acm_from', function (JoinClause $join) {
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
->leftJoin(
'account_meta as acm_to', function (JoinClause $join) {
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
}
)
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where(
function ($query) {
$query->where(
function ($q) {
$q->where('transaction_types.type', 'Deposit');
$q->where('acm_to.data', '!=', '"sharedExpense"');
}
);
$query->orWhere(
function ($q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_from.data', '=', '"sharedExpense"');
}
);
}
)
->before($end)->after($start)
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('t_from.account_id')->orderBy('transaction_journals.date')
->get(
['transaction_journals.id',
'transaction_journals.description',
'transaction_journals.encrypted',
'transaction_types.type',
't_to.amount', 'transaction_journals.date', 't_from.account_id as account_id',
'ac_from.name as name']
);
->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;
}
/**
* Gets a list of expenses grouped by the budget they were filed under.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsByBudget(Carbon $start, Carbon $end)
{
return 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')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->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('account_meta.data', '!=', '"sharedExpense"')
->where('transaction_types.type', 'Withdrawal')
->groupBy('budgets.id')
->orderBy('budgets.name', 'ASC')
->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
*
* @return Collection
*/
public function journalsByCategory(Carbon $start, Carbon $end)
{
return 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')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->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('account_meta.data', '!=', '"sharedExpense"')
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('amount')
->get(['categories.id', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]);
}
/**
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* So now it will include them!
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsByExpenseAccount(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
->leftJoin(
'account_meta as acm_from', function (JoinClause $join) {
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
->leftJoin(
'account_meta as acm_to', function (JoinClause $join) {
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
}
)
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where(
function ($query) {
$query->where(
function ($q) {
$q->where('transaction_types.type', 'Withdrawal');
$q->where('acm_from.data', '!=', '"sharedExpense"');
}
);
$query->orWhere(
function ($q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_to.data', '=', '"sharedExpense"');
}
);
}
)
->before($end)
->after($start)
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('t_to.account_id')
->orderBy('amount', 'DESC')
->get(['t_to.account_id as id', 'ac_to.name as name', DB::Raw('SUM(t_to.amount) as `amount`')]);
}
/**
* This method returns all deposits into asset accounts, grouped by the revenue account,
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsByRevenueAccount(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
->leftJoin(
'account_meta as acm_from', function (JoinClause $join) {
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
->leftJoin(
'account_meta as acm_to', function (JoinClause $join) {
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
}
)
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where(
function ($query) {
$query->where(
function ($q) {
$q->where('transaction_types.type', 'Deposit');
$q->where('acm_to.data', '!=', '"sharedExpense"');
}
);
$query->orWhere(
function ($q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_from.data', '=', '"sharedExpense"');
}
);
}
)
->before($end)->after($start)
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('t_from.account_id')->orderBy('amount')
->get(['t_from.account_id as account_id', 'ac_from.name as name', DB::Raw('SUM(t_from.amount) as `amount`')]);
}
/**
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
* expenses.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpenses(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
'transactions.amount', '>', 0
);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->where('account_meta.data', '"sharedExpense"')
->after($start)
->before($end)
->where('transaction_types.type', 'Transfer')
->where('transaction_journals.user_id', Auth::user()->id)
->get(
['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name',
'transactions.amount']
);
}
/**
* With a slightly misleading name, this query returns all transfers to shared accounts
* which are technically expenses, since it won't be just your money that gets spend.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpensesByCategory(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
'transactions.amount', '>', 0
);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
->where('account_meta.data', '"sharedExpense"')
->after($start)
->before($end)
->where('transaction_types.type', 'Transfer')
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('categories.name')
->get(
[
'categories.id',
'categories.name as name',
DB::Raw('SUM(`transactions`.`amount`) * -1 AS `amount`')
]
);
}
}
}

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,120 +16,66 @@ interface ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
* See ReportQueryInterface::incomeInPeriodCorrected
*
* 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();
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 $includeShared
*
* @return Collection
*/
public function getAllAccounts(Carbon $start, Carbon $end);
public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = 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.
* 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 incomeByPeriod(Carbon $start, Carbon $end);
public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false);
/**
* Gets a list of expenses grouped by the budget they were filed under.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsByBudget(Carbon $start, Carbon $end);
/**
* 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
*
* @return Collection
*/
public function journalsByCategory(Carbon $start, Carbon $end);
/**
* 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
*
* @return Collection
*/
public function journalsByExpenseAccount(Carbon $start, Carbon $end);
/**
* This method returns all deposits into asset accounts, grouped by the revenue account,
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsByRevenueAccount(Carbon $start, Carbon $end);
/**
* 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);
/**
* Grabs a summary of all expenses grouped by budget, related to the account.
* 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);
/**
* 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
* @param bool $shared
*
* @return Collection
* @return string
*/
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end);
}
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false);
}

View File

@@ -1,16 +1,17 @@
<?php namespace FireflyIII\Http\Controllers;
use App;
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\AccountFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Session;
use Steam;
use URL;
use View;
/**
@@ -21,12 +22,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'));
}
/**
@@ -36,8 +38,16 @@ class AccountController extends Controller
*/
public function create($what = 'asset')
{
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $what);
$subTitle = 'Create a new ' . e($what) . ' account';
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$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'));
@@ -50,17 +60,24 @@ 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'));
}
/**
* @param Account $account
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Account $account, AccountRepositoryInterface $repository)
public function destroy(AccountRepositoryInterface $repository, Account $account)
{
$type = $account->accountType->type;
@@ -69,70 +86,103 @@ 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]));
Preferences::mark();
return Redirect::route('accounts.index', $typeName);
return Redirect::to(Session::get('accounts.delete.url'));
}
public function edit(Account $account, AccountRepositoryInterface $repository)
/**
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @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);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('accounts.edit.fromUpdate') !== true) {
Session::put('accounts.edit.url', URL::previous());
}
Session::forget('accounts.edit.fromUpdate');
// pre fill some useful values.
// the opening balance is tricky:
$openingBalanceAmount = null;
if ($openingBalance) {
$transaction = $openingBalance->transactions()->where('account_id', $account->id)->first();
$transaction = $repository->getFirstTransaction($openingBalance, $account);
$openingBalanceAmount = $transaction->amount;
}
$preFilled = [
'accountRole' => $account->getMeta('accountRole'),
'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null,
'openingBalance' => $openingBalanceAmount
'accountRole' => $account->getMeta('accountRole'),
'ccType' => $account->getMeta('ccType'),
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null,
'openingBalance' => $openingBalanceAmount,
'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'));
}
/**
* @param string $what
* @param AccountRepositoryInterface $repository
* @param $what
*
* @return View
* @return \Illuminate\View\View
*/
public function index($what = 'default')
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 = Auth::user()->accounts()->accountTypeIn($types)->get(['accounts.*']);
$accounts = $repository->getAccounts($types);
// last activity:
/**
* HERE WE ARE
*/
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$start->subDay();
$accounts->each(
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()));
}
);
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
}
/**
* @param Account $account
* @param string $range
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return \Illuminate\View\View
*/
public function show(Account $account, $range = 'session')
public function show(AccountRepositoryInterface $repository, Account $account)
{
/** @var \FireflyIII\Repositories\Account\AccountRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Account\AccountRepositoryInterface');
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$journals = $repository->getJournals($account, $page, $range);
$subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
$journals = $repository->getJournals($account, $page);
$subTitle = trans('firefly.details_for_' . $what, ['name' => $account->name]);
$journals->setPath('accounts/show/' . $account->id);
return view('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle'));
return view('accounts.show', compact('account', 'what', 'subTitleIcon', 'journals', 'subTitle'));
}
/**
@@ -146,47 +196,70 @@ class AccountController extends Controller
$accountData = [
'name' => $request->input('name'),
'accountType' => $request->input('what'),
'virtualBalance' => floatval($request->input('virtualBalance')),
'active' => true,
'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);
Session::flash('success', 'New account "' . $account->name . '" stored!');
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('accounts.create.fromStore', true);
return Redirect::route('accounts.create')->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('accounts.create.url'));
return Redirect::route('accounts.index', $request->input('what'));
}
/**
* @param Account $account
* @param AccountFormRequest $request
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Account $account, AccountFormRequest $request, AccountRepositoryInterface $repository)
public function update(AccountFormRequest $request, AccountRepositoryInterface $repository, Account $account)
{
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$accountData = [
'name' => $request->input('name'),
'active' => $request->input('active'),
'user' => Auth::user()->id,
'accountRole' => $request->input('accountRole'),
'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'),
];
$repository->update($account, $accountData);
Session::flash('success', 'Account "' . $account->name . '" updated.');
Preferences::mark();
return Redirect::route('accounts.index', $what);
if (intval(Input::get('return_to_edit')) === 1) {
// 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]);
}
// redirect to previous URL.
return Redirect::to(Session::get('accounts.edit.url'));
}

View File

@@ -1,9 +1,17 @@
<?php namespace FireflyIII\Http\Controllers\Auth;
use App;
use Auth;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Registrar;
use FireflyIII\Models\Role;
use FireflyIII\User;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Mail\Message;
use Mail;
use Session;
use Twig;
use Validator;
/**
* Class AuthController
@@ -31,16 +39,113 @@ class AuthController extends Controller
/**
* Create a new authentication controller instance.
*
* @param \Illuminate\Contracts\Auth\Guard $auth
* @param \Illuminate\Contracts\Auth\Registrar $registrar
* @codeCoverageIgnore
*
*/
public function __construct(Guard $auth, Registrar $registrar)
public function __construct()
{
$this->auth = $auth;
$this->registrar = $registrar;
$this->middleware('guest', ['except' => 'getLogout']);
}
/**
* Show the application login form.
*
* @codeCoverageIgnore
* @return \Illuminate\Http\Response
*
*/
public function getLogin()
{
return Twig::render('auth.login');
}
/**
* Handle a registration request for the application.
*
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
// @codeCoverageIgnoreStart
}
// @codeCoverageIgnoreEnd
$data = $request->all();
$data['password'] = bcrypt($data['password']);
Auth::login($this->create($data));
// get the email address
if (Auth::user() instanceof User) {
$email = Auth::user()->email;
$address = route('index');
// send email.
Mail::send(
['emails.registered-html', 'emails.registered'], ['address' => $address], 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();
Auth::user()->attachRole($admin);
}
return redirect($this->redirectPath());
}
// @codeCoverageIgnoreStart
App::abort(500, 'Not a user!');
return redirect('/');
// @codeCoverageIgnoreEnd
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
*
* @return \Illuminate\Contracts\Validation\Validator
*/
public function validator(array $data)
{
return Validator::make(
$data, [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]
);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
*
* @return User
*/
public function create(array $data)
{
return User::create(
[
'email' => $data['email'],
'password' => $data['password'],
]
);
}
}

View File

@@ -1,13 +1,12 @@
<?php namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\PasswordBroker;
use Illuminate\Foundation\Auth\ResetsPasswords;
/**
* Class PasswordController
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Controllers\Auth
*/
class PasswordController extends Controller
@@ -32,15 +31,11 @@ class PasswordController extends Controller
/**
* Create a new password controller instance.
*
* @param \Illuminate\Contracts\Auth\Guard $auth
* @param \Illuminate\Contracts\Auth\PasswordBroker $passwords
* @codeCoverageIgnore
*
*/
public function __construct(Guard $auth, PasswordBroker $passwords)
public function __construct()
{
$this->auth = $auth;
$this->passwords = $passwords;
$this->middleware('guest');
}

View File

@@ -1,13 +1,12 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests;
use Config;
use FireflyIII\Http\Requests\BillFormRequest;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Session;
use URL;
@@ -21,56 +20,88 @@ use View;
class BillController extends Controller
{
/**
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Bills');
parent::__construct();
View::share('title', trans('firefly.bills'));
View::share('mainTitleIcon', 'fa-calendar-o');
}
/**
* @return $this
* @return \Illuminate\View\View
*/
public function create()
{
$periods = \Config::get('firefly.periods_to_text');
$periods = Config::get('firefly.periods_to_text');
$subTitle = trans('firefly.create_new_bill');
return view('bills.create')->with('periods', $periods)->with('subTitle', 'Create new');
// put previous url in session if not redirect from store (not "create another").
if (Session::get('bills.create.fromStore') !== true) {
Session::put('bills.create.url', URL::previous());
}
Session::forget('bills.create.fromStore');
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'create');
return view('bills.create', compact('periods', 'subTitle'));
}
/**
* @param Bill $bill
*
* @return $this
* @return \Illuminate\View\View
*/
public function delete(Bill $bill)
{
return view('bills.delete')->with('bill', $bill)->with('subTitle', 'Delete "' . e($bill->name) . '"');
// put previous url in session
Session::put('bills.delete.url', URL::previous());
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'delete');
$subTitle = trans('firefly.delete_bill', ['name' => $bill->name]);
return view('bills.delete', compact('bill', 'subTitle'));
}
/**
* @param Bill $bill
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Bill $bill)
public function destroy(BillRepositoryInterface $repository, Bill $bill)
{
$bill->delete();
Session::flash('success', 'The bill was deleted.');
$repository->destroy($bill);
return Redirect::route('bills.index');
Session::flash('success', 'The bill was deleted.');
Preferences::mark();
return Redirect::to(Session::get('bills.delete.url'));
}
/**
* @param Bill $bill
*
* @return $this
* @return \Illuminate\View\View
*/
public function edit(Bill $bill)
{
$periods = \Config::get('firefly.periods_to_text');
$periods = Config::get('firefly.periods_to_text');
$subTitle = trans('firefly.edit_bill', ['name' => $bill->name]);
return view('bills.edit')->with('periods', $periods)->with('bill', $bill)->with('subTitle', 'Edit "' . e($bill->name) . '"');
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('bills.edit.fromUpdate') !== true) {
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'));
}
/**
@@ -80,15 +111,11 @@ class BillController extends Controller
*/
public function index(BillRepositoryInterface $repository)
{
$bills = Auth::user()->bills()->get();
$bills = $repository->getBills();
$bills->each(
function (Bill $bill) use ($repository) {
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
$last = $bill->transactionjournals()->orderBy('date', 'DESC')->first();
$bill->lastFoundMatch = null;
if ($last) {
$bill->lastFoundMatch = $last->date;
}
$bill->lastFoundMatch = $repository->lastFoundMatch($bill);
}
);
@@ -96,144 +123,97 @@ class BillController extends Controller
}
/**
* @param Bill $bill
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return mixed
* @return \Illuminate\Http\RedirectResponse
*/
public function rescan(Bill $bill, BillRepositoryInterface $repository)
public function rescan(BillRepositoryInterface $repository, Bill $bill)
{
if (intval($bill->active) == 0) {
Session::flash('warning', 'Inactive bills cannot be scanned.');
return Redirect::intended('/');
return Redirect::to(URL::previous());
}
$set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get(['transaction_journal_id']);
$ids = [];
$journals = $repository->getPossiblyRelatedJournals($bill);
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$repository->scan($bill, $journal);
}
/** @var Transaction $entry */
foreach ($set as $entry) {
$ids[] = intval($entry->transaction_journal_id);
}
if (count($ids) > 0) {
$journals = Auth::user()->transactionjournals()->whereIn('id',$ids)->get();
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$repository->scan($bill, $journal);
}
}
Session::flash('success', 'Rescanned everything.');
Preferences::mark();
return Redirect::to(URL::previous());
}
/**
* @param Bill $bill
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return mixed
* @return \Illuminate\View\View
*/
public function show(Bill $bill, BillRepositoryInterface $repository)
public function show(BillRepositoryInterface $repository, Bill $bill)
{
$journals = $bill->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get();
$journals = $repository->getJournals($bill);
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
$hideBill = true;
$subTitle = e($bill->name);
return view('bills.show', compact('journals', 'hideBill', 'bill'))->with('subTitle', e($bill->name));
return view('bills.show', compact('journals', 'hideBill', 'bill', 'subTitle'));
}
/**
* @return $this
* @param BillFormRequest $request
* @param BillRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(BillFormRequest $request, BillRepositoryInterface $repository)
{
var_dump($request->all());
$billData = [
'name' => $request->get('name'),
'match' => $request->get('match'),
'amount_min' => floatval($request->get('amount_min')),
'amount_currency_id' => floatval($request->get('amount_currency_id')),
'amount_max' => floatval($request->get('amount_max')),
'date' => new Carbon($request->get('date')),
'user' => Auth::user()->id,
'repeat_freq' => $request->get('repeat_freq'),
'skip' => intval($request->get('skip')),
'automatch' => intval($request->get('automatch')) === 1,
'active' => intval($request->get('active')) === 1,
];
$bill = $repository->store($billData);
$billData = $request->getBillData();
$bill = $repository->store($billData);
Session::flash('success', 'Bill "' . e($bill->name) . '" stored.');
Preferences::mark();
return Redirect::route('bills.index');
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('bills.create.fromStore', true);
return Redirect::route('bills.create')->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('bills.create.url'));
}
/**
* @param Bill $bill
* @param BillFormRequest $request
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return $this
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Bill $bill, BillFormRequest $request, BillRepositoryInterface $repository)
public function update(BillFormRequest $request, BillRepositoryInterface $repository, Bill $bill)
{
$billData = [
'name' => $request->get('name'),
'match' => $request->get('match'),
'amount_min' => floatval($request->get('amount_min')),
'amount_currency_id' => floatval($request->get('amount_currency_id')),
'amount_max' => floatval($request->get('amount_max')),
'date' => new Carbon($request->get('date')),
'user' => Auth::user()->id,
'repeat_freq' => $request->get('repeat_freq'),
'skip' => intval($request->get('skip')),
'automatch' => intval($request->get('automatch')) === 1,
'active' => intval($request->get('active')) === 1,
];
$bill = $repository->update($bill, $billData);
$billData = $request->getBillData();
$bill = $repository->update($bill, $billData);
Session::flash('success', 'Bill "' . e($bill->name) . '" updated.');
Preferences::mark();
return Redirect::route('bills.index');
if (intval(Input::get('return_to_edit')) === 1) {
// 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]);
}
// $data = Input::except('_token');
// $data['active'] = intval(Input::get('active'));
// $data['automatch'] = intval(Input::get('automatch'));
// $data['user_id'] = Auth::user()->id;
//
// // always validate:
// $messages = $this->_repository->validate($data);
//
// // flash messages:
// Session::flash('warnings', $messages['warnings']);
// Session::flash('successes', $messages['successes']);
// Session::flash('errors', $messages['errors']);
// if ($messages['errors']->count() > 0) {
// Session::flash('error', 'Could not update bill: ' . $messages['errors']->first());
//
// return Redirect::route('bills.edit', $bill->id)->withInput();
// }
//
// // return to update screen:
// if ($data['post_submit_action'] == 'validate_only') {
// return Redirect::route('bills.edit', $bill->id)->withInput();
// }
//
// // update
// $this->_repository->update($bill, $data);
// Session::flash('success', 'Bill "' . e($data['name']) . '" updated.');
//
// // go back to list
// if ($data['post_submit_action'] == 'update') {
// return Redirect::route('bills.index');
// }
//
// // go back to update screen.
// return Redirect::route('bills.edit', $bill->id)->withInput(['post_submit_action' => 'return_to_edit']);
// redirect to previous URL.
return Redirect::to(Session::get('bills.edit.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;
@@ -12,44 +12,64 @@ use Preferences;
use Redirect;
use Response;
use Session;
use URL;
use View;
/**
* Class BudgetController
*
* @package FireflyIII\Http\Controllers
* @SuppressWarnings(PHPMD.TooManyMethods)
*/
class BudgetController extends Controller
{
/**
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Budgets');
parent::__construct();
View::share('title', trans('firefly.budgets'));
View::share('mainTitleIcon', 'fa-tasks');
View::share('hideBudgets', true);
}
/**
* @param Budget $budget
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return \Illuminate\Http\JsonResponse
* @throws Exception
* @return \Symfony\Component\HttpFoundation\Response
*/
public function amount(Budget $budget, BudgetRepositoryInterface $repository)
public function amount(BudgetRepositoryInterface $repository, Budget $budget)
{
$amount = intval(Input::get('amount'));
$date = Session::get('start', Carbon::now()->startOfMonth());
$limitRepetition = $repository->updateLimitAmount($budget, $date, $amount);
if ($amount == 0) {
$limitRepetition = null;
}
Preferences::mark();
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]);
}
/**
* @return $this
* @return \Illuminate\View\View
*/
public function create()
{
return view('budgets.create')->with('subTitle', 'Create a new budget');
// put previous url in session if not redirect from store (not "create another").
if (Session::get('budgets.create.fromStore') !== true) {
Session::put('budgets.create.url', URL::previous());
}
Session::forget('budgets.create.fromStore');
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'create');
$subTitle = trans('firefly.create_new_budget');
return view('budgets.create', compact('subTitle'));
}
/**
@@ -59,13 +79,19 @@ 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'));
}
/**
* @param Budget $budget
* @param Budget $budget
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
@@ -75,83 +101,144 @@ class BudgetController extends Controller
$name = $budget->name;
$repository->destroy($budget);
Session::flash('success', 'The budget "' . e($name) . '" was deleted.');
return Redirect::route('budgets.index');
Session::flash('success', 'The budget "' . e($name) . '" was deleted.');
Preferences::mark();
return Redirect::to(Session::get('budgets.delete.url'));
}
/**
* @param Budget $budget
*
* @return $this
* @return \Illuminate\View\View
*/
public function edit(Budget $budget)
{
$subTitle = 'Edit budget "' . e($budget->name) . '"';
$subTitle = trans('firefly.edit_budget', ['name' => $budget->name]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('budgets.edit.fromUpdate') !== true) {
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'));
}
/**
* @return mixed
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index(BudgetRepositoryInterface $repository)
{
$budgets = Auth::user()->budgets()->get();
$budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets();
$spent = '0';
$budgeted = '0';
bcscale(2);
/**
* Do some cleanup:
*/
$repository->cleanupBudgets();
// loop the budgets:
$budgets->each(
function (Budget $budget) use ($repository) {
$date = Session::get('start', Carbon::now()->startOfMonth());
$budget->spent = $repository->spentInMonth($budget, $date);
$budget->currentRep = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']);
/** @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')
);
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$spent = $budgets->sum('spent');
$amount = Preferences::get('budgetIncomeTotal' . $date, 1000)->data;
$overspent = $spent > $amount;
$spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
return view('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
}
/**
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function noBudget()
public function noBudget(BudgetRepositoryInterface $repository)
{
$start = \Session::get('start', Carbon::now()->startOfMonth());
$end = \Session::get('end', Carbon::now()->startOfMonth());
$list = Auth::user()
->transactionjournals()
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('budget_transaction_journal.id')
->before($end)
->after($start)
->orderBy('transaction_journals.date')
->get(['transaction_journals.*']);
$subTitle = 'Transactions without a budget in ' . $start->format('F Y');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->startOfMonth());
$list = $repository->getWithoutBudget($start, $end);
$subTitle = trans(
'firefly.without_budget_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
return view('budgets.noBudget', compact('list', 'subTitle'));
}
/**
* @return mixed
* @return \Illuminate\Http\RedirectResponse
*/
public function postUpdateIncome()
{
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
Preferences::set('budgetIncomeTotal' . $date, intval(Input::get('amount')));
Preferences::mark();
return Redirect::route('budgets.index');
}
/**
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Illuminate\View\View
*/
public function show(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition = null)
{
if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) {
$message = 'Invalid selection.';
return view('error', compact('message'));
}
$journals = $repository->getJournals($budget, $repetition);
if (is_null($repetition->id)) {
$limits = $repository->getBudgetLimits($budget);
$subTitle = e($budget->name);
} else {
$limits = [$repetition->budgetLimit];
$subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]);
}
$journals->setPath('/budgets/show/' . $budget->id);
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
}
/**
* @param BudgetFormRequest $request
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository)
{
$budgetData = [
@@ -161,62 +248,60 @@ class BudgetController extends Controller
$budget = $repository->store($budgetData);
Session::flash('success', 'New budget "' . $budget->name . '" stored!');
Preferences::mark();
return Redirect::route('budgets.index');
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('budgets.create.fromStore', true);
}
/**
*
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Illuminate\View\View
*/
public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository)
{
if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) {
return view('error')->with('message', 'Invalid selection.');
return Redirect::route('budgets.create')->withInput();
}
$hideBudget = true; // used in transaction list.
$journals = $repository->getJournals($budget, $repetition);
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
// redirect to previous URL.
return Redirect::to(Session::get('budgets.create.url'));
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
}
/**
* @param Budget $budget
* @param BudgetFormRequest $request
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Budget $budget, BudgetFormRequest $request, BudgetRepositoryInterface $repository)
public function update(BudgetFormRequest $request, BudgetRepositoryInterface $repository, Budget $budget)
{
$budgetData = [
'name' => $request->input('name'),
'name' => $request->input('name'),
'active' => intval($request->input('active')) == 1
];
$repository->update($budget, $budgetData);
Session::flash('success', 'Budget "' . $budget->name . '" updated.');
Preferences::mark();
return Redirect::route('budgets.index');
if (intval(Input::get('return_to_edit')) === 1) {
// 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]);
}
// redirect to previous URL.
return Redirect::to(Session::get('budgets.edit.url'));
}
/**
* @return $this
* @return \Illuminate\View\View
*/
public function updateIncome()
{
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$budgetAmount = Preferences::get('budgetIncomeTotal' . $date, 1000);
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$amount = Preferences::get('budgetIncomeTotal' . $date, 1000);
return view('budgets.income')->with('amount', $budgetAmount);
return view('budgets.income', compact('amount'));
}
}

View File

@@ -2,16 +2,16 @@
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\CategoryFormRequest;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use Illuminate\Pagination\LengthAwarePaginator;
use Input;
use Preferences;
use Redirect;
use Session;
use URL;
use View;
use Input;
/**
* Class CategoryController
@@ -22,58 +22,30 @@ class CategoryController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Categories');
parent::__construct();
View::share('title', trans('firefly.categories'));
View::share('mainTitleIcon', 'fa-bar-chart');
}
/**
* @return $this
*/
public function create()
{
return view('categories.create')->with('subTitle', 'Create a new category');
}
/**
* @param Category $category
*
* @return $this
*/
public function show(Category $category, CategoryRepositoryInterface $repository)
{
$hideCategory = true; // used in list.
$page = intval(Input::get('page'));
$offset = $page > 0 ? $page * 50 : 0;
$set = $category->transactionJournals()->withRelevantData()->take(50)->offset($offset)->orderBy('date', 'DESC')->get(['transaction_journals.*']);
$count = $category->transactionJournals()->count();
$journals = new LengthAwarePaginator($set, $count, 50, $page);
return view('categories.show', compact('category', 'journals', 'hideCategory'));
}
/**
* @return \Illuminate\View\View
*/
public function noCategory()
public function create()
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->startOfMonth());
$list = Auth::user()
->transactionjournals()
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('category_transaction_journal.id')
->before($end)
->after($start)
->orderBy('transaction_journals.date')
->get(['transaction_journals.*']);
$subTitle = 'Transactions without a category in ' . $start->format('F Y');
// put previous url in session if not redirect from store (not "create another").
if (Session::get('categories.create.fromStore') !== true) {
Session::put('categories.create.url', URL::previous());
}
Session::forget('categories.create.fromStore');
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'create');
$subTitle = trans('firefly.create_new_category');
return view('categories.noCategory', compact('list', 'subTitle'));
return view('categories.create', compact('subTitle'));
}
/**
@@ -83,55 +55,114 @@ 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'));
}
/**
* @param Category $category
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Category $category, CategoryRepositoryInterface $repository)
public function destroy(CategoryRepositoryInterface $repository, Category $category)
{
$name = $category->name;
$repository->destroy($category);
Session::flash('success', 'The category "' . e($name) . '" was deleted.');
Preferences::mark();
return Redirect::route('categories.index');
return Redirect::to(Session::get('categories.delete.url'));
}
/**
* @param Category $category
*
* @return $this
* @return \Illuminate\View\View
*/
public function edit(Category $category)
{
$subTitle = 'Edit category "' . e($category->name) . '"';
$subTitle = trans('firefly.edit_category', ['name' => $category->name]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('categories.edit.fromUpdate') !== true) {
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'));
}
/**
* @return $this
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index()
public function index(CategoryRepositoryInterface $repository)
{
$categories = Auth::user()->categories()->get();
$categories = $repository->getCategories();
$categories->each(
function (Category $category) use ($repository) {
$category->lastActivity = $repository->getLatestActivity($category);
}
);
return view('categories.index', compact('categories'));
}
/**
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function noCategory(CategoryRepositoryInterface $repository)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->startOfMonth());
$list = $repository->getWithoutCategory($start, $end);
$subTitle = trans(
'firefly.without_category_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
return view('categories.noCategory', compact('list', 'subTitle'));
}
/**
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Illuminate\View\View
*/
public function show(CategoryRepositoryInterface $repository, Category $category)
{
$hideCategory = true; // used in list.
$page = intval(Input::get('page'));
$set = $repository->getJournals($category, $page);
$count = $repository->countJournals($category);
$journals = new LengthAwarePaginator($set, $count, 50, $page);
$journals->setPath('categories/show/' . $category->id);
return view('categories.show', compact('category', 'journals', 'hideCategory'));
}
/**
* @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository
*
* @return mixed
* @return \Illuminate\Http\RedirectResponse
*/
public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository)
{
@@ -142,20 +173,26 @@ class CategoryController extends Controller
$category = $repository->store($categoryData);
Session::flash('success', 'New category "' . $category->name . '" stored!');
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
Session::put('categories.create.fromStore', true);
return Redirect::route('categories.create')->withInput();
}
return Redirect::route('categories.index');
}
/**
* @param Category $category
* @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Category $category, CategoryFormRequest $request, CategoryRepositoryInterface $repository)
public function update(CategoryFormRequest $request, CategoryRepositoryInterface $repository, Category $category)
{
$categoryData = [
'name' => $request->input('name'),
@@ -164,8 +201,16 @@ class CategoryController extends Controller
$repository->update($category, $categoryData);
Session::flash('success', 'Category "' . $category->name . '" updated.');
Preferences::mark();
return Redirect::route('categories.index');
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('categories.edit.fromUpdate', true);
return Redirect::route('categories.edit', [$category->id]);
}
// redirect to previous URL.
return Redirect::to(Session::get('categories.edit.url'));
}

View File

@@ -0,0 +1,144 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Preferences;
use Response;
use Session;
/**
* Class AccountController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class AccountController extends Controller
{
/** @var \FireflyIII\Generator\Chart\Account\AccountChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Account\AccountChartGenerator');
}
/**
* Shows the balances for all the user's accounts.
*
* @param AccountRepositoryInterface $repository
*
* @param $year
* @param $month
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function all(AccountRepositoryInterface $repository, $year, $month, $shared = false)
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('all');
$cache->addProperty('accounts');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
/** @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);
}
}
}
// make chart:
$data = $this->generator->all($accounts, $start, $end);
$cache->store($data);
return Response::json($data);
}
/**
* Shows the balances for all the user's frontpage accounts.
*
* @param AccountRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(AccountRepositoryInterface $repository)
{
$frontPage = Preferences::get('frontPageAccounts', []);
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = clone Session::get('end', Carbon::now()->endOfMonth());
$accounts = $repository->getFrontpageAccounts($frontPage);
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('frontpage');
$cache->addProperty('accounts');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$data = $this->generator->frontpage($accounts, $start, $end);
$cache->store($data);
return Response::json($data);
}
/**
* Shows an account's balance for a single month.
*
* @param Account $account
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(Account $account)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('frontpage');
$cache->addProperty('single');
$cache->addProperty($account->id);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$data = $this->generator->single($account, $start, $end);
$cache->store($data);
return Response::json($data);
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use App;
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 FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Response;
use Session;
use Steam;
/**
* Class BillController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class BillController extends Controller
{
/** @var \FireflyIII\Generator\Chart\Bill\BillChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Bill\BillChartGenerator');
}
/**
* Shows all bills and whether or not theyve been paid this month (pie chart).
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('bills');
$cache->addProperty('frontpage');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$bills = $repository->getActiveBills();
$paid = new Collection; // journals.
$unpaid = new Collection; // bills
/** @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);
}
}
// build chart:
$data = $this->generator->frontpage($paid, $unpaid);
$cache->store($data);
return Response::json($data);
}
/**
* Shows the overview for a bill. The min/max amount and matched journals.
*
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(BillRepositoryInterface $repository, Bill $bill)
{
$cache = new CacheProperties;
$cache->addProperty('single');
$cache->addProperty('bill');
$cache->addProperty($bill->id);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
// get first transaction or today for start:
$results = $repository->getJournals($bill);
// resort:
$results = $results->sortBy(
function (TransactionJournal $journal) {
return $journal->date->format('U');
}
);
$data = $this->generator->single($bill, $results);
$cache->store($data);
return Response::json($data);
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
use Response;
use Session;
/**
* Class BudgetController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class BudgetController extends Controller
{
/** @var \FireflyIII\Generator\Chart\Budget\BudgetChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator');
}
/**
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budget(BudgetRepositoryInterface $repository, Budget $budget)
{
// dates and times
$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);
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($first);
$cache->addProperty($last);
$cache->addProperty('budget');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
while ($first < $last) {
$end = Navigation::addPeriod($first, $range, 0);
$end->subDay();
$chartDate = clone $end;
$chartDate->startOfMonth();
$spent = $repository->spentInPeriodCorrected($budget, $first, $end);
$entries->push([$chartDate, $spent]);
$first = Navigation::addPeriod($first, $range, 0);
}
$data = $this->generator->budget($entries);
$cache->store($data);
return Response::json($data);
}
/**
* Shows the amount left in a specific budget limit.
*
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('budget');
$cache->addProperty('limit');
$cache->addProperty($budget->id);
$cache->addProperty($repetition->id);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
$amount = $repetition->amount;
while ($start <= $end) {
/*
* Sum of expenses on this day:
*/
$sum = $repository->expensesOnDayCorrected($budget, $start);
$amount += $sum;
$entries->push([clone $start, $amount]);
$start->addDay();
}
$data = $this->generator->budgetLimit($entries);
$cache->store($data);
return Response::json($data);
}
/**
* Shows a budget list with spent/left/overspent.
*
* @param BudgetRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(BudgetRepositoryInterface $repository)
{
$budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$allEntries = new Collection;
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('budget');
$cache->addProperty('all');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
bcscale(2);
/** @var Budget $budget */
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, 0, 0]);
continue;
}
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
// $left can be less than zero.
// $overspent can be more than zero ( = overspending)
$left = max(bcsub($repetition->amount, $expenses), 0); // limited at zero.
$overspent = max(bcsub($expenses, $repetition->amount), 0); // limited at zero.
$name = $budget->name;
// $spent is maxed to the repetition amount:
$spent = $expenses > $repetition->amount ? $repetition->amount : $expenses;
$allEntries->push([$name, $left, $spent, $overspent, $repetition->amount, $expenses]);
}
}
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1;
$allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses, 0, 0]);
$data = $this->generator->frontpage($allEntries);
$cache->store($data);
return Response::json($data);
}
/**
* Show a yearly overview for a budget.
*
* @param BudgetRepositoryInterface $repository
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function year(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();
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('budget');
$cache->addProperty('year');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
while ($start < $end) {
// month is the current end of the period:
$month = clone $start;
$month->endOfMonth();
$row = [clone $start];
// each budget, fill the row:
foreach ($budgets as $budget) {
$spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
$row[] = $spent;
}
$entries->push($row);
$start->endOfMonth()->addDay();
}
$data = $this->generator->year($budgets, $entries);
$cache->store($data);
return Response::json($data);
}
}

View File

@@ -0,0 +1,216 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
use Response;
use Session;
/**
* Class CategoryController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class CategoryController extends Controller
{
/** @var \FireflyIII\Generator\Chart\Category\CategoryChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Category\CategoryChartGenerator');
}
/**
* Show an overview for a category for all time, per month/week/year.
*
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function all(CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
$start = $repository->getFirstActivityDate($category);
$range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($start, $range);
$end = new Carbon;
$entries = new Collection;
// chart properties for cache:
$cache = new CacheProperties();
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('all');
$cache->addProperty('categories');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range);
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
$entries->push([clone $start, $spent]);
$start = Navigation::addPeriod($start, $range, 0);
}
$data = $this->generator->all($entries);
$cache->store($data);
return Response::json($data);
}
/**
* Show this month's category overview.
*
* @param CategoryRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(CategoryRepositoryInterface $repository)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('category');
$cache->addProperty('frontpage');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$array = $repository->getCategoriesAndExpensesCorrected($start, $end);
// sort by callback:
uasort(
$array,
function ($left, $right) {
if ($left['sum'] == $right['sum']) {
return 0;
}
return ($left['sum'] < $right['sum']) ? 1 : -1;
}
);
$set = new Collection($array);
$data = $this->generator->frontpage($set);
return Response::json($data);
}
/**
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function month(CategoryRepositoryInterface $repository, Category $category)
{
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($category->id);
$cache->addProperty('category');
$cache->addProperty('month');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
while ($start <= $end) {
$spent = $repository->spentOnDaySumCorrected($category, $start);
$entries->push([clone $start, $spent]);
$start->addDay();
}
$data = $this->generator->month($entries);
$cache->store($data);
return Response::json($data);
}
/**
* This chart will only show expenses.
*
* @param CategoryRepositoryInterface $repository
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function year(CategoryRepositoryInterface $repository, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('category');
$cache->addProperty('year');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$shared = $shared == 'shared' ? true : false;
$categories = $repository->getCategories();
$entries = new Collection;
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;
}
$entries->push($row);
$start->addMonth();
}
$data = $this->generator->year($categories, $entries);
$cache->store($data);
return Response::json($data);
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use App;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Response;
/**
* Class PiggyBankController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class PiggyBankController extends Controller
{
/** @var \FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator');
}
/**
* Shows the piggy bank history.
*
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function history(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty('piggy-history');
$cache->addProperty($piggyBank->id);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
/** @var Collection $set */
$set = new Collection($repository->getEventSummarySet($piggyBank));
$data = $this->generator->history($set);
$cache->store($data);
return Response::json($data);
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Response;
/**
* Class ReportController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class ReportController extends Controller
{
/** @var \FireflyIII\Generator\Chart\Report\ReportChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Report\ReportChartGenerator');
}
/**
* Summarizes all income and expenses, per month, for a given year.
*
* @param ReportQueryInterface $query
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInOut(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 properties for cache:
$cache = new CacheProperties;
$cache->addProperty('yearInOut');
$cache->addProperty($year);
$cache->addProperty($shared);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$incomeSum = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount');
$expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount');
$entries->push([clone $start, $incomeSum, $expenseSum]);
$start->addMonth();
}
$data = $this->generator->yearInOut($entries);
$cache->store($data);
return Response::json($data);
}
/**
* Summarizes all income and expenses for a given year. Gives a total and an average.
*
* @param ReportQueryInterface $query
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInOutSummarized(ReportQueryInterface $query, $year, $shared = false)
{
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty('yearInOutSummarized');
$cache->addProperty($year);
$cache->addProperty($shared);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$income = '0';
$expense = '0';
$count = 0;
bcscale(2);
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$income = bcadd($income, $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
$expense = bcadd($expense, $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
$count++;
$start->addMonth();
}
$data = $this->generator->yearInOutSummarized($income, $expense, $count);
$cache->store($data);
return Response::json($data);
}
}

View File

@@ -1,8 +1,12 @@
<?php namespace FireflyIII\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Auth;
use Config;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Preferences;
use View;
/**
* Class Controller
@@ -12,6 +16,32 @@ use Illuminate\Routing\Controller as BaseController;
abstract class Controller extends BaseController
{
use DispatchesCommands, ValidatesRequests;
use DispatchesJobs, ValidatesRequests;
/** @var string */
protected $monthAndDayFormat;
/** @var string */
protected $monthFormat;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('hideBudgets', false);
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,14 +1,16 @@
<?php namespace FireflyIII\Http\Controllers;
use FireflyIII\Http\Requests;
use Auth;
use Cache;
use FireflyIII\Http\Requests\CurrencyFormRequest;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Session;
use URL;
use View;
use Cache;
/**
* Class CurrencyController
@@ -20,12 +22,12 @@ class CurrencyController extends Controller
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Currencies');
parent::__construct();
View::share('title', trans('firefly.currencies'));
View::share('mainTitleIcon', 'fa-usd');
}
@@ -35,7 +37,15 @@ class CurrencyController extends Controller
public function create()
{
$subTitleIcon = 'fa-plus';
$subTitle = 'Create a new currency';
$subTitle = trans('firefly.create_currency');
// put previous url in session if not redirect from store (not "create another").
if (Session::get('currency.create.fromStore') !== true) {
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'));
}
@@ -48,9 +58,8 @@ class CurrencyController extends Controller
public function defaultCurrency(TransactionCurrency $currency)
{
$currencyPreference = Preferences::get('currencyPreference', 'EUR');
$currencyPreference->data = $currency->code;
$currencyPreference->save();
Preferences::set('currencyPreference', $currency->code);
Preferences::mark();
Session::flash('success', $currency->name . ' is now the default currency.');
Cache::forget('FFCURRENCYSYMBOL');
@@ -61,40 +70,51 @@ class CurrencyController extends Controller
}
/**
* @param TransactionCurrency $currency
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
* @return \Illuminate\Http\RedirectResponse|View
*/
public function delete(TransactionCurrency $currency)
public function delete(CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
if ($currency->transactionJournals()->count() > 0) {
if ($repository->countJournals($currency) > 0) {
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
return Redirect::route('currency.index');
}
// put previous url in session
Session::put('currency.delete.url', URL::previous());
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'delete');
$subTitle = trans('form.delete_currency', ['name' => $currency->name]);
return view('currency.delete', compact('currency'));
return view('currency.delete', compact('currency', 'subTitle'));
}
/**
* @param TransactionCurrency $currency
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/
public function destroy(TransactionCurrency $currency)
public function destroy(CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
if ($currency->transactionJournals()->count() > 0) {
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
if ($repository->countJournals($currency) > 0) {
Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.');
return Redirect::route('currency.index');
}
Session::flash('success', 'Currency "' . e($currency->name) . '" deleted');
if (Auth::user()->hasRole('owner')) {
$currency->delete();
}
$currency->delete();
return Redirect::route('currency.index');
return Redirect::to(Session::get('currency.delete.url'));
}
/**
@@ -105,67 +125,93 @@ class CurrencyController extends Controller
public function edit(TransactionCurrency $currency)
{
$subTitleIcon = 'fa-pencil';
$subTitle = 'Edit currency "' . e($currency->name) . '"';
$subTitle = trans('firefly.edit_currency', ['name' => $currency->name]);
$currency->symbol = htmlentities($currency->symbol);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('currency.edit.fromUpdate') !== true) {
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'));
}
/**
* @param CurrencyRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index()
public function index(CurrencyRepositoryInterface $repository)
{
$currencies = TransactionCurrency::get();
$currencyPreference = Preferences::get('currencyPreference', 'EUR');
$defaultCurrency = TransactionCurrency::whereCode($currencyPreference->data)->first();
$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'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param CurrencyFormRequest $request
* @param CurrencyRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function store(CurrencyFormRequest $request)
public function store(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository)
{
$data = $request->getCurrencyData();
if (Auth::user()->hasRole('owner')) {
$currency = $repository->store($data);
Session::flash('success', 'Currency "' . $currency->name . '" created');
}
// no repository, because the currency controller is relatively simple.
$currency = TransactionCurrency::create(
[
'name' => $request->get('name'),
'code' => $request->get('code'),
'symbol' => $request->get('symbol'),
]
);
if (intval(Input::get('create_another')) === 1) {
Session::put('currency.create.fromStore', true);
Session::flash('success', 'Currency "' . $currency->name . '" created');
return Redirect::route('currency.create')->withInput();
}
return Redirect::route('currency.index');
// redirect to previous URL.
return Redirect::to(Session::get('currency.create.url'));
}
/**
* @param TransactionCurrency $currency
* @param CurrencyFormRequest $request
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(TransactionCurrency $currency, CurrencyFormRequest $request)
public function update(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
$data = $request->getCurrencyData();
if (Auth::user()->hasRole('owner')) {
$currency = $repository->update($currency, $data);
}
Session::flash('success', 'Currency "' . e($currency->name) . '" updated.');
Preferences::mark();
$currency->code = $request->get('code');
$currency->symbol = $request->get('symbol');
$currency->name = $request->get('name');
$currency->save();
Session::flash('success', 'Currency "' . e($currency->namename) . '" updated.');
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('currency.edit.fromUpdate', true);
return Redirect::route('currency.index');
return Redirect::route('currency.edit', [$currency->id]);
}
// redirect to previous URL.
return Redirect::to(Session::get('currency.edit.url'));
}

View File

@@ -1,635 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use App;
use Auth;
use Carbon\Carbon;
use Crypt;
use Exception;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Http\Requests;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Query\JoinClause;
use Navigation;
use Preferences;
use Response;
use Session;
use DB;
use Steam;
/**
* Class GoogleChartController
*
* @package FireflyIII\Http\Controllers
*/
class GoogleChartController extends Controller
{
/**
* @param Account $account
* @param string $view
*
* @return \Illuminate\Http\JsonResponse
*/
public function accountBalanceChart(Account $account, $view = 'session', GChart $chart)
{
$chart->addColumn('Day of month', 'date');
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$count = $account->transactions()->count();
if ($view == 'all' && $count > 0) {
$first = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy(
'date', 'ASC'
)->first(['transaction_journals.date']);
$last = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy(
'date', 'DESC'
)->first(['transaction_journals.date']);
$start = new Carbon($first->date);
$end = new Carbon($last->date);
}
$current = clone $start;
while ($end >= $current) {
$chart->addRow(clone $current, Steam::balance($account, $current), false);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allAccountsBalanceChart(GChart $chart)
{
$chart->addColumn('Day of the month', 'date');
$frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
if ($frontPage->data == []) {
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
} else {
$accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->get(['accounts.*']);
}
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param int $year
*
* @return $this|\Illuminate\Http\JsonResponse
*/
public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository)
{
try {
new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid year.');
}
$budgets = Auth::user()->budgets()->get();
$budgets->sortBy('name');
$chart->addColumn('Month', 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
$start = Carbon::createFromDate(intval($year), 1, 1);
$end = clone $start;
$end->endOfYear();
while ($start <= $end) {
$row = [clone $start];
foreach ($budgets as $budget) {
$spent = $repository->spentInMonth($budget, $start);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsHomeChart(GChart $chart)
{
$chart->addColumn('Budget', 'string');
$chart->addColumn('Budgeted', 'number');
$chart->addColumn('Spent', 'number');
$budgets = Auth::user()->budgets()->orderBy('name', 'DESC')->get();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
/** @var Budget $budget */
foreach ($budgets as $budget) {
/** @var \LimitRepetition $repetition */
$repetition = LimitRepetition::
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00'))
->where('budget_limits.budget_id', $budget->id)
->first(['limit_repetitions.*']);
if (is_null($repetition)) { // use the session start and end for our search query
$searchStart = $start;
$searchEnd = $end;
$limit = 0; // the limit is zero:
} else {
// use the limit's start and end for our search query
$searchStart = $repetition->startdate;
$searchEnd = $repetition->enddate;
$limit = floatval($repetition->amount); // the limit is the repetitions limit:
}
$expenses = floatval($budget->transactionjournals()->before($searchEnd)->after($searchStart)->lessThan(0)->sum('amount')) * -1;
if ($expenses > 0) {
$chart->addRow($budget->name, $limit, $expenses);
}
}
$noBudgetSet = Auth::user()
->transactionjournals()
->whereNotIn(
'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) {
$query
->select('transaction_journals.id')
->from('transaction_journals')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00'));
}
)
->before($end)
->after($start)
->lessThan(0)
->transactionTypes(['Withdrawal'])
->get();
$sum = $noBudgetSet->sum('amount') * -1;
$chart->addRow('No budget', 0, $sum);
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allCategoriesHomeChart(GChart $chart)
{
$chart->addColumn('Category', 'string');
$chart->addColumn('Spent', 'number');
// query!
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$set = TransactionJournal::leftJoin(
'transactions',
function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
}
)
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->after($start)
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('sum', 'DESC')
->get(['categories.id', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
foreach ($set as $entry) {
$entry->name = strlen($entry->name) == 0 ? '(no category)' : $entry->name;
$chart->addRow($entry->name, floatval($entry->sum));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param Bill $bill
*
* @return \Illuminate\Http\JsonResponse
*/
public function billOverview(Bill $bill, GChart $chart)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Max amount', 'number');
$chart->addColumn('Min amount', 'number');
$chart->addColumn('Current entry', 'number');
// get first transaction or today for start:
$first = $bill->transactionjournals()->orderBy('date', 'ASC')->first();
if ($first) {
$start = $first->date;
} else {
$start = new Carbon;
}
$end = new Carbon;
while ($start <= $end) {
$result = $bill->transactionjournals()->before($end)->after($start)->first();
if ($result) {
/** @var Transaction $tr */
foreach ($result->transactions()->get() as $tr) {
if (floatval($tr->amount) > 0) {
$amount = floatval($tr->amount);
}
}
} else {
$amount = 0;
}
unset($result);
$chart->addRow(clone $start, $bill->amount_max, $bill->amount_min, $amount);
$start = Navigation::addPeriod($start, $bill->repeat_freq, 0);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billsOverview(GChart $chart)
{
$paid = ['items' => [], 'amount' => 0];
$unpaid = ['items' => [], 'amount' => 0];
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$chart->addColumn('Name', 'string');
$chart->addColumn('Amount', 'number');
$set = Bill::
leftJoin(
'transaction_journals', function (JoinClause $join) use ($start, $end) {
$join->on('bills.id', '=', 'transaction_journals.bill_id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'));
}
)
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '>', 0);
}
)
->where('active', 1)
->groupBy('bills.id')
->get(
['bills.id', 'bills.name', 'transaction_journals.description',
'transaction_journals.encrypted',
'transaction_journals.id as journalId',
\DB::Raw('SUM(`bills`.`amount_min` + `bills`.`amount_max`) / 2 as `averageAmount`'),
'transactions.amount AS actualAmount']
);
foreach ($set as $entry) {
if (intval($entry->journalId) == 0) {
$unpaid['items'][] = $entry->name;
$unpaid['amount'] += floatval($entry->averageAmount);
} else {
$description = intval($entry->encrypted) == 1 ? Crypt::decrypt($entry->description) : $entry->description;
$paid['items'][] = $description;
$paid['amount'] += floatval($entry->actualAmount);
}
}
$chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']);
$chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']);
$chart->generate();
return Response::json($chart->getData());
}
/**
*
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Illuminate\Http\JsonResponse
*/
public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
$chart->addColumn('Day', 'date');
$chart->addColumn('Left', 'number');
$amount = $repetition->amount;
while ($start <= $end) {
/*
* Sum of expenses on this day:
*/
$sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount'));
$amount += $sum;
$chart->addRow(clone $start, $amount);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
*
* @param Budget $budget
*
* @param int $year
*
* @return \Illuminate\Http\JsonResponse
*/
public function budgetsAndSpending(Budget $budget, $year = 0)
{
$chart = App::make('Grumpydictator\Gchart\GChart');
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepository');
$chart->addColumn('Month', 'date');
$chart->addColumn('Budgeted', 'number');
$chart->addColumn('Spent', 'number');
if ($year == 0) {
// grab the first budgetlimit ever:
$firstLimit = $budget->budgetlimits()->orderBy('startdate', 'ASC')->first();
if ($firstLimit) {
$start = new Carbon($firstLimit->startdate);
} else {
$start = Carbon::now()->startOfYear();
}
// grab the last budget limit ever:
$lastLimit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first();
if ($lastLimit) {
$end = new Carbon($lastLimit->startdate);
} else {
$end = Carbon::now()->endOfYear();
}
} else {
$start = Carbon::createFromDate(intval($year), 1, 1);
$end = clone $start;
$end->endOfYear();
}
while ($start <= $end) {
$spent = $repository->spentInMonth($budget, $start);
$repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00'))
->where('budget_limits.budget_id', $budget->id)
->first(['limit_repetitions.*']);
if ($repetition) {
$budgeted = floatval($repetition->amount);
\Log::debug('Found a repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name . '!');
} else {
\Log::debug('No repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name);
$budgeted = null;
}
$chart->addRow(clone $start, $budgeted, $spent);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
*
* @param Category $category
* @param $year
*
* @return \Illuminate\Http\JsonResponse
*/
public function categoriesAndSpending(Category $category, $year, GChart $chart)
{
try {
new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid year.');
}
$chart->addColumn('Month', 'date');
$chart->addColumn('Budgeted', 'number');
$chart->addColumn('Spent', 'number');
$start = new Carbon('01-01-' . $year);
$end = clone $start;
$end->endOfYear();
while ($start <= $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
$spent = floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
$budgeted = null;
$chart->addRow(clone $start, $budgeted, $spent);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\JsonResponse
*/
public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Balance', 'number');
$set = \DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
foreach ($set as $entry) {
$chart->addRow(new Carbon($entry->date), floatval($entry->sum));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
*
* @param $year
*
* @return \Illuminate\Http\JsonResponse
*/
public function yearInExp($year, GChart $chart, ReportQueryInterface $query)
{
try {
$start = new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid year.');
}
$chart->addColumn('Month', 'date');
$chart->addColumn('Income', 'number');
$chart->addColumn('Expenses', 'number');
// get report query interface.
$end = clone $start;
$end->endOfYear();
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income:
$income = $query->incomeByPeriod($start, $currentEnd);
$incomeSum = 0;
foreach ($income as $entry) {
$incomeSum += floatval($entry->amount);
}
// total expenses:
$expense = $query->journalsByExpenseAccount($start, $currentEnd);
$expenseSum = 0;
foreach ($expense as $entry) {
$expenseSum += floatval($entry->amount);
}
$chart->addRow(clone $start, $incomeSum, $expenseSum);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
*
* @param $year
*
* @return \Illuminate\Http\JsonResponse
*/
public function yearInExpSum($year, GChart $chart, ReportQueryInterface $query)
{
try {
$start = new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid year.');
}
$chart->addColumn('Summary', 'string');
$chart->addColumn('Income', 'number');
$chart->addColumn('Expenses', 'number');
$income = 0;
$expense = 0;
$count = 0;
$end = clone $start;
$end->endOfYear();
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income:
$incomeResult = $query->incomeByPeriod($start, $currentEnd);
$incomeSum = 0;
foreach ($incomeResult as $entry) {
$incomeSum += floatval($entry->amount);
}
// total expenses:
$expenseResult = $query->journalsByExpenseAccount($start, $currentEnd);
$expenseSum = 0;
foreach ($expenseResult as $entry) {
$expenseSum += floatval($entry->amount);
}
$income += $incomeSum;
$expense += $expenseSum;
$count++;
$start->addMonth();
}
$chart->addRow('Sum', $income, $expense);
$count = $count > 0 ? $count : 1;
$chart->addRow('Average', ($income / $count), ($expense / $count));
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -1,94 +1,51 @@
<?php namespace FireflyIII\Http\Controllers;
use ErrorException;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Http\Request;
use League\CommonMark\CommonMarkConverter;
use Route;
use FireflyIII\Helpers\Help\HelpInterface;
use Log;
use Response;
use Cache;
/**
* Class HelpController
*
* @package FireflyIII\Http\Controllers
*/
class HelpController extends Controller {
class HelpController extends Controller
{
/**
* @param $route
* @param HelpInterface $help
* @param $route
*
* @return \Illuminate\Http\JsonResponse
*/
public function show($route)
public function show(HelpInterface $help, $route)
{
$content = [
'text' => '<p>There is no help for this route!</p>',
'title' => 'Help',
];
if (!Route::has($route)) {
\Log::error('No such route: ' . $route);
if (!$help->hasRoute($route)) {
Log::error('No such route: ' . $route);
return Response::json($content);
}
if ($this->_inCache($route)) {
if ($help->inCache($route)) {
$content = [
'text' => Cache::get('help.' . $route . '.text'),
'title' => Cache::get('help.' . $route . '.title'),
'text' => $help->getFromCache('help.' . $route . '.text'),
'title' => $help->getFromCache('help.' . $route . '.title'),
];
return Response::json($content);
}
$content = $this->_getFromGithub($route);
$content = $help->getFromGithub($route);
Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week.
Cache::put('help.' . $route . '.title', $content['title'], 10080);
$help->putInCache($route, $content);
return Response::json($content);
}
/**
* @param $route
*
* @return bool
*/
protected function _inCache($route)
{
return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text');
}
/**
* @param $route
*
* @return array
*/
protected function _getFromGithub($route)
{
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
$content = [
'text' => '<p>There is no help for this route!</p>',
'title' => $route,
];
try {
$content['text'] = file_get_contents($uri);
} catch (ErrorException $e) {
\Log::error(trim($e->getMessage()));
}
if (strlen(trim($content['text'])) == 0) {
$content['text'] = '<p>There is no help for this route.</p>';
}
$converter = new CommonMarkConverter();
$content['text'] = $converter->convertToHtml($content['text']);
return $content;
}
}

View File

@@ -1,13 +1,16 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Cache;
use Carbon\Carbon;
use Navigation;
use Config;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Route;
use Session;
use URL;
use Steam;
/**
* Class HomeController
@@ -17,11 +20,19 @@ use URL;
class HomeController extends Controller
{
/**
*
*/
public function __construct()
public function dateRange()
{
$start = new Carbon(Input::get('start'));
$end = new Carbon(Input::get('end'));
$diff = $start->diffInDays($end);
if ($diff > 50) {
Session::flash('warning', $diff . ' days of data may take a while to load.');
}
Session::put('start', $start);
Session::put('end', $end);
}
/**
@@ -29,96 +40,106 @@ class HomeController extends Controller
*/
public function flush()
{
Cache::flush();
// get all tags.
// update all counts:
$tags = Tag::get();
/** @var Tag $tag */
foreach ($tags as $tag) {
foreach ($tag->transactionjournals()->get() as $journal) {
$count = $journal->tags()->count();
$journal->tag_count = $count;
$journal->save();
}
}
Session::clear();
return Redirect::route('index');
}
/**
* @return \Illuminate\View\View
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function index()
public function index(AccountRepositoryInterface $repository)
{
$count = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->count();
$types = Config::get('firefly.accountTypesByIdentifier.asset');
$count = $repository->countAccounts($types);
if ($count == 0) {
return Redirect::route('new-user.index');
}
$title = 'Firefly';
$subTitle = 'What\'s playing?';
$subTitle = trans('firefly.welcomeBack');
$mainTitleIcon = 'fa-fire';
$transactions = [];
$frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
if ($frontPage->data == []) {
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
} else {
$accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->get(['accounts.*']);
$accounts = $repository->getFrontpageAccounts($frontPage);
$savings = $repository->getSavingsAccounts();
$piggyBankAccounts = $repository->getPiggyBankAccounts();
$savingsTotal = 0;
foreach ($savings as $savingAccount) {
$savingsTotal += Steam::balance($savingAccount, $end);
}
$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.'
);
}
foreach ($accounts as $account) {
$set = Auth::user()
->transactionjournals()
->with(['transactions', 'transactioncurrency', 'transactiontype'])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
->where('date', '>=', $start->format('Y-m-d'))
->where('date', '<=', $end->format('Y-m-d'))
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->take(10)
->get(['transaction_journals.*']);
$set = $repository->getFrontpageTransactions($account, $start, $end);
if (count($set) > 0) {
$transactions[] = [$set, $account];
}
}
// var_dump($transactions);
return view('index', compact('count', 'title', 'subTitle', 'mainTitleIcon', 'transactions'));
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal', 'piggyBankAccounts'));
}
/**
* @param string $range
*
* @return mixed
* @codeCoverageIgnore
* @return \Illuminate\Http\RedirectResponse|string
*/
public function rangeJump($range)
public function routes()
{
if (!Auth::user()->hasRole('owner')) {
Session::flash('warning', 'This page is broken.');
$valid = ['1D', '1W', '1M', '3M', '6M', '1Y',];
if (in_array($range, $valid)) {
Preferences::set('viewRange', $range);
Session::forget('range');
return Redirect::route('index');
}
return Redirect::to(URL::previous());
// get all routes:
$routeCollection = Route::getRoutes();
/** @var \Illuminate\Routing\Route $value */
foreach ($routeCollection as $value) {
$name = $value->getName();
$methods = $value->getMethods();
$isPost = in_array('POST', $methods);
$index = str_replace('.', '-', $name);
if (strlen($name) > 0 && !$isPost) {
echo "'" . $index . "' => '" . $name . "',<br />";
}
}
return '&nbsp;';
}
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function sessionNext()
{
$range = Session::get('range');
$start = Session::get('start');
Session::put('start', Navigation::jumpToNext($range, clone $start));
return Redirect::to(URL::previous());
}
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function sessionPrev()
{
$range = Session::get('range');
$start = Session::get('start');
Session::put('start', Navigation::jumpToPrevious($range, clone $start));
return Redirect::to(URL::previous());
}
}

View File

@@ -1,49 +1,268 @@
<?php namespace FireflyIII\Http\Controllers;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Amount;
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
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 FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Response;
use Auth;
use Session;
use Steam;
/**
* Class JsonController
*
* @package FireflyIII\Http\Controllers
*/
class JsonController extends Controller {
class JsonController extends Controller
{
/**
* @param BillRepositoryInterface $repository
*
* @param AccountRepositoryInterface $accountRepository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-bills-paid');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$amount = 0;
// these two functions are the same as the chart
$bills = $repository->getActiveBills();
/** @var Bill $bill */
foreach ($bills as $bill) {
$amount += $repository->billPaymentsInRange($bill, $start, $end);
}
unset($bill, $bills);
/**
* Find credit card accounts and possibly unpaid credit card bills.
*/
$creditCards = $accountRepository->getCreditCards();
// if the balance is not zero, the monthly payment is still underway.
/** @var Account $creditCard */
foreach ($creditCards as $creditCard) {
$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.
$amount += $accountRepository->getTransfersInRange($creditCard, $start, $end)->sum('amount');
}
}
$data = ['box' => 'bills-paid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accountRepository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxBillsUnpaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
{
$amount = 0;
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-bills-unpaid');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$bills = $repository->getActiveBills();
$unpaid = new Collection; // bills
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
if ($journals->count() == 0) {
$unpaid->push([$bill, $range['start']]);
}
}
}
unset($bill, $bills, $range, $ranges);
$creditCards = $accountRepository->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;
$fakeAmount = $balance * -1;
$fakeBill = $repository->createFakeBill($description, $date, $fakeAmount);
$unpaid->push([$fakeBill, $date]);
}
}
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$amount += $current;
}
$data = ['box' => 'bills-unpaid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* @param ReportQueryInterface $reportQuery
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxIn(ReportQueryInterface $reportQuery)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-in');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$amount = $reportQuery->incomeInPeriodCorrected($start, $end, true)->sum('amount');
$data = ['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* @param ReportQueryInterface $reportQuery
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxOut(ReportQueryInterface $reportQuery)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-out');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount');
$data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* Returns a list of categories.
*
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function categories()
public function categories(CategoryRepositoryInterface $repository)
{
$list = Auth::user()->categories()->orderBy('name','ASC')->get();
$return = [];
$list = $repository->getCategories();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
}
sort($return);
return Response::json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param AccountRepositoryInterface $accountRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function expenseAccounts(AccountRepositoryInterface $accountRepository)
{
$list = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']);
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
}
return Response::json($return);
}
/**
* @param AccountRepositoryInterface $accountRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function revenueAccounts(AccountRepositoryInterface $accountRepository)
{
$list = $accountRepository->getAccounts(['Revenue account']);
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
}
return Response::json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param TagRepositoryInterface $tagRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function expenseAccounts()
public function tags(TagRepositoryInterface $tagRepository)
{
$list = Auth::user()->accounts()->accountTypeIn(['Expense account', 'Beneficiary account'])->get();
$return = [];
$list = $tagRepository->get();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
$return[] = $entry->tag;
}
return Response::json($return);
@@ -51,17 +270,26 @@ class JsonController extends Controller {
}
/**
* @return \Illuminate\Http\JsonResponse
* @param JournalRepositoryInterface $repository
* @param $what
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function revenueAccounts()
public function transactionJournals(JournalRepositoryInterface $repository, $what)
{
$list = Auth::user()->accounts()->accountTypeIn(['Revenue account'])->get();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
$descriptions = [];
$dbType = $repository->getTransactionType($what);
$journals = $repository->getJournalsOfType($dbType);
foreach ($journals as $j) {
$descriptions[] = $j->description;
}
return Response::json($return);
$descriptions = array_unique($descriptions);
sort($descriptions);
return Response::json($descriptions);
}

View File

@@ -0,0 +1,111 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Http\Requests\NewUserFormRequest;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Preferences;
use Redirect;
use Session;
use View;
/**
* Class NewUserController
*
* @package FireflyIII\Http\Controllers
*/
class NewUserController extends Controller
{
/**
* @param AccountRepositoryInterface $repository
*
* @@return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function index(AccountRepositoryInterface $repository)
{
View::share('title', 'Welcome to Firefly!');
View::share('mainTitleIcon', 'fa-fire');
$types = Config::get('firefly.accountTypesByIdentifier.asset');
$count = $repository->countAccounts($types);
if ($count > 0) {
return Redirect::route('index');
}
return view('new-user.index');
}
/**
* @param NewUserFormRequest $request
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function submit(NewUserFormRequest $request, AccountRepositoryInterface $repository)
{
// create normal asset account:
$assetAccount = [
'name' => $request->get('bank_name'),
'accountType' => 'asset',
'virtualBalance' => 0,
'active' => true,
'user' => Auth::user()->id,
'accountRole' => 'defaultAsset',
'openingBalance' => floatval($request->input('bank_balance')),
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
];
$repository->store($assetAccount);
// create savings account
if (strlen($request->get('savings_balance') > 0)) {
$savingsAccount = [
'name' => $request->get('bank_name') . ' savings account',
'accountType' => 'asset',
'virtualBalance' => 0,
'active' => true,
'user' => Auth::user()->id,
'accountRole' => 'savingAsset',
'openingBalance' => floatval($request->input('savings_balance')),
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
];
$repository->store($savingsAccount);
}
// create credit card.
if (strlen($request->get('credit_card_limit') > 0)) {
$creditAccount = [
'name' => 'Credit card',
'accountType' => 'asset',
'virtualBalance' => floatval($request->get('credit_card_limit')),
'active' => true,
'user' => Auth::user()->id,
'accountRole' => 'ccAsset',
'openingBalance' => null,
'openingBalanceDate' => null,
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
];
$creditCard = $repository->store($creditAccount);
// store meta for CC:
AccountMeta::create(['name' => 'ccType', 'data' => 'monthlyFull', 'account_id' => $creditCard->id,]);
AccountMeta::create(['name' => 'ccMonthlyPaymentDate', 'data' => Carbon::now()->year . '-01-01', 'account_id' => $creditCard->id,]);
}
Session::flash('success', 'New account(s) created!');
Preferences::mark();
return Redirect::route('index');
}
}

View File

@@ -1,24 +1,26 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth;
use Carbon\Carbon;
use Config;
use ExpandedForm;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Illuminate\Support\Collection;
use Input;
use Preferences;
use Redirect;
use Session;
use Steam;
use URL;
use View;
/**
*
* @SuppressWarnings(PHPMD.TooManyMethods)
*
* Class PiggyBankController
*
* @package FireflyIII\Http\Controllers
@@ -27,45 +29,55 @@ class PiggyBankController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Piggy banks');
parent::__construct();
View::share('title', trans('firefly.piggyBanks'));
View::share('mainTitleIcon', 'fa-sort-amount-asc');
}
/**
* Add money to piggy bank
*
* @param PiggyBank $piggyBank
* @param AccountRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return $this
*/
public function add(PiggyBank $piggyBank, AccountRepositoryInterface $repository)
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);
\Log::debug('Now going to view for piggy bank #' . $piggyBank->id . ' (' . $piggyBank->name . ')');
return view('piggy-banks.add', compact('piggyBank', 'maxAmount'));
}
/**
* @param AccountRepositoryInterface $repository
*
* @return mixed
*/
public function create()
public function create(AccountRepositoryInterface $repository)
{
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
$subTitle = 'Create new piggy bank';
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$subTitle = trans('firefly.create_new_piggybank');
$subTitleIcon = 'fa-plus';
// put previous url in session if not redirect from store (not "create another").
if (Session::get('piggy-banks.create.fromStore') !== true) {
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'));
}
@@ -76,38 +88,45 @@ class PiggyBankController extends Controller
*/
public function delete(PiggyBank $piggyBank)
{
$subTitle = 'Delete "' . e($piggyBank->name) . '"';
$subTitle = trans('firefly.delete_piggy_bank', ['name' => $piggyBank->name]);
return view('piggy_banks.delete', compact('piggyBank', 'subTitle'));
// 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'));
}
/**
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(PiggyBank $piggyBank)
public function destroy(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
$this->_repository->destroy($piggyBank);
return Redirect::route('piggy_banks.index');
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
Preferences::mark();
$repository->destroy($piggyBank);
return Redirect::to(Session::get('piggy-banks.delete.url'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* @param AccountRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @param PiggyBank $piggyBank
*
* @return $this
* @return View
*/
public function edit(PiggyBank $piggyBank)
public function edit(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"';
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$subTitle = trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
$subTitleIcon = 'fa-pencil';
/*
@@ -123,28 +142,37 @@ class PiggyBankController extends Controller
'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) {
Session::put('piggy-banks.edit.url', URL::previous());
}
Session::forget('piggy-banks.edit.fromUpdate');
return view('piggy-banks.edit', compact('subTitle', 'subTitleIcon', 'piggyBank', 'accounts', 'periods', 'preFilled'));
}
/**
* @return $this
* @param AccountRepositoryInterface $repository
* @param PiggyBankRepositoryInterface $piggyRepository
*
* @return View
*/
public function index(AccountRepositoryInterface $repository)
public function index(AccountRepositoryInterface $repository, PiggyBankRepositoryInterface $piggyRepository)
{
/** @var Collection $piggyBanks */
$piggyBanks = Auth::user()->piggyBanks()->where('repeats', 0)->get();
$piggyBanks = $piggyRepository->getPiggyBanks();
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = [];
/** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) {
$piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount);
$piggyBank->percentage = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100);
$piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
$piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar;
/*
@@ -154,8 +182,8 @@ class PiggyBankController extends Controller
if (!isset($accounts[$account->id])) {
$accounts[$account->id] = [
'name' => $account->name,
'balance' => Steam::balance($account),
'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
@@ -170,18 +198,36 @@ class PiggyBankController extends Controller
return view('piggy-banks.index', compact('piggyBanks', 'accounts'));
}
/**
* @param PiggyBankRepositoryInterface $repository
*/
public function order(PiggyBankRepositoryInterface $repository)
{
$data = Input::get('order');
// set all users piggy banks to zero:
$repository->reset();
if (is_array($data)) {
foreach ($data as $order => $id) {
$repository->setOrder(intval($id), (intval($order) + 1));
}
}
}
/**
* POST add money to piggy bank
*
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postAdd(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts)
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);
@@ -191,12 +237,11 @@ class PiggyBankController extends Controller
$repetition->currentamount += $amount;
$repetition->save();
/*
* Create event!
*/
//Event::fire('piggy_bank.addMoney', [$piggyBank, $amount]); // new and used.
// create event
$repository->createEvent($piggyBank, $amount);
Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
Preferences::mark();
} else {
Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
}
@@ -205,11 +250,12 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postRemove(PiggyBank $piggyBank)
public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$amount = floatval(Input::get('amount'));
@@ -220,12 +266,11 @@ class PiggyBankController extends Controller
$repetition->currentamount -= $amount;
$repetition->save();
/*
* Create event!
*/
//Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used.
// create event
$repository->createEvent($piggyBank, $amount * -1);
Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
Preferences::mark();
} else {
Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
}
@@ -236,7 +281,6 @@ class PiggyBankController extends Controller
/**
* @param PiggyBank $piggyBank
*
* @SuppressWarnings("Unused")
*
* @return \Illuminate\View\View
*/
@@ -246,19 +290,14 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return $this
* @return View
*/
public function show(PiggyBank $piggyBank)
public function show(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
/*
* Number of reminders:
*/
$events = $repository->getEvents($piggyBank);
$subTitle = e($piggyBank->name);
return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle'));
@@ -266,54 +305,76 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBankFormRequest $request
* @param PiggyBankRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
{
$piggyBankData = [
'repeats' => false,
'name' => $request->get('name'),
'startdate' => new Carbon,
'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')),
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
'reminder' => $request->get('reminder'),
'name' => $request->get('name'),
'startdate' => new Carbon,
'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')),
'remind_me' => false,
'reminder_skip' => 0,
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
];
$piggyBank = $repository->store($piggyBankData);
Session::flash('success', 'Stored piggy bank "' . e($piggyBank->name) . '".');
Preferences::mark();
return Redirect::route('piggy-banks.index');
if (intval(Input::get('create_another')) === 1) {
Session::put('piggy-banks.create.fromStore', true);
return Redirect::route('piggy-banks.create')->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('piggy-banks.create.url'));
}
/**
* @param PiggyBank $piggyBank
*
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBankFormRequest $request
* @param PiggyBank $piggyBank
*
* @return $this
*/
public function update(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request)
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
{
$piggyBankData = [
'repeats' => false,
'name' => $request->get('name'),
'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')),
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
'reminder' => $request->get('reminder'),
'name' => $request->get('name'),
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')),
'remind_me' => false,
'reminder_skip' => 0,
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
];
$piggyBank = $repository->update($piggyBank, $piggyBankData);
Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".');
Preferences::mark();
return Redirect::route('piggy-banks.index');
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('piggy-banks.edit.fromUpdate', true);
return Redirect::route('piggy-banks.edit', [$piggyBank->id]);
}
// redirect to previous URL.
return Redirect::to(Session::get('piggy-banks.edit.url'));
}
}

View File

@@ -1,47 +1,47 @@
<?php namespace FireflyIII\Http\Controllers;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Http\Request;
use View;
use Auth;
use Preferences;
use Config;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Session;
use Preferences;
use Redirect;
use Session;
use View;
/**
* Class PreferencesController
*
* @package FireflyIII\Http\Controllers
*/
class PreferencesController extends Controller {
class PreferencesController extends Controller
{
/**
*
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Preferences');
parent::__construct();
View::share('title', trans('firefly.preferences'));
View::share('mainTitleIcon', 'fa-gear');
}
/**
* @param AccountRepositoryInterface $repository
*
* @return $this|\Illuminate\View\View
*/
public function index()
public function index(AccountRepositoryInterface $repository)
{
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
$viewRange = Preferences::get('viewRange', '1M');
$viewRangeValue = $viewRange->data;
$frontPage = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
$viewRangePref = Preferences::get('viewRange', '1M');
$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'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with(
'viewRange', $viewRangeValue
);
return view('preferences.index', compact('budgetMaximum', 'language', 'accounts', 'frontPageAccounts', 'viewRange'));
}
/**
@@ -51,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'));
@@ -67,8 +69,15 @@ 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!');
Preferences::mark();
return Redirect::route('preferences');
}

View File

@@ -2,6 +2,7 @@
use Auth;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
use FireflyIII\Http\Requests\ProfileFormRequest;
use Hash;
use Redirect;
@@ -25,6 +26,16 @@ class ProfileController extends Controller
);
}
/**
* @return \Illuminate\View\View
*/
public function deleteAccount()
{
return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', 'Delete account')->with(
'mainTitleIcon', 'fa-user'
);
}
/**
* @return \Illuminate\View\View
*
@@ -35,6 +46,8 @@ class ProfileController extends Controller
}
/**
* @param ProfileFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function postChangePassword(ProfileFormRequest $request)
@@ -43,13 +56,13 @@ class ProfileController extends Controller
if (!Hash::check($request->get('current_password'), Auth::user()->password)) {
Session::flash('error', 'Invalid current password!');
return Redirect::route('change-password');
return Redirect::route('profile.change-password');
}
$result = $this->_validatePassword($request->get('current_password'), $request->get('new_password'), $request->get('new_password_confirmation'));
$result = $this->validatePassword($request->get('current_password'), $request->get('new_password'));
if (!($result === true)) {
Session::flash('error', $result);
return Redirect::route('change-password');
return Redirect::route('profile.change-password');
}
// update the user with the new password.
@@ -62,29 +75,45 @@ class ProfileController extends Controller
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param string $old
* @param string $new1
* @param string $new2
*
* @return string|bool
*/
protected function _validatePassword($old, $new1, $new2)
protected function validatePassword($old, $new1)
{
if (strlen($new1) == 0 || strlen($new2) == 0) {
return 'Do fill in a password!';
}
if ($new1 == $old) {
return 'The idea is to change your password.';
}
if ($new1 !== $new2) {
return 'New passwords do not match!';
}
return true;
}
/**
* @param DeleteAccountFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/
public function postDeleteAccount(DeleteAccountFormRequest $request)
{
// old, new1, new2
if (!Hash::check($request->get('password'), Auth::user()->password)) {
Session::flash('error', 'Invalid password!');
return Redirect::route('profile.delete-account');
}
// DELETE!
Auth::user()->delete();
Session::flush();
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'delete-account');
return Redirect::route('index');
}
}

View File

@@ -1,156 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth;
use FireflyIII\Http\Requests;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection;
use Response;
use Input;
/**
* Class RelatedController
*
* @package FireflyIII\Http\Controllers
*/
class RelatedController extends Controller
{
/**
*
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\JsonResponse
*/
public function alreadyRelated(TransactionJournal $journal)
{
$ids = [];
/** @var TransactionGroup $group */
foreach ($journal->transactiongroups()->get() as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$ids[] = $loopJournal->id;
}
}
}
$unique = array_unique($ids);
if (count($unique) > 0) {
$set = Auth::user()->transactionjournals()->whereIn('id', $unique)->get();
$set->each(
function (TransactionJournal $journal) {
/** @var Transaction $t */
foreach ($journal->transactions()->get() as $t) {
if ($t->amount > 0) {
$journal->amount = $t->amount;
}
}
}
);
return Response::json($set->toArray());
} else {
return Response::json((new Collection)->toArray());
}
}
/**
* @param TransactionJournal $parentJournal
* @param TransactionJournal $childJournal
*
* @return \Illuminate\Http\JsonResponse
*/
public function relate(TransactionJournal $parentJournal, TransactionJournal $childJournal)
{
$group = new TransactionGroup;
$group->relation = 'balance';
$group->user_id = Auth::user()->id;
$group->save();
$group->transactionjournals()->save($parentJournal);
$group->transactionjournals()->save($childJournal);
return Response::json(true);
}
/**
* @param TransactionJournal $journal
*
* @return \Illuminate\View\View
*/
public function related(TransactionJournal $journal)
{
$groups = $journal->transactiongroups()->get();
$members = new Collection;
/** @var TransactionGroup $group */
foreach ($groups as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$members->push($loopJournal);
}
}
}
return view('related.relate', compact('journal', 'members'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param TransactionJournal $parentJournal
* @param TransactionJournal $childJournal
*
* @return \Illuminate\Http\JsonResponse
* @throws Exception
*/
public function removeRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal)
{
$groups = $parentJournal->transactiongroups()->get();
/** @var TransactionGroup $group */
foreach ($groups as $group) {
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id == $childJournal->id) {
// remove from group:
$group->transactionjournals()->detach($childJournal);
}
}
if ($group->transactionjournals()->count() == 1) {
$group->delete();
}
}
return Response::json(true);
}
/**
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\JsonResponse
*/
public function search(TransactionJournal $journal, JournalRepositoryInterface $repository)
{
$search = e(trim(Input::get('searchValue')));
$result = $repository->searchRelated($search, $journal);
$result->each(
function (TransactionJournal $journal) {
/** @var Transaction $t */
foreach ($journal->transactions()->get() as $t) {
if ($t->amount > 0) {
$journal->amount = $t->amount;
}
}
}
);
return Response::json($result->toArray());
}
}

View File

@@ -1,199 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use Config;
use ExpandedForm;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Redirect;
use Session;
use View;
/**
* Class RepeatedExpenseController
*
* @package FireflyIII\Http\Controllers
*/
class RepeatedExpenseController extends Controller
{
/**
*
*/
public function __construct()
{
View::share('title', 'Repeated expenses');
View::share('mainTitleIcon', 'fa-rotate-left');
}
/**
* @return $this
*/
public function create()
{
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
return view('repeatedExpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with(
'subTitleIcon', 'fa-plus'
);
}
/**
* @param PiggyBank $repeatedExpense
*
* @return $this
*/
public function delete(PiggyBank $repeatedExpense)
{
$subTitle = 'Delete "' . e($repeatedExpense->name) . '"';
return view('repeatedExpense.delete', compact('repeatedExpense', 'subTitle'));
}
/**
* @param PiggyBank $repeatedExpense
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(PiggyBank $repeatedExpense)
{
Session::flash('success', 'Repeated expense "' . e($repeatedExpense->name) . '" deleted.');
$repeatedExpense->delete();
return Redirect::route('repeated.index');
}
/**
* @param PiggyBank $repeatedExpense
*
* @return $this
*/
public function edit(PiggyBank $repeatedExpense)
{
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
$subTitle = 'Edit repeated expense "' . e($repeatedExpense->name) . '"';
$subTitleIcon = 'fa-pencil';
/*
* Flash some data to fill the form.
*/
$preFilled = ['name' => $repeatedExpense->name,
'account_id' => $repeatedExpense->account_id,
'targetamount' => $repeatedExpense->targetamount,
'reminder_skip' => $repeatedExpense->reminder_skip,
'rep_every' => $repeatedExpense->rep_every,
'rep_times' => $repeatedExpense->rep_times,
'targetdate' => $repeatedExpense->targetdate->format('Y-m-d'),
'reminder' => $repeatedExpense->reminder,
'remind_me' => intval($repeatedExpense->remind_me) == 1 || !is_null($repeatedExpense->reminder) ? true : false
];
Session::flash('preFilled', $preFilled);
return view('repeatedExpense.edit', compact('subTitle', 'subTitleIcon', 'repeatedExpense', 'accounts', 'periods', 'preFilled'));
}
/**
* @return \Illuminate\View\View
*/
public function index()
{
$subTitle = 'Overview';
$expenses = Auth::user()->piggyBanks()->where('repeats', 1)->get();
$expenses->each(
function (PiggyBank $piggyBank) {
$piggyBank->currentRelevantRep();
}
);
return view('repeatedExpense.index', compact('expenses', 'subTitle'));
}
/**
* @param PiggyBank $repeatedExpense
*
* @return \Illuminate\View\View
*/
public function show(PiggyBank $repeatedExpense, PiggyBankRepositoryInterface $repository)
{
$subTitle = $repeatedExpense->name;
$today = Carbon::now();
$repetitions = $repeatedExpense->piggyBankRepetitions()->get();
$repetitions->each(
function (PiggyBankRepetition $repetition) use ($repository) {
$repetition->bars = $repository->calculateParts($repetition);
}
);
return view('repeatedExpense.show', compact('repetitions', 'repeatedExpense', 'today', 'subTitle'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*/
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
{
$piggyBankData = [
'repeats' => true,
'name' => $request->get('name'),
'startdate' => new Carbon,
'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')),
'targetdate' => new Carbon($request->get('targetdate')),
'reminder' => $request->get('reminder'),
'skip' => intval($request->get('skip')),
'rep_every' => intval($request->get('rep_every')),
'rep_times' => intval($request->get('rep_times')),
];
$piggyBank = $repository->store($piggyBankData);
Session::flash('success', 'Stored repeated expense "' . e($piggyBank->name) . '".');
return Redirect::route('repeated.index');
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param PiggyBank $repeatedExpense
*
* @return $this
*/
public function update(PiggyBank $repeatedExpense, PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
{
$piggyBankData = [
'repeats' => false,
'name' => $request->get('name'),
'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')),
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
'rep_length' => $request->get('rep_length'),
'rep_every' => intval($request->get('rep_every')),
'rep_times' => intval($request->get('rep_times')),
'remind_me' => intval($request->get('remind_me')) == 1 ? true : false ,
'reminder' => $request->get('reminder'),
];
$piggyBank = $repository->update($repeatedExpense, $piggyBankData);
Session::flash('success', 'Updated repeated expense "' . e($piggyBank->name) . '".');
return Redirect::route('repeated.index');
}
}

View File

@@ -1,14 +1,10 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use Exception;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Http\Requests;
use FireflyIII\Models\Account;
use Illuminate\Database\Query\JoinClause;
use Steam;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Session;
use View;
/**
@@ -19,264 +15,135 @@ use View;
class ReportController extends Controller
{
/** @var ReportHelperInterface */
protected $helper;
/**
* @codeCoverageIgnore
*
* @param ReportHelperInterface $helper
*/
public function __construct()
public function __construct(ReportHelperInterface $helper)
{
View::share('title', 'Reports');
parent::__construct();
$this->helper = $helper;
View::share('title', trans('firefly.reports'));
View::share('mainTitleIcon', 'fa-line-chart');
}
/**
* @param string $year
* @param string $month
*
* @return \Illuminate\View\View
*/
public function budget($year = '2014', $month = '1', ReportQueryInterface $query)
{
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date');
}
$date = new Carbon($year . '-' . $month . '-01');
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
$start->subDay();
$dayEarly = clone $date;
$subTitle = 'Budget report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$dayEarly = $dayEarly->subDay();
$accounts = $query->getAllAccounts($start, $end);
$start->addDay();
$accounts->each(
function (Account $account) use ($start, $end, $query) {
$budgets = $query->getBudgetSummary($account, $start, $end);
$balancedAmount = $query->balancedTransactionsList($account, $start, $end);
$array = [];
foreach ($budgets as $budget) {
$id = intval($budget->id);
$data = $budget->toArray();
$array[$id] = $data;
}
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
}
);
$start = clone $date;
$start->startOfMonth();
/**
* Start getBudgetsForMonth DONE
*/
$set = Auth::user()->budgets()->orderBy('budgets.name', 'ASC')
->leftJoin(
'budget_limits', function (JoinClause $join) use ($date) {
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
}
)
->get(['budgets.*', 'budget_limits.amount as amount']);
$budgets = Steam::makeArray($set);
$amountSet = $query->journalsByBudget($start, $end);
$amounts = Steam::makeArray($amountSet);
$budgets = Steam::mergeArrays($budgets, $amounts);
$budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0;
$budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0;
$budgets[0]['name'] = 'No budget';
// find transactions to shared expense accounts, which are without a budget by default:
$transfers = $query->sharedExpenses($start, $end);
foreach ($transfers as $transfer) {
$budgets[0]['spent'] += floatval($transfer->amount) * -1;
}
/**
* End getBudgetsForMonth DONE
*/
return view('reports.budget', compact('subTitle', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly'));
}
/**
* @param ReportHelperInterface $helper
* @param AccountRepositoryInterface $repository
*
* @return View
* @internal param ReportHelperInterface $helper
*/
public function index(ReportHelperInterface $helper)
public function index(AccountRepositoryInterface $repository)
{
$start = $helper->firstDate();
$months = $helper->listOfMonths($start);
$years = $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;
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->getMeta('accountRole') == 'sharedAsset') {
$hasShared = true;
}
}
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', ReportQueryInterface $query)
public function month($year = '2014', $month = '1', $shared = false)
{
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date.');
$start = new Carbon($year . '-' . $month . '-01');
$subTitle = trans('firefly.reportForMonth', ['month' => $start->formatLocalized($this->monthFormat)]);
$subTitleIcon = 'fa-calendar';
$end = clone $start;
$incomeTopLength = 8;
$expenseTopLength = 8;
if ($shared == 'shared') {
$shared = true;
$subTitle = trans('firefly.reportForMonthShared', ['month' => $start->formatLocalized($this->monthFormat)]);
}
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$displaySum = true; // to show sums in report.
/**
*
* get income for month (date)
*
*/
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
/**
* Start getIncomeForMonth DONE
*/
$income = $query->incomeByPeriod($start, $end);
/**
* End getIncomeForMonth DONE
*/
/**
* Start getExpenseGroupedForMonth DONE
*/
$set = $query->journalsByExpenseAccount($start, $end);
$expenses = Steam::makeArray($set);
$expenses = Steam::sortArray($expenses);
$expenses = Steam::limitArray($expenses, 10);
/**
* End getExpenseGroupedForMonth DONE
*/
/**
* Start getBudgetsForMonth DONE
*/
$set = Auth::user()->budgets()
->leftJoin(
'budget_limits', function (JoinClause $join) use ($date) {
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
}
)
->get(['budgets.*', 'budget_limits.amount as amount']);
$budgets = Steam::makeArray($set);
$amountSet = $query->journalsByBudget($start, $end);
$amounts = Steam::makeArray($amountSet);
$budgets = Steam::mergeArrays($budgets, $amounts);
$budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0;
$budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0;
$budgets[0]['name'] = 'No budget';
$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);
// find transactions to shared expense accounts, which are without a budget by default:
$transfers = $query->sharedExpenses($start, $end);
foreach ($transfers as $transfer) {
$budgets[0]['spent'] += floatval($transfer->amount) * -1;
}
/**
* End getBudgetsForMonth DONE
*/
/**
* Start getCategoriesForMonth DONE
*/
// all categories.
$result = $query->journalsByCategory($start, $end);
$categories = Steam::makeArray($result);
// all transfers
$result = $query->sharedExpensesByCategory($start, $end);
$transfers = Steam::makeArray($result);
$merged = Steam::mergeArrays($categories, $transfers);
// sort.
$sorted = Steam::sortNegativeArray($merged);
// limit to $limit:
$categories = Steam::limitArray($sorted, 10);
/**
* End getCategoriesForMonth DONE
*/
/**
* Start getAccountsForMonth
*/
$list = $query->accountList();
$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, ReportHelperInterface $helper, ReportQueryInterface $query)
public function year($year, $shared = false)
{
try {
new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date.');
}
$date = new Carbon('01-01-' . $year);
$end = clone $date;
$end->endOfYear();
$title = 'Reports';
$subTitle = $year;
$subTitleIcon = 'fa-bar-chart';
$mainTitleIcon = 'fa-line-chart';
$balances = $helper->yearBalanceReport($date);
$groupedIncomes = $query->journalsByRevenueAccount($date, $end);
$groupedExpenses = $query->journalsByExpenseAccount($date, $end);
$start = new Carbon('01-01-' . $year);
$end = clone $start;
$subTitle = trans('firefly.reportForYear', ['year' => $year]);
$subTitleIcon = 'fa-bar-chart';
$incomeTopLength = 8;
$expenseTopLength = 8;
//$groupedExpenses = $helper-> expensesGroupedByAccount($date, $end, 15);
if ($shared == 'shared') {
$shared = true;
$subTitle = trans('firefly.reportForYearShared', ['year' => $year]);
}
$end->endOfYear();
$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', 'shared', 'accounts', 'incomes', 'expenses', 'subTitle', 'subTitleIcon', 'incomeTopLength', 'expenseTopLength')
);
}

View File

@@ -1,10 +1,6 @@
<?php namespace FireflyIII\Http\Controllers;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Support\Search\SearchInterface;
use Illuminate\Http\Request;
use Input;
/**
@@ -12,9 +8,14 @@ use Input;
*
* @package FireflyIII\Http\Controllers
*/
class SearchController extends Controller {
class SearchController extends Controller
{
/**
* Results always come in the form of an array [results, count, fullCount]
*
* @param SearchInterface $searcher
*
* @return $this
*/
public function index(SearchInterface $searcher)
{
@@ -25,7 +26,7 @@ class SearchController extends Controller {
if (!is_null(Input::get('q')) && strlen(Input::get('q')) > 0) {
$rawQuery = trim(Input::get('q'));
$words = explode(' ', $rawQuery);
$subTitle = 'Results for "' . e($rawQuery) . '"';
$subTitle = trans('firefly.search_results_for', ['query' => $rawQuery]);
$transactions = $searcher->searchTransactions($words);
$accounts = $searcher->searchAccounts($words);

View File

@@ -0,0 +1,304 @@
<?php
namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests\TagFormRequest;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Response;
use Session;
use URL;
use View;
/**
* Class TagController
*
* Remember: a balancingAct takes at most one expense and one transfer.
* an advancePayment takes at most one expense, infinite deposits and NO transfers.
*
* transaction can only have one advancePayment OR balancingAct.
* Other attempts to put in such a tag are blocked.
* also show an error when editing a tag and it becomes either
* of these two types. Or rather, block editing of the tag.
*
* @package FireflyIII\Http\Controllers
*/
class TagController extends Controller
{
public $tagOptions = [];
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Tags');
View::share('mainTitleIcon', 'fa-tags');
View::share('hideTags', true);
$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', $this->tagOptions);
}
/**
* @return \Illuminate\View\View
*/
public function create()
{
$subTitle = trans('firefly.new_tag');
$subTitleIcon = 'fa-tag';
$preFilled = [
'tagMode' => 'nothing'
];
if (!Input::old('tagMode')) {
Session::flash('preFilled', $preFilled);
}
// put previous url in session if not redirect from store (not "create another").
if (Session::get('tags.create.fromStore') !== true) {
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'));
}
/**
* @param Tag $tag
*
* @return \Illuminate\View\View
*/
public function delete(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'));
}
/**
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(TagRepositoryInterface $repository, Tag $tag)
{
$tagName = $tag->tag;
$repository->destroy($tag);
Session::flash('success', 'Tag "' . e($tagName) . '" was deleted.');
Preferences::mark();
return Redirect::to(route('tags.index'));
}
/**
* @param Tag $tag
*
* @param TagRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function edit(Tag $tag, TagRepositoryInterface $repository)
{
$subTitle = trans('firefly.edit_tag', ['tag' => $tag->tag]);
$subTitleIcon = 'fa-tag';
/*
* Default tag options (again)
*/
$tagOptions = $this->tagOptions;
/*
* Can this tag become another type?
*/
$allowAdvance = $repository->tagAllowAdvance($tag);
$allowToBalancingAct = $repository->tagAllowBalancing($tag);
// edit tag options:
if ($allowAdvance === false) {
unset($tagOptions['advancePayment']);
}
if ($allowToBalancingAct === false) {
unset($tagOptions['balancingAct']);
}
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('tags.edit.fromUpdate') !== true) {
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'));
}
/**
* @param $state
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function hideTagHelp($state)
{
$state = $state == 'true' ? true : false;
Preferences::set('hideTagHelp', $state);
return Response::json([true]);
}
/**
*
*/
public function index()
{
/** @var Preference $helpHiddenPref */
$helpHiddenPref = Preferences::get('hideTagHelp', false);
$title = 'Tags';
$mainTitleIcon = 'fa-tags';
$helpHidden = $helpHiddenPref->data;
// group years.
$types = ['nothing', 'balancingAct', 'advancePayment'];
// loop each types and get the tags, group them by year.
$collection = [];
foreach ($types as $type) {
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get();
/** @var Tag $tag */
foreach ($tags as $tag) {
$year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year;
$month = is_null($tag->date) ? trans('firefly.no_month') : $tag->date->formatLocalized($this->monthFormat);
$collection[$type][$year][$month][] = $tag;
}
}
return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'helpHidden', 'collection'));
}
/**
* @param Tag $tag
*
* @return \Illuminate\View\View
*/
public function show(Tag $tag)
{
$subTitle = $tag->tag;
$subTitleIcon = 'fa-tag';
return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon'));
}
/**
* @param TagFormRequest $request
*
* @param TagRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(TagFormRequest $request, TagRepositoryInterface $repository)
{
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;
} else {
$latitude = null;
$longitude = null;
$zoomLevel = null;
}
$data = [
'tag' => $request->get('tag'),
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : '',
'latitude' => $latitude,
'longitude' => $longitude,
'zoomLevel' => $zoomLevel,
'tagMode' => $request->get('tagMode'),
];
$repository->store($data);
Session::flash('success', 'The tag has been created!');
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('tags.create.fromStore', true);
return Redirect::route('tags.create')->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('tags.create.url'));
}
/**
* @param TagFormRequest $request
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag)
{
if (Input::get('setTag') == 'true') {
$latitude = $request->get('latitude');
$longitude = $request->get('longitude');
$zoomLevel = $request->get('zoomLevel');
} else {
$latitude = null;
$longitude = null;
$zoomLevel = null;
}
$data = [
'tag' => $request->get('tag'),
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : '',
'latitude' => $latitude,
'longitude' => $longitude,
'zoomLevel' => $zoomLevel,
'tagMode' => $request->get('tagMode'),
];
$repository->update($tag, $data);
Session::flash('success', 'Tag "' . e($data['tag']) . '" updated.');
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {
// 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]);
}
// redirect to previous URL.
return Redirect::to(Session::get('tags.edit.url'));
}
}

View File

@@ -3,19 +3,21 @@
use Auth;
use Carbon\Carbon;
use ExpandedForm;
use FireflyIII\Http\Requests;
use FireflyIII\Events\JournalCreated;
use FireflyIII\Events\JournalSaved;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Input;
use Preferences;
use Redirect;
use Response;
use Session;
use URL;
use View;
/**
* Class TransactionController
*
@@ -24,40 +26,45 @@ use View;
class TransactionController extends Controller
{
/**
* @codeCoverageIgnore
*/
public function __construct()
{
View::share('title', 'Transactions');
parent::__construct();
View::share('title', trans('firefly.transactions'));
View::share('mainTitleIcon', 'fa-repeat');
}
/**
* Shows the view helping the user to create a new transaction journal.
*
* @param string $what
* @param AccountRepositoryInterface $repository
* @param string $what
*
* @return \Illuminate\View\View
*/
public function create($what = 'deposit')
public function create(AccountRepositoryInterface $repository, $what = 'deposit')
{
$accounts = ExpandedForm::makeSelectList(
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->where('active', 1)->orderBy('name', 'DESC')->get(['accounts.*'])
);
$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);
// put previous url in session if not redirect from store (not "create another").
if (Session::get('transactions.create.fromStore') !== true) {
Session::put('transactions.create.url', URL::previous());
}
Session::forget('transactions.create.fromStore');
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'create-' . $what);
asort($piggies);
@@ -69,68 +76,70 @@ 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) . '"';
$what = strtolower($journal->transactionType->type);
$subTitle = trans('firefly.delete_' . $what, ['description' => $journal->description]);
return View::make('transactions.delete', compact('journal', 'subTitle'));
// put previous url in session
Session::put('transactions.delete.url', URL::previous());
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'delete-' . $what);
return view('transactions.delete', compact('journal', 'subTitle', 'what'));
}
/**
* @param TransactionJournal $transactionJournal
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $transactionJournal
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(TransactionJournal $transactionJournal)
public function destroy(JournalRepositoryInterface $repository, TransactionJournal $transactionJournal)
{
$type = $transactionJournal->transactionType->type;
$return = 'withdrawal';
Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.');
$transactionJournal->delete();
$repository->delete($transactionJournal);
switch ($type) {
case 'Deposit':
$return = 'deposit';
break;
case 'Transfer':
$return = 'transfers';
break;
}
Preferences::mark();
return Redirect::route('transactions.index', $return);
// redirect to previous URL:
return Redirect::to(Session::get('transactions.delete.url'));
}
/**
* Shows the view to edit a transaction.
*
* @param TransactionJournal $journal
* @param AccountRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return $this
*/
public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository)
public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal)
{
$what = strtolower($journal->transactiontype->type);
$accounts = ExpandedForm::makeSelectList(
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->where('active', 1)->orderBy('name', 'DESC')->get(['accounts.*'])
);
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$transactions = $journal->transactions()->orderBy('amount', 'DESC')->get();
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = '(no piggy bank)';
$preFilled = [
$what = strtolower($journal->transactionType->type);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = trans('form.noBudget');
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = trans('form.noPiggybank');
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
$preFilled = [
'date' => $journal->date->format('Y-m-d'),
'category' => '',
'budget_id' => 0,
'piggy_bank_id' => 0
];
// get tags:
$tags = [];
foreach ($journal->tags as $tag) {
$tags[] = $tag->tag;
}
$preFilled['tags'] = join(',', $tags);
$category = $journal->categories()->first();
if (!is_null($category)) {
@@ -143,65 +152,70 @@ class TransactionController extends Controller
}
if ($journal->piggyBankEvents()->count() > 0) {
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->first()->piggy_bank_id;
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
}
$preFilled['amount'] = 0;
/** @var Transaction $t */
foreach ($transactions as $t) {
if (floatval($t->amount) > 0) {
$preFilled['amount'] = floatval($t->amount);
}
$preFilled['amount'] = $journal->actual_amount;
if ($journal->transactionType->type == 'Withdrawal') {
$preFilled['account_id'] = $journal->source_account->id;
$preFilled['expense_account'] = $journal->destination_account->name_for_editform;
} else {
$preFilled['account_id'] = $journal->destination_account->id;
$preFilled['revenue_account'] = $journal->source_account->name_for_editform;
}
$preFilled['account_id'] = $repository->getAssetAccount($journal);
$preFilled['expense_account'] = $transactions[0]->account->name;
$preFilled['revenue_account'] = $transactions[1]->account->name;
$preFilled['account_from_id'] = $transactions[1]->account->id;
$preFilled['account_to_id'] = $transactions[0]->account->id;
$preFilled['account_from_id'] = $journal->source_account->id;
$preFilled['account_to_id'] = $journal->destination_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) {
Session::put('transactions.edit.url', URL::previous());
}
Session::forget('transactions.edit.fromUpdate');
return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled);
}
/**
* @param $what
* @param JournalRepositoryInterface $repository
* @param $what
*
* @return $this
* @return \Illuminate\View\View
*/
public function index($what)
public function index(JournalRepositoryInterface $repository, $what)
{
$types = [];
switch ($what) {
case 'expenses':
case 'withdrawal':
$subTitleIcon = 'fa-long-arrow-left';
$subTitle = 'Expenses';
//$journals = $this->_repository->getWithdrawalsPaginated(50);
$types = ['Withdrawal'];
$subTitle = trans('firefly.expenses');
$types = ['Withdrawal'];
break;
case 'revenue':
case 'deposit':
$subTitleIcon = 'fa-long-arrow-right';
$subTitle = 'Revenue, income and deposits';
// $journals = $this->_repository->getDepositsPaginated(50);
$types = ['Deposit'];
$subTitle = trans('firefly.income');
$types = ['Deposit'];
break;
case 'transfer':
case 'transfers':
$subTitleIcon = 'fa-arrows-h';
$subTitle = 'Transfers';
//$journals = $this->_repository->getTransfersPaginated(50);
$types = ['Transfer'];
$subTitleIcon = 'fa-exchange';
$subTitle = trans('firefly.transfers');
$types = ['Transfer'];
break;
}
$page = intval(\Input::get('page'));
$offset = $page > 0 ? ($page - 1) * 50 : 0;
$page = intval(Input::get('page'));
$offset = $page > 0 ? ($page - 1) * 50 : 0;
$journals = $repository->getJournalsOfTypes($types, $offset, $page);
$set = Auth::user()->transactionJournals()->transactionTypes($types)->withRelevantData()->take(50)->offset($offset)->orderBy('date', 'DESC')->get(
['transaction_journals.*']
);
$count = Auth::user()->transactionJournals()->transactionTypes($types)->count();
$journals = new LengthAwarePaginator($set, $count, 50, $page);
$journals->setPath('transactions/' . $what);
return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals'));
@@ -209,98 +223,115 @@ class TransactionController extends Controller
}
/**
* @param TransactionJournal $journal
* @param JournalRepositoryInterface $repository
*
* @return $this
* @return \Symfony\Component\HttpFoundation\Response
*/
public function show(TransactionJournal $journal)
public function reorder(JournalRepositoryInterface $repository)
{
$journal->transactions->each(
function (Transaction $t) use ($journal) {
$t->before = floatval(
$t->account->transactions()->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))->where(
'transaction_journals.created_at', '<=', $journal->created_at->format('Y-m-d H:i:s')
)->where('transaction_journals.id', '!=', $journal->id)->sum('transactions.amount')
);
$t->after = $t->before + $t->amount;
}
);
$members = new Collection;
/** @var TransactionGroup $group */
foreach ($journal->transactiongroups()->get() as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$members->push($loopJournal);
$ids = Input::get('items');
$date = new Carbon(Input::get('date'));
if (count($ids) > 0) {
$order = 0;
foreach ($ids as $id) {
$journal = $repository->getWithDate($id, $date);
if ($journal) {
$journal->order = $order;
$order++;
$journal->save();
}
}
}
Preferences::mark();
return view('transactions.show', compact('journal', 'members'))->with(
'subTitle', e($journal->transactiontype->type) . ' "' . e($journal->description) . '"'
);
}
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository)
{
$journalData = [
'what' => $request->get('what'),
'description' => $request->get('description'),
'account_id' => intval($request->get('account_id')),
'account_from_id' => intval($request->get('account_from_id')),
'account_to_id' => intval($request->get('account_to_id')),
'expense_account' => $request->get('expense_account'),
'revenue_account' => $request->get('revenue_account'),
'amount' => floatval($request->get('amount')),
'user' => Auth::user()->id,
'amount_currency_id' => intval($request->get('amount_currency_id')),
'date' => new Carbon($request->get('date')),
'budget_id' => intval($request->get('budget_id')),
'category' => $request->get('category'),
];
$journal = $repository->store($journalData);
Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
return Redirect::route('transactions.index', $request->input('what'));
return Response::json([true]);
}
/**
* @param TransactionJournal $journal
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @return $this
* @throws FireflyException
* @return \Illuminate\View\View
*/
public function update(TransactionJournal $journal, JournalFormRequest $request, JournalRepositoryInterface $repository)
public function show(JournalRepositoryInterface $repository, TransactionJournal $journal)
{
$journal->transactions->each(
function (Transaction $t) use ($journal, $repository) {
$t->before = $repository->getAmountBefore($journal, $t);
$t->after = $t->before + $t->amount;
}
);
$what = strtolower($journal->transactionType->type);
$subTitle = trans('firefly.' . $journal->transactionType->type) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal', 'subTitle', 'what'));
}
/**
* @param JournalFormRequest $request
* @param JournalRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository)
{
$journalData = [
'what' => $request->get('what'),
'description' => $request->get('description'),
'account_id' => intval($request->get('account_id')),
'account_from_id' => intval($request->get('account_from_id')),
'account_to_id' => intval($request->get('account_to_id')),
'expense_account' => $request->get('expense_account'),
'revenue_account' => $request->get('revenue_account'),
'amount' => floatval($request->get('amount')),
'user' => Auth::user()->id,
'amount_currency_id' => intval($request->get('amount_currency_id')),
'date' => new Carbon($request->get('date')),
'budget_id' => intval($request->get('budget_id')),
'category' => $request->get('category'),
];
$journalData = $request->getJournalData();
$journal = $repository->store($journalData);
// rescan journal, UpdateJournalConnection
event(new JournalSaved($journal));
// ConnectJournalToPiggyBank
if ($journal->transactionType->type == 'Transfer' && intval($request->get('piggy_bank_id')) > 0) {
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
}
Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('transactions.create.fromStore', true);
return Redirect::route('transactions.create', [$request->input('what')])->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('transactions.create.url'));
}
/**
* @param JournalFormRequest $request
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{
$journalData = $request->getJournalData();
$repository->update($journal, $journalData);
Session::flash('success', 'Transaction "' . e($journalData['description']) . '" updated.');
return Redirect::route('transactions.index', $journalData['what']);
event(new JournalSaved($journal));
// update, get events by date and sort DESC
Session::flash('success', 'Transaction "' . e($journalData['description']) . '" updated.');
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {
// 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]);
}
// redirect to previous URL.
return Redirect::to(Session::get('transactions.edit.url'));
}

View File

@@ -22,6 +22,7 @@ class Kernel extends HttpKernel
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'FireflyIII\Http\Middleware\ReplaceTestVars',
'FireflyIII\Http\Middleware\VerifyCsrfToken',
];
@@ -36,6 +37,7 @@ class Kernel extends HttpKernel
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated',
'range' => 'FireflyIII\Http\Middleware\Range',
];
}

View File

@@ -1,11 +1,17 @@
<?php namespace FireflyIII\Http\Middleware;
use App;
use Carbon\Carbon;
use Closure;
use Config;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Preferences;
/**
* Class Authenticate
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class Authenticate
@@ -37,7 +43,7 @@ class Authenticate
*
* @return mixed
*/
public function handle($request, Closure $next)
public function handle(Request $request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
@@ -46,6 +52,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

@@ -3,12 +3,15 @@
namespace FireflyIII\Http\Middleware;
use App;
use Carbon\Carbon;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Navigation;
use Preferences;
use Session;
use View;
/**
* Class SessionFilter
@@ -40,36 +43,46 @@ class Range
*
* @param \Illuminate\Http\Request $request
* @param \Closure $theNext
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return mixed
*/
public function handle($request, Closure $theNext)
public function handle(Request $request, Closure $theNext)
{
if ($this->auth->check()) {
// user's view range comes from preferences, gets set in session:
/** @var \FireflyIII\Models\Preference $viewRange */
$viewRange = Preferences::get('viewRange', '1M');
// ignore preference. set the range to be the current month:
if (!Session::has('start') && !Session::has('end')) {
// the start and end date are checked and stored:
$start = Session::has('start') ? Session::get('start') : new Carbon;
$start = Navigation::updateStartDate($viewRange->data, $start);
$end = Navigation::updateEndDate($viewRange->data, $start);
$period = Navigation::periodName($viewRange->data, $start);
$prev = Navigation::jumpToPrevious($viewRange->data, clone $start);
$next = Navigation::jumpToNext($viewRange->data, clone $start);
Session::put('range', $viewRange->data);
Session::put('start', $start);
Session::put('end', $end);
Session::put('period', $period);
Session::put('prev', Navigation::periodName($viewRange->data, $prev));
Session::put('next', Navigation::periodName($viewRange->data, $next));
/** @var \FireflyIII\Models\Preference $viewRange */
$viewRange = Preferences::get('viewRange', '1M')->data;
$start = new Carbon;
$start = Navigation::updateStartDate($viewRange, $start);
$end = Navigation::updateEndDate($viewRange, $start);
Session::put('start', $start);
Session::put('end', $end);
}
if (!Session::has('first')) {
/** @var \FireflyIII\Repositories\Journal\JournalRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Journal\JournalRepositoryInterface');
$journal = $repository->first();
if ($journal) {
Session::put('first', $journal->date);
} else {
Session::put('first', Carbon::now()->startOfYear());
}
}
$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

@@ -3,10 +3,12 @@
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
/**
* Class RedirectIfAuthenticated
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class RedirectIfAuthenticated
@@ -38,7 +40,7 @@ class RedirectIfAuthenticated
*
* @return mixed
*/
public function handle($request, Closure $next)
public function handle(Request $request, Closure $next)
{
if ($this->auth->check()) {
return new RedirectResponse(url('/'));

View File

@@ -0,0 +1,57 @@
<?php
namespace FireflyIII\Http\Middleware;
use Closure;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Request;
use Log;
/**
* Class ReplaceTestVars
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class ReplaceTestVars
{
/**
* The application implementation.
*
* @var Application
*/
protected $app;
/**
* Create a new filter instance.
*
* @param Application $app
*
*/
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ('testing' === $this->app->environment() && $request->has('_token')) {
$input = $request->all();
$input['_token'] = $request->session()->token();
// we need to update _token value to make sure we get the POST / PUT tests passed.
Log::debug('Input token replaced (' . $input['_token'] . ').');
$request->replace($input);
}
return $next($request);
}
}

View File

@@ -6,6 +6,7 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
/**
* Class VerifyCsrfToken
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class VerifyCsrfToken extends BaseVerifier

View File

@@ -10,6 +10,7 @@ use Input;
/**
* Class AccountFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class AccountFormRequest extends Request
@@ -28,22 +29,29 @@ class AccountFormRequest extends Request
*/
public function rules()
{
$accountRoles = join(',', array_keys(Config::get('firefly.accountRoles')));
$types = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier')));
$accountRoles = join(',', array_keys(Config::get('firefly.accountRoles')));
$types = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = join(',', array_keys(Config::get('firefly.ccTypes')));
$nameRule = 'required|between:1,100|uniqueForUser:accounts,name';
$nameRule = 'required|min:1|uniqueAccountForUser';
$idRule = '';
if (Account::find(Input::get('id'))) {
$nameRule = 'required|between:1,100';
$idRule = 'belongsToUser:accounts';
$nameRule = 'required|min:1|uniqueAccountForUser:' . Input::get('id');
}
return [
'name' => $nameRule,
'openingBalance' => 'numeric',
'openingBalanceDate' => 'date',
'accountRole' => 'in:' . $accountRoles,
'active' => 'boolean',
'balance_currency_id' => 'exists:transaction_currencies,id',
'what' => 'in:' . $types
'id' => $idRule,
'name' => $nameRule,
'openingBalance' => 'numeric',
'virtualBalance' => 'numeric',
'openingBalanceDate' => 'date',
'accountRole' => 'in:' . $accountRoles,
'active' => 'boolean',
'ccType' => 'in:' . $ccPaymentTypes,
'ccMonthlyPaymentDate' => 'date',
'balance_currency_id' => 'exists:transaction_currencies,id',
'what' => 'in:' . $types
];
}
}
}

View File

@@ -1,19 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 25/02/15
* Time: 12:29
*/
namespace FireflyIII\Http\Requests;
use Auth;
use Carbon\Carbon;
use Input;
/**
* Class BillFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class BillFormRequest extends Request
@@ -27,19 +23,41 @@ class BillFormRequest extends Request
return Auth::check();
}
/**
* @return array
*/
public function getBillData()
{
return [
'name' => $this->get('name'),
'match' => $this->get('match'),
'amount_min' => floatval($this->get('amount_min')),
'amount_currency_id' => floatval($this->get('amount_currency_id')),
'amount_max' => floatval($this->get('amount_max')),
'date' => new Carbon($this->get('date')),
'user' => Auth::user()->id,
'repeat_freq' => $this->get('repeat_freq'),
'skip' => intval($this->get('skip')),
'automatch' => intval($this->get('automatch')) === 1,
'active' => intval($this->get('active')) === 1,
];
}
/**
* @return array
*/
public function rules()
{
$nameRule = 'required|between:1,255|uniqueForUser:bills,name';
if(intval(Input::get('id')) > 0) {
$nameRule .= ','.intval(Input::get('id'));
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name';
$matchRule = 'required|between:1,255|uniqueObjectForUser:bills,match';
if (intval(Input::get('id')) > 0) {
$nameRule .= ',' . intval(Input::get('id'));
$matchRule .= ',' . intval(Input::get('id'));
}
$rules = [
'name' => $nameRule,
'match' => 'required|between:1,255',
'match' => $matchRule,
'amount_min' => 'required|numeric|min:0.01',
'amount_max' => 'required|numeric|min:0.01',
'amount_currency_id' => 'required|exists:transaction_currencies,id',
@@ -52,4 +70,4 @@ class BillFormRequest extends Request
return $rules;
}
}
}

View File

@@ -9,6 +9,7 @@ use Input;
/**
* Class BudgetFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class BudgetFormRequest extends Request
@@ -28,13 +29,14 @@ class BudgetFormRequest extends Request
public function rules()
{
$nameRule = 'required|between:1,100|uniqueForUser:budgets,name';
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name';
if (Budget::find(Input::get('id'))) {
$nameRule = 'required|between:1,100';
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,' . intval(Input::get('id'));
}
return [
'name' => $nameRule,
'name' => $nameRule,
'active' => 'numeric|between:0,1'
];
}
}
}

View File

@@ -9,6 +9,7 @@ use Input;
/**
* Class CategoryFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class CategoryFormRequest extends Request
@@ -28,13 +29,13 @@ class CategoryFormRequest extends Request
public function rules()
{
$nameRule = 'required|between:1,100|uniqueForUser:categories,name';
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name';
if (Category::find(Input::get('id'))) {
$nameRule = 'required|between:1,100';
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,' . intval(Input::get('id'));
}
return [
'name' => $nameRule,
];
}
}
}

View File

@@ -1,10 +1,4 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 25/02/15
* Time: 12:29
*/
namespace FireflyIII\Http\Requests;
@@ -14,6 +8,7 @@ use Input;
/**
* Class BillFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class CurrencyFormRequest extends Request
@@ -27,6 +22,18 @@ class CurrencyFormRequest extends Request
return Auth::check();
}
/**
* @return array
*/
public function getCurrencyData()
{
return [
'name' => $this->get('name'),
'code' => $this->get('code'),
'symbol' => $this->get('symbol'),
];
}
/**
* @return array
*/
@@ -48,4 +55,4 @@ class CurrencyFormRequest extends Request
return $rules;
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace FireflyIII\Http\Requests;
use Auth;
/**
* Class DeleteAccountFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class DeleteAccountFormRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
return [
'password' => 'required',
];
}
}

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