Compare commits

...

211 Commits
3.8.4 ... 3.9.0

Author SHA1 Message Date
James Cole
f8eb1fa44a Merge branch 'release/3.9.0'
Signed-off-by: James Cole <thegrumpydictator@gmail.com>

# Conflicts:
#	app/Helpers/Csv/Converter/BillName.php
2016-05-22 16:46:11 +02:00
James Cole
afc794513f last minute composer update [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-22 16:43:47 +02:00
James Cole
7e6d3c9d6b Various last minute bug fixes.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-22 16:38:32 +02:00
James Cole
44960e8e42 Various last minute bug fixes. 2016-05-22 15:48:34 +02:00
James Cole
41430c3bb2 Same bug, another line. 2016-05-22 09:08:37 +02:00
James Cole
2f435019e0 Fix bug. 2016-05-22 09:04:16 +02:00
James Cole
480e70dfac Sharper spent in period. [skip ci] 2016-05-20 18:30:48 +02:00
James Cole
c4818334e7 Sharper spent in period. [skip ci] 2016-05-20 18:29:51 +02:00
James Cole
a5d5f86aed Some code cleanup and a better chart [skip ci] 2016-05-20 18:26:43 +02:00
James Cole
78afb771b1 Code cleanup [skip ci] 2016-05-20 17:58:10 +02:00
James Cole
a74a646777 Code cleanup. Moving closer to new release. 2016-05-20 17:53:03 +02:00
James Cole
87f9ca3bb2 Removed some old configuration values. 2016-05-20 17:28:07 +02:00
James Cole
d54e264a91 Cannot create empty tags.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-20 15:09:25 +02:00
James Cole
99aea5ce7a Fix bug in verification.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-20 15:08:24 +02:00
James Cole
e10d5e89e5 Last minute bug fixes.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-20 15:02:52 +02:00
James Cole
0105456828 Copyright notices. [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-20 12:42:21 +02:00
James Cole
5c7df5c04d Copyright notices. [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-20 12:41:23 +02:00
James Cole
563ede822f Copyright notices. [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-05-20 12:27:31 +02:00
James Cole
786cfc21c7 Make strval for bcadd [skip ci] 2016-05-20 12:08:48 +02:00
James Cole
8f0856e31a Make strval for bcadd [skip ci] 2016-05-20 12:07:55 +02:00
James Cole
bea075c74d Make strval for bcadd [skip ci] 2016-05-20 12:06:54 +02:00
James Cole
5f82accb61 Point to other library. [skip ci] 2016-05-20 12:03:28 +02:00
James Cole
95f50ca2fd Point to other library. [skip ci] 2016-05-20 12:02:19 +02:00
James Cole
d8b76bdfd2 Code cleanup [skip ci] 2016-05-20 11:59:54 +02:00
James Cole
74a9edaaf7 Bug fixes in strict types. 2016-05-20 11:53:34 +02:00
James Cole
7dd858be39 Fix bugs. 2016-05-20 11:27:41 +02:00
James Cole
7d7ff71384 New routes. 2016-05-20 11:09:09 +02:00
James Cole
003177fa49 Move stuff around. 2016-05-20 11:09:02 +02:00
James Cole
3c3a83330d More moving stuff around. 2016-05-20 11:02:07 +02:00
James Cole
724f423692 Move some stuff around. 2016-05-20 09:45:24 +02:00
James Cole
65b8882ed4 Clean up repository. 2016-05-20 09:25:17 +02:00
James Cole
66d7fd7d4c Declare strict types. 2016-05-20 08:57:45 +02:00
James Cole
782a6f289c Remove deprecated methods. 2016-05-20 08:11:54 +02:00
James Cole
70d936bb8f Fix filters and other methods that used deprecated methods. 2016-05-20 08:09:53 +02:00
James Cole
dda3082c7e Some code cleanup. 2016-05-20 08:00:35 +02:00
James Cole
ed948cc965 Allow user to split unsplit journal 2016-05-20 07:51:26 +02:00
James Cole
0347649f42 Fix some views. 2016-05-20 06:58:13 +02:00
James Cole
c66fe2b541 Fix some views [skip ci] 2016-05-20 06:27:48 +02:00
James Cole
8c1ae76c7a More tight report thing [skip ci] 2016-05-19 13:39:36 +02:00
James Cole
04dee404c0 More narrow result for popup. [skip ci] 2016-05-19 13:38:12 +02:00
James Cole
b22dd29835 Fix charts. [skip ci] 2016-05-19 08:57:25 +02:00
James Cole
536a5cd1c8 New translations. [skip ci] 2016-05-18 18:13:38 +02:00
James Cole
b7f1bcf7c9 Slightly larger screenshots. [skip ci] 2016-05-18 14:24:59 +02:00
James Cole
5e590072dd Slightly larger screenshots. [skip ci] 2016-05-18 14:24:31 +02:00
James Cole
d204b9b752 Slightly larger screenshots. [skip ci] 2016-05-18 14:23:54 +02:00
James Cole
22d1121193 New read me. [skip ci] 2016-05-18 14:22:48 +02:00
James Cole
e23c6521b9 Add expenses. [skip ci] 2016-05-18 14:19:33 +02:00
James Cole
b0cb9663a6 Updated read me [skip ci] 2016-05-18 07:23:11 +02:00
James Cole
95b7da89f0 Some code cleanup. 2016-05-18 07:01:27 +02:00
James Cole
b0a5b53abb Better number formatting. 2016-05-17 19:23:23 +02:00
James Cole
ce78c8993f Optimise query. [skip ci] 2016-05-17 16:47:43 +02:00
James Cole
2538b4a885 Small changes to audit report. 2016-05-17 16:11:19 +02:00
James Cole
109d96ad16 Small but expensive changes to audit report. 2016-05-17 16:10:32 +02:00
James Cole
4cbb0d9716 Fixed split journals views. 2016-05-17 16:00:27 +02:00
James Cole
65ecea3b1c Small fix to split data. 2016-05-17 15:25:03 +02:00
James Cole
495b80f5ef More code for the split journal support. 2016-05-17 15:19:07 +02:00
James Cole
e113736887 Should fix issue #263 2016-05-17 12:45:31 +02:00
James Cole
042b7a4966 Fix multi-year chart. [skip ci] 2016-05-16 12:51:52 +02:00
James Cole
5ab8cb38d3 Small change in report [skip ci] 2016-05-16 12:47:43 +02:00
James Cole
fc4ab29244 Fixed chart. [skip ci] 2016-05-16 09:05:06 +02:00
James Cole
5a43e6cb9f Better query for no budget. [skip ci] 2016-05-16 07:13:54 +02:00
James Cole
4effc95c5f Fixed some report bugs. 2016-05-15 19:23:19 +02:00
James Cole
962965b5b7 Code cleanup. 2016-05-15 18:36:40 +02:00
James Cole
260b611293 Various fixes in report pages. 2016-05-15 18:16:31 +02:00
James Cole
d2131c371b Fixed more report details. 2016-05-15 17:53:00 +02:00
James Cole
eedf6a07f0 Fixed the income report. 2016-05-15 17:46:53 +02:00
James Cole
5cd1e7c100 Fix charts. [skip ci] 2016-05-15 16:15:17 +02:00
James Cole
6a750a998f Remove category chart from report controller. 2016-05-15 16:13:05 +02:00
James Cole
bd818b2dea Code clean up. 2016-05-15 15:39:22 +02:00
James Cole
4164ebcc69 Added a lot of todo things. 2016-05-15 15:24:23 +02:00
James Cole
60d732067b Made some things less complex. 2016-05-15 15:08:59 +02:00
James Cole
b7b52707fb Fix Travis. 2016-05-15 15:02:07 +02:00
James Cole
f373c72679 Remove tests. 2016-05-15 15:01:29 +02:00
James Cole
ec2027b8db Update git ignore. [skip ci] 2016-05-15 14:48:52 +02:00
James Cole
a84de5db77 Enable caching. Remove stuff for development. 2016-05-15 14:48:21 +02:00
James Cole
5065b1ee03 Enable cache [skip ci] 2016-05-15 12:39:39 +02:00
James Cole
a0aa114ee6 Update balance view. [skip ci] 2016-05-15 12:32:18 +02:00
James Cole
823839fbf6 Better routes and titles. 2016-05-15 12:26:40 +02:00
James Cole
1c93d8bf79 More test data and better views. 2016-05-15 12:08:41 +02:00
James Cole
626404407e More support for #142 2016-05-15 09:00:49 +02:00
James Cole
446ab62d38 View updates. [skip ci] 2016-05-14 23:14:49 +02:00
James Cole
0d39161ec3 Fix iban in test data. 2016-05-14 22:23:55 +02:00
James Cole
29be16dcba Fix complex query. [skip ci] 2016-05-14 22:21:08 +02:00
James Cole
b0bb790386 Experimental query. [skip ci] 2016-05-14 22:12:16 +02:00
James Cole
e64b40d58b Experimental query. [skip ci] 2016-05-14 22:11:49 +02:00
James Cole
4870945af2 Remove references to unused library. 2016-05-14 21:55:43 +02:00
James Cole
a547a5f3f9 New Chart library. [skip ci] 2016-05-14 21:50:02 +02:00
James Cole
e5eabdf7e7 Clean up test data. 2016-05-14 21:49:16 +02:00
James Cole
f78d56b149 Will implement changes to test database. 2016-05-14 17:08:28 +02:00
James Cole
771926c779 No longer needed. 2016-05-14 14:02:37 +02:00
James Cole
6090efe2df Refactoring. 2016-05-14 14:02:12 +02:00
James Cole
863227c55c Some refactoring. 2016-05-14 13:51:33 +02:00
James Cole
5a6967cefd Better formatting for split transactions. 2016-05-13 19:40:13 +02:00
James Cole
5166171e5d More refactoring 2016-05-13 17:22:24 +02:00
James Cole
3e36a29c23 More refactoring. 2016-05-13 15:58:30 +02:00
James Cole
20e1e50032 Refactoring. 2016-05-13 15:53:39 +02:00
James Cole
36bc483edb Reorder some fields. 2016-05-13 10:50:19 +02:00
James Cole
aa59227786 Fixed transactions and attachments. 2016-05-13 09:55:06 +02:00
James Cole
2d8449ed68 This should just about finished split transaction editing. 2016-05-13 07:33:04 +02:00
James Cole
d7ab482ae1 Various updates for split transactions. 2016-05-12 22:44:31 +02:00
James Cole
cfcc4ce88a Let's leave this on false. 2016-05-12 16:34:44 +02:00
James Cole
eda44bbed0 Merge branch 'develop' of github.com:JC5/firefly-iii into develop 2016-05-12 12:13:42 +02:00
James Cole
988049061d Start with edit split journals routine. 2016-05-12 12:13:10 +02:00
James Cole
ebb1c5ae25 Merge pull request #260 from zjean/ssl
Force https schema if APP_FORCE_SSL=true in .env
2016-05-12 11:00:41 +02:00
James Cole
ce7eebac5c Build edit split transactions. 2016-05-12 10:38:44 +02:00
James Cole
b7c446f7db Start with edit and view screens. 2016-05-11 23:03:13 +02:00
James Cole
7c39a04c4b Cleanup. 2016-05-11 17:33:22 +02:00
James Cole
037d84b810 Fixes for transactions. 2016-05-11 17:17:43 +02:00
James Cole
529bf50c85 Removed some dead code. 2016-05-11 10:37:56 +02:00
James Cole
d2b4bd78a9 Removed some dead code. 2016-05-11 10:02:27 +02:00
James Cole
e1c146a5c1 Reinstate chart. 2016-05-11 09:17:47 +02:00
James Cole
ed9acbdfde Reinstate report. 2016-05-11 09:08:18 +02:00
James Cole
dc825d5a9c Fix queries. 2016-05-11 08:40:22 +02:00
James Cole
9f8faf15f1 Reinstate sorting. 2016-05-11 08:10:05 +02:00
James Cole
934656c954 Some small changes. 2016-05-11 07:57:16 +02:00
James Cole
d233a2df3c Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Should fix frontpage.

# Conflicts:
#	app/Models/TransactionJournal.php
#	app/Repositories/Account/AccountRepository.php
2016-05-11 06:08:05 +02:00
James Cole
7c7740d3ba Should fix frontpage. 2016-05-10 09:33:23 +02:00
James Cole
cda6cfb4cd Fix more charts. 2016-05-09 20:15:26 +02:00
James Cole
a90d095609 More stuff for categories. 2016-05-09 18:06:53 +02:00
James Cole
98e683329e New stuff for categories and transactions. 2016-05-08 13:45:23 +02:00
James Cole
3588bd881c More chart cleanup. 2016-05-06 22:54:36 +02:00
James Cole
0460811e6c Fixed some more charts. 2016-05-06 22:53:08 +02:00
James Cole
27f5fe18df Moving stuff around, optimising charts. 2016-05-06 10:32:26 +02:00
James Cole
6d944ec98f More cleanup for budgets. 2016-05-06 06:15:46 +02:00
James Cole
adf6691470 This breaks everything budget-related. 2016-05-05 22:03:35 +02:00
James Cole
dd8b500efd These budget charts are the worst, I'm telling you. 2016-05-05 21:25:20 +02:00
James Cole
4e1ff8c4a3 Removed phpunit.xml 2016-05-05 19:07:46 +02:00
James Cole
e73d590ead Update composer.lock 2016-05-05 19:05:29 +02:00
James Cole
5cc22f49cf Fix tests. 2016-05-05 19:04:21 +02:00
James Cole
eb3d2b1749 Building split transactions and fixing tests. 2016-05-05 18:59:46 +02:00
James Cole
21a197ba46 More translations. 2016-05-05 07:46:19 +02:00
James Cole
0b74707638 Display and handle errors. 2016-05-05 07:46:11 +02:00
James Cole
16dc8b7d68 Translation for error. 2016-05-05 07:45:52 +02:00
James Cole
5a8abe004e Field rename 2016-05-05 07:45:40 +02:00
James Cole
b211d72c8b Static data must remain static data. 2016-05-05 07:45:29 +02:00
James Cole
36f3eb8b2f Small fix in journal handler. 2016-05-05 07:09:12 +02:00
zjean
cb1cb9f328 Force https schema if APP_FORCE_SSL=true in .env 2016-05-04 22:09:42 +02:00
James Cole
3344bb7263 Code cleanup. 2016-05-02 20:49:19 +02:00
James Cole
5e1167b8ae Code cleanup. 2016-05-01 15:05:29 +02:00
James Cole
b80db054e2 Remove journal collector. 2016-05-01 09:52:58 +02:00
James Cole
c66df3cb2c Code cleanup. 2016-05-01 09:42:08 +02:00
James Cole
ac8ff4e565 Clean up repository. 2016-05-01 07:09:58 +02:00
James Cole
bfa7ee90f4 Reverse stuff 2016-05-01 06:59:08 +02:00
James Cole
77c9e37584 Move some stuff around. 2016-05-01 06:37:47 +02:00
James Cole
80350f8423 Fix for transactions. 2016-04-30 22:30:11 +02:00
James Cole
3c1ff4d21f Fix query. 2016-04-30 22:05:58 +02:00
James Cole
55b8f03590 Some new data thing. 2016-04-30 21:20:39 +02:00
James Cole
1fd7852309 Fix query thing. 2016-04-30 20:24:47 +02:00
James Cole
9c5292962f More stuff for splits. 2016-04-30 19:50:42 +02:00
James Cole
c05c6e72c0 Display budget and category if relevant. 2016-04-30 16:36:58 +02:00
James Cole
bdcd033952 Fix edit routine 2016-04-30 12:46:21 +02:00
James Cole
4ec6bcc8c7 More code for split and small bug fix in attachment helper. 2016-04-30 09:48:39 +02:00
James Cole
11ea4b6d47 Fix migrations. 2016-04-30 07:15:28 +02:00
James Cole
e4f45b5370 List of categories will check transactions as well. #142 2016-04-29 22:00:24 +02:00
James Cole
9baadd3793 Use other method of collecting query fields. #142 2016-04-29 21:52:15 +02:00
James Cole
94a79876ce View for split transactions. #142 2016-04-29 21:49:18 +02:00
James Cole
42c3d1fa68 Expanding support for split transactions #142 2016-04-29 21:36:59 +02:00
James Cole
0e3ccebd0b First attempt at #142. Needs a lot of work still. 2016-04-29 20:59:28 +02:00
James Cole
4af8272faa Updates to transactions. 2016-04-29 17:29:13 +02:00
James Cole
0ef3d0cf03 Better message for issue #247 2016-04-29 17:26:59 +02:00
James Cole
f266b92ef1 This catches issue #247 2016-04-29 17:26:38 +02:00
James Cole
462c9fb3aa Merge pull request #259 from tonicospinelli/pt_BR
add brazilian currency and translation
2016-04-29 15:11:23 +02:00
Antonio Spinelli
568186828c add brazilian currency and translation
fix #257
2016-04-29 07:30:22 -03:00
James Cole
8bcc319b7d Better demo warning and budget indication. 2016-04-29 11:34:48 +02:00
James Cole
baff9780de Smaller report. [skip ci] 2016-04-29 11:05:52 +02:00
James Cole
d8b8f98738 Translations. [skip ci] 2016-04-29 09:56:50 +02:00
James Cole
b714eaac06 Boxes will try to remember their state and auto-collapse. 2016-04-29 09:47:47 +02:00
James Cole
14b94a5bd2 Simplified some code. 2016-04-29 08:56:56 +02:00
James Cole
ea014a6504 Some code simplifications. 2016-04-28 16:30:21 +02:00
James Cole
e28e66e8f1 Fix ABN AMRO importer 2016-04-28 16:23:21 +02:00
James Cole
b47a140c2f Updates to budgets. 2016-04-28 10:59:36 +02:00
James Cole
19d7e27fa9 Code cleanup. 2016-04-28 05:50:29 +02:00
James Cole
2d368f226e Remove parameters. [skip ci] 2016-04-27 19:23:24 +02:00
James Cole
75d81f8f18 Parameter change [skip ci] 2016-04-27 19:22:15 +02:00
James Cole
e3437ba697 Various code cleanup. 2016-04-27 19:21:47 +02:00
James Cole
84f299c33b Forgot a return statement. 2016-04-27 10:39:27 +02:00
James Cole
3d4489efe6 Code cleanup. 2016-04-27 10:38:51 +02:00
James Cole
6aa50e3c00 @roberthorlings I have no idea if this is a correct fix. 2016-04-27 09:20:51 +02:00
James Cole
b70498c337 Some cleaning up. 2016-04-27 06:46:02 +02:00
James Cole
f34aa77d1d Cleaned up some code. 2016-04-27 06:43:17 +02:00
James Cole
3833a41acb Fix sorting. 2016-04-27 06:19:13 +02:00
James Cole
b5a5a216cd Fine tune chart. [skip ci] 2016-04-26 22:32:55 +02:00
James Cole
d9da2a57b6 Fix query error [skip ci] 2016-04-26 22:31:49 +02:00
James Cole
1591b61b77 Expand new charts. 2016-04-26 22:30:53 +02:00
James Cole
66f2df9677 Some code cleanup and I sneaked in a chart optimisation. 2016-04-26 22:21:34 +02:00
James Cole
5199377113 Fixes tests.. for now. 2016-04-26 21:47:16 +02:00
James Cole
da202317c0 Code cleanup. 2016-04-26 21:40:15 +02:00
James Cole
1d2a4e707e Code cleanup in export routine 2016-04-26 20:49:22 +02:00
James Cole
edf9dbc6e8 Some cleaning up [skip ci] 2016-04-26 14:56:42 +02:00
James Cole
dfbe6e5b6e Code clean up. [skip ci] 2016-04-26 12:39:29 +02:00
James Cole
d551333fa2 Some cleaning up and more charts. 2016-04-26 09:21:57 +02:00
James Cole
01cab599bb And now to make sure it works. 2016-04-26 08:11:26 +02:00
James Cole
1c8834fffb Some code cleaning up and refactoring. 2016-04-26 08:09:10 +02:00
James Cole
22e6ea700f Some extensions to budgets. 2016-04-25 21:37:08 +02:00
James Cole
7f7d6cf893 Expand query [skip ci] 2016-04-25 21:07:17 +02:00
James Cole
a94d476b75 Small additions to budget handling [skip ci] 2016-04-25 20:05:09 +02:00
James Cole
eb5e55a272 Some code cleanup. Fixes the tests. 2016-04-25 18:43:09 +02:00
James Cole
53c80aaef8 Small optimizations to reports. 2016-04-25 14:53:41 +02:00
James Cole
607d0115f0 Code improvements for budgets. 2016-04-25 13:20:42 +02:00
James Cole
b4f18dbe77 Database stuff. 2016-04-25 11:44:41 +02:00
James Cole
51d97cdca5 Reinstated a chart. 2016-04-25 09:57:39 +02:00
James Cole
2cd593157f Comment some stuff. 2016-04-25 09:50:46 +02:00
James Cole
ec70fde557 Start of some changes in budget overview related to #256 and #246 2016-04-25 09:49:34 +02:00
James Cole
950576d38b Better date format [skip ci] 2016-04-25 09:12:52 +02:00
James Cole
ce5304277d Translation for popup [skip ci] 2016-04-25 09:11:09 +02:00
James Cole
53760766a0 Fixed budget charts. 2016-04-24 20:41:12 +02:00
James Cole
ed863986a7 Fine tuning. [skip ci] 2016-04-24 20:28:08 +02:00
James Cole
89ff5a83b5 Expand cache. [skip ci] 2016-04-24 20:25:35 +02:00
James Cole
fe0b62b9b4 Cache charts. [skip ci] 2016-04-24 20:23:42 +02:00
James Cole
32c8ddbe1b First render of new budget charts. 2016-04-24 20:23:17 +02:00
James Cole
2cfbfd8649 Start of better budget charts. 2016-04-24 20:00:20 +02:00
559 changed files with 14471 additions and 12696 deletions

View File

@@ -1,5 +1,6 @@
APP_ENV=production
APP_DEBUG=false
APP_FORCE_SSL=false
APP_KEY=SomeRandomStringOf32CharsExactly
LOG_LEVEL=warning
@@ -36,6 +37,7 @@ SEND_REGISTRATION_MAIL=true
MUST_CONFIRM_ACCOUNT=false
SHOW_INCOMPLETE_TRANSLATIONS=false
SHOW_DEMO_WARNING=false
ANALYTICS_ID=
RUNCLEANUP=true

View File

@@ -1,5 +1,6 @@
APP_ENV=testing
APP_DEBUG=true
APP_FORCE_SSL=false
APP_KEY=SomeRandomStringOf32CharsExactly
LOG_LEVEL=debug

3
.gitignore vendored
View File

@@ -1,6 +1,5 @@
/vendor
/node_modules
.env
storage/
_development
.env.local

View File

@@ -4,7 +4,6 @@ php:
- 7
install:
- cp _development/phpunit.xml ./phpunit.xml
- phpenv config-rm xdebug.ini
- composer selfupdate
- rm composer.lock

View File

@@ -5,6 +5,25 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
- No unreleased changes yet.
[3.9.0]
### Added
- @zjean has added code that allows you to force "https://"-URL's.
- @tonicospinelli has added Portuguese (Brazil) translations.
- Firefly III supports the *splitting* of transactions:
- A withdrawal (expense) can be split into multiple sub-transactions (with multiple destinations)
- Likewise for deposits (incomes). You can set multiple sources.
- Likewise for transfers.
### Changed
- Update a lot of libraries.
- Big improvement to test data generation.
- Cleaned up many repositories.
### Removed
- Front page boxes will no longer respond to credit card bills.
### Fixed
- Many bugs
## [3.8.4] - 2016-04-24
### Added

View File

@@ -1,16 +1,18 @@
# Firefly III
# Firefly III [![Requires PHP7](https://img.shields.io/badge/php-7.0-red.svg)](https://secure.php.net/downloads.php#v7.0.4) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](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)
[![Requires PHP7](https://img.shields.io/badge/php-7.0-red.svg)](https://secure.php.net/downloads.php#v7.0.4)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](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)
[![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)
## A personal finances manager
## About
[![Screenshot](https://i.nder.be/hhfv03hp/400)](https://i.nder.be/hhfv03hp) [![Screenshot](https://i.nder.be/hhmwmqw9/400)](https://i.nder.be/hhmwmqw9)
"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.
[![Screenshot](https://i.nder.be/g63q05m0/400)](https://i.nder.be/g63q05m0) [![Screenshot](https://i.nder.be/c2g30ngg/400)](https://i.nder.be/c2g30ngg)
"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.
## Installation
To install Firefly III, you'll need a web server (preferrably on Linux) and access to the command line. Then, please read the [installation guide](https://jc5.github.io/firefly-iii/installation-guide/).
## More about Firefly III
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.
@@ -24,3 +26,5 @@ Firefly works on the principle that if you know where you're money is going, you
- If you feel you're missing something you can just ask me and I'll add it!
Firefly is pretty awesome. [You can read more about Firefly III, and its features, on the Github Pages](https://jc5.github.io/firefly-iii/).
If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com).

View File

@@ -1 +0,0 @@
src_dir: .

View File

@@ -1,2 +0,0 @@
--exclude-exts=.min.css
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes

View File

@@ -1 +0,0 @@
**/*{.,-}min.js

View File

@@ -1,213 +0,0 @@
ecmaFeatures:
modules: true
jsx: true
env:
amd: true
browser: true
es6: true
jquery: true
node: true
# http://eslint.org/docs/rules/
rules:
# Possible Errors
comma-dangle: [2, never]
no-cond-assign: 2
no-console: 0
no-constant-condition: 2
no-control-regex: 2
no-debugger: 2
no-dupe-args: 2
no-dupe-keys: 2
no-duplicate-case: 2
no-empty: 2
no-empty-character-class: 2
no-ex-assign: 2
no-extra-boolean-cast: 2
no-extra-parens: 0
no-extra-semi: 2
no-func-assign: 2
no-inner-declarations: [2, functions]
no-invalid-regexp: 2
no-irregular-whitespace: 2
no-negated-in-lhs: 2
no-obj-calls: 2
no-regex-spaces: 2
no-sparse-arrays: 2
no-unexpected-multiline: 2
no-unreachable: 2
use-isnan: 2
valid-jsdoc: 0
valid-typeof: 2
# Best Practices
accessor-pairs: 2
block-scoped-var: 0
complexity: [2, 6]
consistent-return: 0
curly: 0
default-case: 0
dot-location: 0
dot-notation: 0
eqeqeq: 2
guard-for-in: 2
no-alert: 2
no-caller: 2
no-case-declarations: 2
no-div-regex: 2
no-else-return: 0
no-empty-label: 2
no-empty-pattern: 2
no-eq-null: 2
no-eval: 2
no-extend-native: 2
no-extra-bind: 2
no-fallthrough: 2
no-floating-decimal: 0
no-implicit-coercion: 0
no-implied-eval: 2
no-invalid-this: 0
no-iterator: 2
no-labels: 0
no-lone-blocks: 2
no-loop-func: 2
no-magic-number: 0
no-multi-spaces: 0
no-multi-str: 0
no-native-reassign: 2
no-new-func: 2
no-new-wrappers: 2
no-new: 2
no-octal-escape: 2
no-octal: 2
no-proto: 2
no-redeclare: 2
no-return-assign: 2
no-script-url: 2
no-self-compare: 2
no-sequences: 0
no-throw-literal: 0
no-unused-expressions: 2
no-useless-call: 2
no-useless-concat: 2
no-void: 2
no-warning-comments: 0
no-with: 2
radix: 2
vars-on-top: 0
wrap-iife: 2
yoda: 0
# Strict
strict: 0
# Variables
init-declarations: 0
no-catch-shadow: 2
no-delete-var: 2
no-label-var: 2
no-shadow-restricted-names: 2
no-shadow: 0
no-undef-init: 2
no-undef: 0
no-undefined: 0
no-unused-vars: 0
no-use-before-define: 0
# Node.js and CommonJS
callback-return: 2
global-require: 2
handle-callback-err: 2
no-mixed-requires: 0
no-new-require: 0
no-path-concat: 2
no-process-exit: 2
no-restricted-modules: 0
no-sync: 0
# Stylistic Issues
array-bracket-spacing: 0
block-spacing: 0
brace-style: 0
camelcase: 0
comma-spacing: 0
comma-style: 0
computed-property-spacing: 0
consistent-this: 0
eol-last: 0
func-names: 0
func-style: 0
id-length: 0
id-match: 0
indent: 0
jsx-quotes: 0
key-spacing: 0
linebreak-style: 0
lines-around-comment: 0
max-depth: 0
max-len: 0
max-nested-callbacks: 0
max-params: 0
max-statements: [2, 30]
new-cap: 0
new-parens: 0
newline-after-var: 0
no-array-constructor: 0
no-bitwise: 0
no-continue: 0
no-inline-comments: 0
no-lonely-if: 0
no-mixed-spaces-and-tabs: 0
no-multiple-empty-lines: 0
no-negated-condition: 0
no-nested-ternary: 0
no-new-object: 0
no-plusplus: 0
no-restricted-syntax: 0
no-spaced-func: 0
no-ternary: 0
no-trailing-spaces: 0
no-underscore-dangle: 0
no-unneeded-ternary: 0
object-curly-spacing: 0
one-var: 0
operator-assignment: 0
operator-linebreak: 0
padded-blocks: 0
quote-props: 0
quotes: 0
require-jsdoc: 0
semi-spacing: 0
semi: 0
sort-vars: 0
space-after-keywords: 0
space-before-blocks: 0
space-before-function-paren: 0
space-before-keywords: 0
space-in-parens: 0
space-infix-ops: 0
space-return-throw-case: 0
space-unary-ops: 0
spaced-comment: 0
wrap-regex: 0
# ECMAScript 6
arrow-body-style: 0
arrow-parens: 0
arrow-spacing: 0
constructor-super: 0
generator-star-spacing: 0
no-arrow-condition: 0
no-class-assign: 0
no-const-assign: 0
no-dupe-class-members: 0
no-this-before-super: 0
no-var: 0
object-shorthand: 0
prefer-arrow-callback: 0
prefer-const: 0
prefer-reflect: 0
prefer-spread: 0
prefer-template: 0
require-yield: 0

View File

@@ -1,22 +0,0 @@
{
"undef": true,
"unused": false,
"strict": true,
"browser": true,
"jquery": true,
"devel": true,
"globals": [
"language",
"token",
"currencyCode",
"$",
"token",
"accountID",
"billID",
"currentMonthName",
"previousMonthName",
"nextMonthName",
"everything",
"moment"
]
}

View File

@@ -1,27 +0,0 @@
<?xml version="1.0"?>
<ruleset name="JamesStandard">
<rule ref="Zend">
<exclude name="Zend.NamingConventions.ValidVariableName" />
<exclude name="PEAR.WhiteSpace.ScopeClosingBrace" />
<!--<exclude name="PEAR.Whitespace.ScopeIndent"/>-->
<exclude name="PEAR.WhiteSpace.ScopeClosingBrace"/>
<exclude name="Generic.Formatting.MultipleStatementAlignment.Incorrect" />
<exclude name="PEAR.Functions.FunctionCallSignature" />
</rule>
<!--
Here we change two messages from the same sniff. Note how the
codes are slightly different because the sniff developer has
defined both a MaxExceeded message and a TooLong message. In the
case of this sniff, one is used for warnings and one is used
for errors.
-->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="160"/>
<property name="absoluteLineLimit" value="160"/>
</properties>
</rule>
</ruleset>

View File

@@ -1,322 +0,0 @@
<code_scheme name="Use This One">
<option name="RIGHT_MARGIN" value="160" />
<CoffeeScriptCodeStyleSettings>
<option name="SPACE_BEFORE_PROPERTY_COLON" value="true" />
</CoffeeScriptCodeStyleSettings>
<JSCodeStyleSettings>
<option name="ALIGN_MULTILINE_VAR_DECLARATION" value="true" />
</JSCodeStyleSettings>
<PHPCodeStyleSettings>
<option name="ALIGN_KEY_VALUE_PAIRS" value="true" />
<option name="ALIGN_PHPDOC_PARAM_NAMES" value="true" />
<option name="ALIGN_PHPDOC_COMMENTS" value="true" />
<option name="ALIGN_ASSIGNMENTS" value="true" />
<option name="COMMA_AFTER_LAST_ARRAY_ELEMENT" value="true" />
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
<option name="PHPDOC_BLANK_LINES_AROUND_PARAMETERS" value="true" />
<option name="PHPDOC_WRAP_LONG_LINES" value="true" />
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
<option name="LOWER_CASE_NULL_CONST" value="true" />
<option name="BLANK_LINE_BEFORE_RETURN_STATEMENT" value="true" />
<option name="KEEP_RPAREN_AND_LBRACE_ON_ONE_LINE" value="true" />
<option name="ALIGN_CLASS_CONSTANTS" value="true" />
<option name="FORCE_SHORT_DECLARATION_ARRAY_STYLE" value="true" />
</PHPCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="CoffeeScript">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
</codeStyleSettings>
<codeStyleSettings language="PHP">
<option name="RIGHT_MARGIN" value="160" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="FOR_STATEMENT_LPAREN_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_RPAREN_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<arrangement>
<tokens>
<token id="modifiers" name="modifiers">
<rules>
<rule>
<match>
<AND>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
<rule>
<match>
<AND>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
<rule>
<match>
<AND>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
<rule>
<match>
<PUBLIC>true</PUBLIC>
</match>
<order>BY_NAME</order>
</rule>
<rule>
<match>
<PROTECTED>true</PROTECTED>
</match>
<order>BY_NAME</order>
</rule>
<rule>
<match>
<PRIVATE>true</PRIVATE>
</match>
<order>BY_NAME</order>
</rule>
</rules>
</token>
<token id="visibility" name="visibility">
<rules>
<rule>
<match>
<PUBLIC>true</PUBLIC>
</match>
</rule>
<rule>
<match>
<PROTECTED>true</PROTECTED>
</match>
</rule>
<rule>
<match>
<PRIVATE>true</PRIVATE>
</match>
</rule>
</rules>
</token>
</tokens>
<groups>
<group>
<type>GETTERS_AND_SETTERS</type>
<order>KEEP</order>
</group>
</groups>
<rules>
<section>
<rule>
<match>
<CONST />
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD />
<PUBLIC />
<STATIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD />
<PROTECTED />
<STATIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD />
<PRIVATE />
<STATIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD />
<PUBLIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD />
<PROTECTED />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD />
<PRIVATE />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<CONSTRUCTOR />
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD />
<PUBLIC />
<STATIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD />
<PROTECTED />
<STATIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD />
<PRIVATE />
<STATIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD />
<PUBLIC />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD />
<PROTECTED />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD />
<PRIVATE />
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<TRAIT />
</match>
</rule>
</section>
<section>
<rule>
<match>
<INTERFACE />
</match>
</rule>
</section>
<section>
<rule>
<match>
<CLASS />
</match>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>

View File

@@ -1,63 +0,0 @@
#!/bin/bash
# set testing environment
cp .env.testing .env
# set cover:
cp phpunit.cover.xml phpunit.xml
# delete test databases:
if [ -f storage/database/testing.db ]
then
echo "Will not remove test db"
# rm storage/database/testing.db
fi
if [ -f storage/database/testing-copy.db ]
then
echo "Will not remove test db"
# rm storage/database/testing-copy.db
fi
# test!
if [ -z "$1" ]
then
echo "Running all tests..."
phpunit
fi
# test selective..
dirs=("acceptance/Controllers" "acceptance/Controllers/Auth" "acceptance/Controllers/Chart" "unit")
#
if [ ! -z "$1" ]
then
for i in "${dirs[@]}"
do
firstFile="./tests/$i/$1.php"
secondFile="./tests/$i/$1Test.php"
if [ -f "$firstFile" ]
then
# run it!
echo "Now running $firstFile"
phpunit $firstFile
result=$?
fi
if [ -f "$secondFile" ]
then
# run it!
echo "Now running $secondFile"
phpunit $secondFile
result=$?
fi
done
fi
# restore .env file
cp .env.local .env
# restore cover
cp phpunit.default.xml phpunit.xml
exit ${result}

Binary file not shown.

View File

@@ -1,16 +0,0 @@
var elixir = require('laravel-elixir');
/*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Sass
| file for our application, as well as publishing vendor resources.
|
*/
elixir(function(mix) {
mix.sass('app.scss');
});

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="pcsg-generated-ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/
</description>
<rule ref="rulesets/codesize.xml/CyclomaticComplexity">
<properties>
<property name="reportLevel" value="5"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/NPathComplexity">
<properties>
<property name="minimum" value="128"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/ExcessiveMethodLength">
<properties>
<property name="minimum" value="40"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/ExcessiveParameterList">
<properties>
<property name="minimum" value="5"/>
</properties>
</rule>
<!-- Import rule set and exclude rules -->
<rule ref="rulesets/controversial.xml">
<exclude name="CamelCasePropertyName" />
</rule>
</ruleset>

View File

@@ -1,5 +0,0 @@
suites:
main:
namespace: FireflyIII
psr4_prefix: FireflyIII
src_path: app

View File

@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ phpunit.cover.xml
~ Copyright (C) 2016 thegrumpydictator@gmail.com
~
~ This software may be modified and distributed under the terms
~ of the MIT license. See the LICENSE file for details.
-->
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">app/Http</directory>
</whitelist>
<blacklist>
<directory>vendor/</directory>
<directory>app/Console</directory>
<directory>app/Events</directory>
<directory>app/Exceptions</directory>
<directory>app/Generator</directory>
<directory>app/Handlers</directory>
<directory>app/Helpers</directory>
<directory>app/Jobs</directory>
<directory>app/Listeners</directory>
<directory>app/Models</directory>
<directory>app/Policies</directory>
<directory>app/Providers</directory>
<directory>app/Repositories</directory>
<directory>app/Rules</directory>
<directory>app/Sql</directory>
<directory>app/Support</directory>
<directory>app/Validation</directory>
<!-- and other directories, -->
</blacklist>
</filter>
<!--
Code coverage has never been slower.
-->
<logging>
<log type="coverage-clover" target="./storage/build/clover.xml" charset="UTF-8" />
</logging>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
</php>
</phpunit>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="true">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">app/</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
</php>
<listeners>
<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
</listeners>
</phpunit>

View File

@@ -1,103 +0,0 @@
#!/bin/bash
searchFile=""
deleteDatabases=false
while getopts ":nhf:" opt; do
case $opt in
n)
# echo "-n was triggered: new database!" >&2
deleteDatabases=true
;;
f)
#echo "-f was triggered: file! $OPTARG" >&2
searchFile=$OPTARG
;;
h)
echo "n: new database" >&2
echo "f: which file to run" >&2
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
# set testing environment
cp .env.testing .env
# set default phpunit.
cp phpunit.default.xml phpunit.xml
# "create" default attachment:
touch storage/upload/at-1.data
touch storage/upload/at-2.data
# delete databses:
if [ "$deleteDatabases" = true ] ; then
echo "Will delete and recreate the databases."
# delete test database:
if [ -f storage/database/testing.db ]
then
echo "Deleted testing.db"
rm storage/database/testing.db
fi
# delete test database copy:
if [ -f storage/database/testing-copy.db ]
then
echo "Delete testing-copy.db"
rm storage/database/testing-copy.db
fi
fi
# do not delete database:
if [ "$deleteDatabases" = false ] ; then
echo "Will not delete databases."
fi
# test!
if [ "$searchFile" == "" ]
then
echo "Running all tests..."
phpunit
result=$?
fi
# test selective..
dirs=("acceptance/Controllers" "acceptance/Controllers/Auth" "acceptance/Controllers/Chart" "unit")
#
if [ "$searchFile" != "" ]
then
echo "Will run test for '$searchFile'"
for i in "${dirs[@]}"
do
firstFile="./tests/$i/$searchFile.php"
secondFile="./tests/$i/"$searchFile"Test.php"
if [ -f "$firstFile" ]
then
# run it!
echo "Found file '$firstFile'"
phpunit --verbose $firstFile
result=$?
fi
if [ -f "$secondFile" ]
then
# run it!
echo "Found file '$secondFile'"
phpunit --verbose $secondFile
result=$?
fi
done
fi
# restore .env file
cp .env.local .env
exit ${result}

View File

@@ -1 +0,0 @@
These are some of the files I use for code formatting, PHPMD and PHPCS.

View File

@@ -7,11 +7,13 @@
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Bootstrap;
use Illuminate\Log\Writer;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Bootstrap\ConfigureLogging as IlluminateConfigureLogging;
use Illuminate\Log\Writer;
/**
* Class ConfigureLogging
@@ -24,20 +26,20 @@ class ConfigureLogging extends IlluminateConfigureLogging
* @param Application $app
* @param Writer $log
*/
protected function configureSingleHandler(Application $app, Writer $log)
protected function configureDailyHandler(Application $app, Writer $log)
{
$log->useFiles($app->storagePath().'/logs/firefly-iii.log');
$log->useDailyFiles(
$app->storagePath() . '/logs/firefly-iii.log',
$app->make('config')->get('app.log_max_files', 5)
);
}
/**
* @param Application $app
* @param Writer $log
*/
protected function configureDailyHandler(Application $app, Writer $log)
protected function configureSingleHandler(Application $app, Writer $log)
{
$log->useDailyFiles(
$app->storagePath().'/logs/firefly-iii.log',
$app->make('config')->get('app.log_max_files', 5)
);
$log->useFiles($app->storagePath() . '/logs/firefly-iii.log');
}
}

View File

@@ -1,9 +1,16 @@
<?php
/**
* UpgradeFireflyInstructions.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console\Commands;
use Config;
use Illuminate\Console\Command;
/**
@@ -43,8 +50,9 @@ class UpgradeFireflyInstructions extends Command
public function handle()
{
//
$version = Config::get('firefly.version');
$config = Config::get('upgrade.text');
/** @var string $version */
$version = config('firefly.version');
$config = config('upgrade.text');
$text = $config[$version] ?? null;
$this->line('+------------------------------------------------------------------------------+');

View File

@@ -1,4 +1,13 @@
<?php
/**
* VerifyDatabase.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console\Commands;
@@ -10,7 +19,6 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
@@ -39,8 +47,6 @@ class VerifyDatabase extends Command
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
@@ -72,6 +78,9 @@ class VerifyDatabase extends Command
$this->reportTransactions();
// deleted accounts that still have not deleted transactions or journals attached to them.
$this->reportDeletedAccounts();
// report on journals with no transactions at all.
$this->reportNoTransactions();
}
/**
@@ -123,7 +132,9 @@ class VerifyDatabase extends Command
::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
->distinct()
->get(['budgets.id', 'budgets.name', 'budget_transaction_journal.budget_id', 'budgets.user_id', 'users.email']);
->whereNull('budget_transaction_journal.budget_id')
->whereNull('budgets.deleted_at')
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
/** @var stdClass $entry */
foreach ($set as $entry) {
@@ -142,7 +153,9 @@ class VerifyDatabase extends Command
::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id')
->leftJoin('users', 'categories.user_id', '=', 'users.id')
->distinct()
->get(['categories.id', 'categories.name', 'category_transaction_journal.category_id', 'categories.user_id', 'users.email']);
->whereNull('category_transaction_journal.category_id')
->whereNull('categories.deleted_at')
->get(['categories.id', 'categories.name', 'categories.user_id', 'users.email']);
/** @var stdClass $entry */
foreach ($set as $entry) {
@@ -210,19 +223,39 @@ class VerifyDatabase extends Command
}
}
private function reportNoTransactions()
{
/*
* select transaction_journals.id, count(transactions.id) as transaction_count from transaction_journals
left join transactions ON transaction_journals.id = transactions.transaction_journal_id
group by transaction_journals.id
having transaction_count = 0
*/
$set = TransactionJournal
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->groupBy('transaction_journals.id')
->having('transaction_count', '=', 0)
->get(['transaction_journals.id', DB::raw('COUNT(`transactions`.`id`) as `transaction_count`')]);
foreach ($set as $entry) {
$this->error(
'Error: Journal #' . $entry->id . ' has zero transactions. Open table `transaction_journals` and delete the entry with id #' . $entry->id
);
}
}
/**
* Reports for each user when the sum of their transactions is not zero.
*/
private function reportSum()
{
/** @var UserRepositoryInterface $userRepository */
$userRepository = app('FireflyIII\Repositories\User\UserRepositoryInterface');
$userRepository = app(UserRepositoryInterface::class);
/** @var User $user */
foreach ($userRepository->all() as $user) {
/** @var AccountRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface', [$user]);
$sum = $repository->sumOfEverything();
$sum = strval($user->transactions()->sum('amount'));
if (bccomp($sum, '0') !== 0) {
$this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!');
}
@@ -238,7 +271,9 @@ class VerifyDatabase extends Command
::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')
->leftJoin('users', 'tags.user_id', '=', 'users.id')
->distinct()
->get(['tags.id', 'tags.tag', 'tag_transaction_journal.tag_id', 'tags.user_id', 'users.email']);
->whereNull('tag_transaction_journal.tag_id')
->whereNull('tags.deleted_at')
->get(['tags.id', 'tags.tag', 'tags.user_id', 'users.email']);
/** @var stdClass $entry */
foreach ($set as $entry) {

View File

@@ -1,6 +1,4 @@
<?php
declare(strict_types = 1);
/**
* Kernel.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -9,11 +7,12 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console;
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
use FireflyIII\Console\Commands\VerifyDatabase;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
/**
@@ -53,17 +52,4 @@ class Kernel extends ConsoleKernel
UpgradeFireflyInstructions::class,
VerifyDatabase::class,
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @return void
*
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*/
protected function schedule(Schedule $schedule)
{
}
}

View File

@@ -0,0 +1,421 @@
<?php
/**
* AccountCrud.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Crud\Account;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
use Log;
/**
* Class AccountCrud
*
* @package FireflyIII\Crud\Account
*/
class AccountCrud implements AccountCrudInterface
{
/** @var User */
private $user;
/** @var array */
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber'];
/**
* AccountCrud constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* @param Account $account
* @param Account $moveTo
*
* @return bool
*/
public function destroy(Account $account, Account $moveTo = null): bool
{
if (!is_null($moveTo)) {
// update all transactions:
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
}
$account->delete();
return true;
}
/**
* @param $accountId
*
* @return Account
*/
public function find(int $accountId): Account
{
$account = $this->user->accounts()->find($accountId);
if (is_null($account)) {
$account = new Account;
}
return $account;
}
/**
* @param array $accountIds
*
* @return Collection
*/
public function getAccountsById(array $accountIds): Collection
{
/** @var Collection $result */
$query = $this->user->accounts()->with(
['accountmeta' => function (HasMany $query) {
$query->where('name', 'accountRole');
}]
);
if (count($accountIds) > 0) {
$query->whereIn('accounts.id', $accountIds);
}
$result = $query->get(['accounts.*']);
$result = $result->sortBy(
function (Account $account) {
return strtolower($account->name);
}
);
return $result;
}
/**
* @param array $types
*
* @return Collection
*/
public function getAccountsByType(array $types): Collection
{
/** @var Collection $result */
$query = $this->user->accounts()->with(
['accountmeta' => function (HasMany $query) {
$query->where('name', 'accountRole');
}]
);
if (count($types) > 0) {
$query->accountTypeIn($types);
}
$result = $query->get(['accounts.*']);
$result = $result->sortBy(
function (Account $account) {
return strtolower($account->name);
}
);
return $result;
}
/**
* @param array $data
*
* @return Account
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function store(array $data): Account
{
$newAccount = $this->storeAccount($data);
if (!is_null($newAccount)) {
$this->storeMetadata($newAccount, $data);
}
// continue with the opposing account:
if ($data['openingBalance'] != 0) {
$opposingData = [
'user' => $data['user'],
'accountType' => 'initial',
'virtualBalance' => 0,
'name' => $data['name'] . ' initial balance',
'active' => false,
'iban' => '',
];
$opposing = $this->storeAccount($opposingData);
if (!is_null($opposing) && !is_null($newAccount)) {
$this->storeInitialBalance($newAccount, $opposing, $data);
}
}
return $newAccount;
}
/**
* @param $account
* @param $name
* @param $value
*
* @return AccountMeta
*/
public function storeMeta(Account $account, string $name, $value): AccountMeta
{
return AccountMeta::create(['name' => $name, 'data' => $value, 'account_id' => $account->id,]);
}
/**
* @param Account $account
* @param array $data
*
* @return Account
*/
public function update(Account $account, array $data): Account
{
// update the account:
$account->name = $data['name'];
$account->active = $data['active'] == '1' ? true : false;
$account->virtual_balance = $data['virtualBalance'];
$account->iban = $data['iban'];
$account->save();
$this->updateMetadata($account, $data);
$openingBalance = $this->openingBalanceTransaction($account);
if ($data['openingBalance'] != 0) {
if (!is_null($openingBalance->id)) {
$this->updateInitialBalance($account, $openingBalance, $data);
return $account;
}
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
$opposingData = [
'user' => $data['user'],
'accountType' => $type,
'name' => $data['name'] . ' initial balance',
'active' => false,
'iban' => '',
'virtualBalance' => 0,
];
$opposing = $this->storeAccount($opposingData);
if (!is_null($opposing)) {
$this->storeInitialBalance($account, $opposing, $data);
}
return $account;
}
if ($openingBalance) { // opening balance is zero, should we delete it?
$openingBalance->delete(); // delete existing opening balance.
}
return $account;
}
/**
* @param array $data
*
* @return Account
*/
protected function storeAccount(array $data): Account
{
$type = config('firefly.accountTypeByIdentifier.' . $data['accountType']);
$accountType = AccountType::whereType($type)->first();
$newAccount = new Account(
[
'user_id' => $data['user'],
'account_type_id' => $accountType->id,
'name' => $data['name'],
'virtual_balance' => $data['virtualBalance'],
'active' => $data['active'] === true ? true : false,
'iban' => $data['iban'],
]
);
if (!$newAccount->isValid()) {
// does the account already exist?
$searchData = [
'user_id' => $data['user'],
'account_type_id' => $accountType->id,
'virtual_balance' => $data['virtualBalance'],
'name' => $data['name'],
'iban' => $data['iban'],
];
$existingAccount = Account::firstOrNullEncrypted($searchData);
if (!$existingAccount) {
Log::error('Account create error: ' . $newAccount->getErrors()->toJson());
abort(500);
}
$newAccount = $existingAccount;
}
$newAccount->save();
return $newAccount;
}
/**
* @param Account $account
* @param Account $opposing
* @param array $data
*
* @return TransactionJournal
*/
protected function storeInitialBalance(Account $account, Account $opposing, array $data): TransactionJournal
{
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
$journal = TransactionJournal::create(
[
'user_id' => $data['user'],
'transaction_type_id' => $transactionType->id,
'bill_id' => null,
'transaction_currency_id' => $data['openingBalanceCurrency'],
'description' => 'Initial balance for "' . $account->name . '"',
'completed' => true,
'date' => $data['openingBalanceDate'],
'encrypted' => true,
]
);
$firstAccount = $account;
$secondAccount = $opposing;
$firstAmount = $data['openingBalance'];
$secondAmount = $data['openingBalance'] * -1;
if ($data['openingBalance'] < 0) {
$firstAccount = $opposing;
$secondAccount = $account;
$firstAmount = $data['openingBalance'] * -1;
$secondAmount = $data['openingBalance'];
}
$one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
$one->save();// first transaction: from
$two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]);
$two->save(); // second transaction: to
return $journal;
}
/**
* @param Account $account
* @param array $data
*/
protected function storeMetadata(Account $account, array $data)
{
foreach ($this->validFields as $field) {
if (isset($data[$field])) {
$metaData = new AccountMeta(
[
'account_id' => $account->id,
'name' => $field,
'data' => $data[$field],
]
);
$metaData->save();
}
}
}
/**
* @param Account $account
* @param TransactionJournal $journal
* @param array $data
*
* @return TransactionJournal
*/
protected function updateInitialBalance(Account $account, TransactionJournal $journal, array $data): TransactionJournal
{
$journal->date = $data['openingBalanceDate'];
$journal->save();
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if ($account->id == $transaction->account_id) {
$transaction->amount = $data['openingBalance'];
$transaction->save();
}
if ($account->id != $transaction->account_id) {
$transaction->amount = $data['openingBalance'] * -1;
$transaction->save();
}
}
return $journal;
}
/**
* @param Account $account
* @param array $data
*
*/
protected function updateMetadata(Account $account, array $data)
{
foreach ($this->validFields as $field) {
$entry = $account->accountMeta()->where('name', $field)->first();
if (isset($data[$field])) {
// update if new data is present:
if (!is_null($entry)) {
$entry->data = $data[$field];
$entry->save();
continue;
}
$metaData = new AccountMeta(
[
'account_id' => $account->id,
'name' => $field,
'data' => $data[$field],
]
);
$metaData->save();
}
}
}
/**
* @param Account $account
*
* @return TransactionJournal|null
*/
private function openingBalanceTransaction(Account $account): TransactionJournal
{
$journal = TransactionJournal
::sortCorrectly()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)
->transactionTypes([TransactionType::OPENING_BALANCE])
->first(['transaction_journals.*']);
if (is_null($journal)) {
return new TransactionJournal;
}
return $journal;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* AccountCrudInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Crud\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use Illuminate\Support\Collection;
/**
* Interface AccountCrudInterface
*
* @package FireflyIII\Crud\Account
*/
interface AccountCrudInterface
{
/**
* @param Account $account
* @param Account $moveTo
*
* @return bool
*/
public function destroy(Account $account, Account $moveTo): bool;
/**
* @param int $accountId
*
* @return Account
*/
public function find(int $accountId): Account;
/**
* @param array $accountIds
*
* @return Collection
*/
public function getAccountsById(array $accountIds): Collection;
/**
* @param array $types
*
* @return Collection
*/
public function getAccountsByType(array $types): Collection;
/**
* @param array $data
*
* @return Account
*/
public function store(array $data) : Account;
/**
* @param $account
* @param $name
* @param $value
*
* @return AccountMeta
*/
public function storeMeta(Account $account, string $name, $value): AccountMeta;
/**
* @param Account $account
* @param array $data
*
* @return Account
*/
public function update(Account $account, array $data): Account;
}

218
app/Crud/Split/Journal.php Normal file
View File

@@ -0,0 +1,218 @@
<?php
/**
* Journal.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Crud\Split;
use FireflyIII\Events\TransactionStored;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
* Class Journal
*
* @package FireflyIII\Crud\Split
*/
class Journal implements JournalInterface
{
/** @var User */
private $user;
/**
* AttachmentRepository constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* @param $journal
*
* @return bool
*/
public function markAsComplete(TransactionJournal $journal)
{
$journal->completed = 1;
$journal->save();
return true;
}
/**
* @param TransactionJournal $journal
* @param array $transaction
*
* @return Collection
*/
public function storeTransaction(TransactionJournal $journal, array $transaction): Collection
{
// store accounts (depends on type)
list($sourceAccount, $destinationAccount) = $this->storeAccounts($journal->transactionType->type, $transaction);
// store transaction one way:
/** @var Transaction $one */
$one = Transaction::create(
['account_id' => $sourceAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $transaction['amount'] * -1,
'description' => $transaction['description']]
);
$two = Transaction::create(
['account_id' => $destinationAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $transaction['amount'],
'description' => $transaction['description']]
);
if (strlen($transaction['category']) > 0) {
$category = Category::firstOrCreateEncrypted(['name' => $transaction['category'], 'user_id' => $journal->user_id]);
$one->categories()->save($category);
$two->categories()->save($category);
}
if (intval($transaction['budget_id']) > 0) {
$budget = Budget::find($transaction['budget_id']);
$one->budgets()->save($budget);
$two->budgets()->save($budget);
}
if ($transaction['piggy_bank_id'] > 0) {
$transaction['date'] = $journal->date->format('Y-m-d');
event(new TransactionStored($transaction));
}
return new Collection([$one, $two]);
}
/**
* @param TransactionJournal $journal
* @param array $data
*
* @return TransactionJournal
*/
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal
{
echo '<pre>';
print_r($data);
$journal->description = $data['journal_description'];
$journal->transaction_currency_id = $data['journal_currency_id'];
$journal->date = $data['date'];
$journal->interest_date = $data['interest_date'];
$journal->book_date = $data['book_date'];
$journal->process_date = $data['process_date'];
$journal->save();
// delete original transactions, and recreate them.
$journal->transactions()->delete();
foreach ($data['transactions'] as $transaction) {
$this->storeTransaction($journal, $transaction);
}
$journal->completed = true;
$journal->save();
return $journal;
}
/**
* @param string $type
* @param array $transaction
*
* @return array
* @throws FireflyException
*/
private function storeAccounts(string $type, array $transaction): array
{
$sourceAccount = null;
$destinationAccount = null;
switch ($type) {
case TransactionType::WITHDRAWAL:
list($sourceAccount, $destinationAccount) = $this->storeWithdrawalAccounts($transaction);
break;
case TransactionType::DEPOSIT:
list($sourceAccount, $destinationAccount) = $this->storeDepositAccounts($transaction);
break;
case TransactionType::TRANSFER:
$sourceAccount = Account::where('user_id', $this->user->id)->where('id', $transaction['source_account_id'])->first();
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $transaction['destination_account_id'])->first();
break;
default:
throw new FireflyException('Cannot handle ' . e($type));
}
return [$sourceAccount, $destinationAccount];
}
/**
* @param array $data
*
* @return array
*/
private function storeDepositAccounts(array $data): array
{
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']);
if (strlen($data['source_account_name']) > 0) {
$sourceType = AccountType::where('type', 'Revenue account')->first();
$sourceAccount = Account::firstOrCreateEncrypted(
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1]
);
return [$sourceAccount, $destinationAccount];
}
$sourceType = AccountType::where('type', 'Cash account')->first();
$sourceAccount = Account::firstOrCreateEncrypted(
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1]
);
return [$sourceAccount, $destinationAccount];
}
/**
* @param array $data
*
* @return array
*/
private function storeWithdrawalAccounts(array $data): array
{
$sourceAccount = Account::where('user_id', $this->user->id)->where('id', $data['source_account_id'])->first(['accounts.*']);
if (strlen($data['destination_account_name']) > 0) {
$destinationType = AccountType::where('type', 'Expense account')->first();
$destinationAccount = Account::firstOrCreateEncrypted(
[
'user_id' => $this->user->id,
'account_type_id' => $destinationType->id,
'name' => $data['destination_account_name'],
'active' => 1,
]
);
return [$sourceAccount, $destinationAccount];
}
$destinationType = AccountType::where('type', 'Cash account')->first();
$destinationAccount = Account::firstOrCreateEncrypted(
['user_id' => $this->user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1]
);
return [$sourceAccount, $destinationAccount];
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* JournalInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Crud\Split;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
/**
* Interface JournalInterface
*
* @package FireflyIII\Crud\Split
*/
interface JournalInterface
{
/**
* @param $journal
*
* @return bool
*/
public function markAsComplete(TransactionJournal $journal);
/**
* @param TransactionJournal $journal
* @param array $transaction
*
* @return Collection
*/
public function storeTransaction(TransactionJournal $journal, array $transaction): Collection;
/**
* @param TransactionJournal $journal
* @param array $data
*
* @return TransactionJournal
*/
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal;
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* BudgetLimitStored.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Carbon\Carbon;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class BudgetLimitStored
*
* @package FireflyIII\Events
*/
class BudgetLimitStored extends Event
{
use SerializesModels;
/** @var BudgetLimit */
public $budgetLimit;
/** @var Carbon */
public $end; // the only variable we can't get from the budget limit (if necessary).
/**
* BudgetLimitEvents constructor.
*
* @param BudgetLimit $budgetLimit
* @param Carbon $end
*/
public function __construct(BudgetLimit $budgetLimit, Carbon $end)
{
//
$this->budgetLimit = $budgetLimit;
$this->end = $end;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* BudgetLimitUpdated.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Carbon\Carbon;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class BudgetLimitUpdated
*
* @package FireflyIII\Events
*/
class BudgetLimitUpdated extends Event
{
use SerializesModels;
/** @var BudgetLimit */
public $budgetLimit;
/** @var Carbon */
public $end; // the only variable we can't get from the budget limit (if necessary).
/**
* BudgetLimitEvents constructor.
*
* @param BudgetLimit $budgetLimit
* @param Carbon $end
*/
public function __construct(BudgetLimit $budgetLimit, Carbon $end)
{
//
$this->budgetLimit = $budgetLimit;
$this->end = $end;
}
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* Event.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* ResendConfirmation.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use FireflyIII\User;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* TransactionJournalStored.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,11 +7,12 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
use Log;
/**
* Class TransactionJournalStored
@@ -35,7 +35,6 @@ class TransactionJournalStored extends Event
*/
public function __construct(TransactionJournal $journal, int $piggyBankId)
{
Log::debug('Created new TransactionJournalStored.');
//
$this->journal = $journal;
$this->piggyBankId = $piggyBankId;

View File

@@ -1,11 +1,18 @@
<?php
/**
* TransactionJournalUpdated.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
use Log;
/**
* Class TransactionJournalUpdated
@@ -26,7 +33,6 @@ class TransactionJournalUpdated extends Event
*/
public function __construct(TransactionJournal $journal)
{
Log::debug('Created new TransactionJournalUpdated');
//
$this->journal = $journal;
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* TransactionStored.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
/**
* Class TransactionJournalStored
*
* @package FireflyIII\Events
*/
class TransactionStored extends Event
{
use SerializesModels;
public $transaction = [];
/**
* Create a new event instance.
*
* @param array $transaction
*/
public function __construct(array $transaction)
{
//
$this->transaction = $transaction;
}
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* UserRegistration.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use FireflyIII\User;

View File

@@ -1,4 +1,12 @@
<?php
/**
* FireflyException.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Exceptions;

View File

@@ -1,4 +1,12 @@
<?php
/**
* Handler.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Exceptions;
@@ -6,7 +14,6 @@ use Auth;
use ErrorException;
use Exception;
use FireflyIII\Jobs\MailError;
use FireflyIII\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@@ -66,9 +73,14 @@ class Handler extends ExceptionHandler
{
if ($exception instanceof FireflyException || $exception instanceof ErrorException) {
$user = Auth::check() ? Auth::user() : new User;
$userData = [
'id' => 0,
'email' => 'unknown@example.com',
];
if (Auth::check()) {
$userData['id'] = Auth::user()->id;
$userData['email'] = Auth::user()->email;
}
$data = [
'class' => get_class($exception),
'errorMessage' => $exception->getMessage(),
@@ -80,7 +92,7 @@ class Handler extends ExceptionHandler
];
// create job that will mail.
$job = new MailError($user, env('SITE_OWNER'), Request::ip(), $data);
$job = new MailError($userData, env('SITE_OWNER'), Request::ip(), $data);
dispatch($job);
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* NotImplementedException.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Exceptions;

View File

@@ -1,4 +1,12 @@
<?php
/**
* ValidationException.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Exceptions;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* AttachmentCollector.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Collector;
use Amount;
@@ -44,7 +45,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
*/
public function __construct(ExportJob $job)
{
$this->repository = app('FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface');
/** @var AttachmentRepositoryInterface repository */
$this->repository = app(AttachmentRepositoryInterface::class);
// make storage:
$this->uploadDisk = Storage::disk('upload');
$this->exportDisk = Storage::disk('export');
@@ -68,8 +70,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
// put the explanation string in a file and attach it as well.
$file = $this->job->key . '-Source of all your attachments explained.txt';
$this->exportDisk->put($file, $this->explanationString);
Log::debug('Also put explanation file "' . $file . '" in the zip.');
$this->getFiles()->push($file);
return true;
}
@@ -102,14 +104,12 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
private function exportAttachment(Attachment $attachment): bool
{
$file = $attachment->fileName();
Log::debug('Original file is at "' . $file . '".');
if ($this->uploadDisk->exists($file)) {
try {
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
$exportFile = $this->exportFileName($attachment);
$this->exportDisk->put($exportFile, $decrypted);
$this->getFiles()->push($exportFile);
Log::debug('Stored file content in new file "' . $exportFile . '", which will be in the final zip file.');
// explain:
$this->explain($attachment);
@@ -142,8 +142,6 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
{
$attachments = $this->repository->get();
Log::debug('Found ' . $attachments->count() . ' attachments.');
return $attachments;
}
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* BasicCollector.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Collector;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* CollectorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Collector;
use Illuminate\Support\Collection;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* UploadCollector.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Collector;
use Auth;
@@ -53,11 +54,11 @@ class UploadCollector extends BasicCollector implements CollectorInterface
{
// grab upload directory.
$files = $this->uploadDisk->files();
Log::debug('Found ' . count($files) . ' files in the upload directory.');
foreach ($files as $entry) {
$this->processOldUpload($entry);
}
return true;
}
@@ -85,11 +86,9 @@ class UploadCollector extends BasicCollector implements CollectorInterface
{
$len = strlen($this->expected);
if (substr($entry, 0, $len) === $this->expected) {
Log::debug($entry . ' is part of this users original uploads.');
return true;
}
Log::debug($entry . ' is not part of this users original uploads.');
return false;
}
@@ -112,7 +111,6 @@ class UploadCollector extends BasicCollector implements CollectorInterface
// continue with file:
$date = $this->getOriginalUploadDate($entry);
$file = $this->job->key . '-Old CSV import dated ' . $date . '.csv';
Log::debug('Will put "' . $file . '" in the zip file.');
$this->exportDisk->put($file, $content);
$this->getFiles()->push($file);
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* ConfigurationFile.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,10 +7,12 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Models\ExportJob;
use Log;
use Storage;
/**
@@ -42,8 +43,8 @@ class ConfigurationFile
*/
public function make(): string
{
$fields = array_keys(get_class_vars(Entry::class));
$types = Entry::getTypes();
$fields = array_keys(Entry::getFieldsAndTypes());
$types = Entry::getFieldsAndTypes();
$configuration = [
'date-format' => 'Y-m-d', // unfortunately, this is hard-coded.
@@ -57,8 +58,6 @@ class ConfigurationFile
$configuration['roles'][] = $types[$field];
}
$file = $this->job->key . '-configuration.json';
Log::debug('Created JSON config file.');
Log::debug('Will put "' . $file . '" in the ZIP file.');
$this->exportDisk->put($file, json_encode($configuration, JSON_PRETTY_PRINT));
return $file;

View File

@@ -1,463 +0,0 @@
<?php
declare(strict_types = 1);
/**
* Entry.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Export;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionJournal;
/**
* To extend the exported object, in case of new features in Firefly III for example,
* do the following:
*
* - Add the field(s) to this class
* - Make sure the "fromJournal"-routine fills these fields.
* - Add them to the static function that returns its type (key=value. Remember that the only
* valid types can be found in config/csv.php (under "roles").
*
* These new entries should be should be strings and numbers as much as possible.
*
*
*
* Class Entry
*
* @package FireflyIII\Export
*/
class Entry
{
/** @var string */
public $amount;
/** @var int */
public $billId;
/** @var string */
public $billName;
/** @var int */
public $budgetId;
/** @var string */
public $budgetName;
/** @var int */
public $categoryId;
/** @var string */
public $categoryName;
/** @var string */
public $date;
/** @var string */
public $description;
/** @var string */
public $fromAccountIban;
/** @var int */
public $fromAccountId;
/** @var string */
public $fromAccountName;
/** @var int */
public $fromAccountNumber;
/** @var string */
public $fromAccountType;
/** @var string */
public $toAccountIban;
/** @var int */
public $toAccountId;
/** @var string */
public $toAccountName;
public $toAccountNumber;
/** @var string */
public $toAccountType;
/**
* @param TransactionJournal $journal
*
* @return Entry
*/
public static function fromJournal(TransactionJournal $journal)
{
$entry = new self;
$entry->setDescription($journal->description);
$entry->setDate($journal->date->format('Y-m-d'));
$entry->setAmount(TransactionJournal::amount($journal));
/** @var Budget $budget */
$budget = $journal->budgets->first();
if (!is_null($budget)) {
$entry->setBudgetId($budget->id);
$entry->setBudgetName($budget->name);
}
/** @var Category $category */
$category = $journal->categories->first();
if (!is_null($category)) {
$entry->setCategoryId($category->id);
$entry->setCategoryName($category->name);
}
if (!is_null($journal->bill_id)) {
$entry->setBillId($journal->bill_id);
$entry->setBillName($journal->bill->name);
}
/** @var Account $sourceAccount */
$sourceAccount = TransactionJournal::sourceAccount($journal);
$entry->setFromAccountId($sourceAccount->id);
$entry->setFromAccountName($sourceAccount->name);
$entry->setFromAccountIban($sourceAccount->iban);
$entry->setFromAccountType($sourceAccount->accountType->type);
$entry->setFromAccountNumber($sourceAccount->getMeta('accountNumber'));
/** @var Account $destination */
$destination = TransactionJournal::destinationAccount($journal);
$entry->setToAccountId($destination->id);
$entry->setToAccountName($destination->name);
$entry->setToAccountIban($destination->iban);
$entry->setToAccountType($destination->accountType->type);
$entry->setToAccountNumber($destination->getMeta('accountNumber'));
return $entry;
}
/**
* @return array
*/
public static function getTypes(): array
{
// key = field name (see top of class)
// value = field type (see csv.php under 'roles')
return [
'amount' => 'amount',
'date' => 'date-transaction',
'description' => 'description',
'billId' => 'bill-id',
'billName' => 'bill-name',
'budgetId' => 'budget-id',
'budgetName' => 'budget-name',
'categoryId' => 'category-id',
'categoryName' => 'category-name',
'fromAccountId' => 'account-id',
'fromAccountNumber' => 'account-number',
'fromAccountName' => 'account-name',
'fromAccountIban' => 'account-iban',
'fromAccountType' => '_ignore', // no, Firefly cannot import what it exports. I know :D
'toAccountId' => 'opposing-id',
'toAccountNumber' => 'account-number',
'toAccountName' => 'opposing-name',
'toAccountIban' => 'opposing-iban',
'toAccountType' => '_ignore',
];
}
/**
* @return string
*/
public function getAmount(): string
{
return $this->amount;
}
/**
* @param string $amount
*/
public function setAmount(string $amount)
{
$this->amount = $amount;
}
/**
* @return int
*/
public function getBillId(): int
{
return $this->billId;
}
/**
* @param int $billId
*/
public function setBillId(int $billId)
{
$this->billId = $billId;
}
/**
* @return string
*/
public function getBillName(): string
{
return $this->billName;
}
/**
* @param string $billName
*/
public function setBillName(string $billName)
{
$this->billName = $billName;
}
/**
* @return int
*/
public function getBudgetId(): int
{
return $this->budgetId;
}
/**
* @param int $budgetId
*/
public function setBudgetId(int $budgetId)
{
$this->budgetId = $budgetId;
}
/**
* @return string
*/
public function getBudgetName(): string
{
return $this->budgetName;
}
/**
* @param string $budgetName
*/
public function setBudgetName(string $budgetName)
{
$this->budgetName = $budgetName;
}
/**
* @return int
*/
public function getCategoryId(): int
{
return $this->categoryId;
}
/**
* @param int $categoryId
*/
public function setCategoryId(int $categoryId)
{
$this->categoryId = $categoryId;
}
/**
* @return string
*/
public function getCategoryName(): string
{
return $this->categoryName;
}
/**
* @param string $categoryName
*/
public function setCategoryName(string $categoryName)
{
$this->categoryName = $categoryName;
}
/**
* @return string
*/
public function getDate(): string
{
return $this->date;
}
/**
* @param string $date
*/
public function setDate(string $date)
{
$this->date = $date;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @param string $description
*/
public function setDescription(string $description)
{
$this->description = $description;
}
/**
* @return string
*/
public function getFromAccountIban(): string
{
return $this->fromAccountIban;
}
/**
* @param string $fromAccountIban
*/
public function setFromAccountIban(string $fromAccountIban)
{
$this->fromAccountIban = $fromAccountIban;
}
/**
* @return int
*/
public function getFromAccountId():int
{
return $this->fromAccountId;
}
/**
* @param int $fromAccountId
*/
public function setFromAccountId(int $fromAccountId)
{
$this->fromAccountId = $fromAccountId;
}
/**
* @return string
*/
public function getFromAccountName(): string
{
return $this->fromAccountName;
}
/**
* @param string $fromAccountName
*/
public function setFromAccountName(string $fromAccountName)
{
$this->fromAccountName = $fromAccountName;
}
/**
* @return string
*/
public function getFromAccountNumber(): string
{
return $this->fromAccountNumber;
}
/**
* @param string $fromAccountNumber
*/
public function setFromAccountNumber(string $fromAccountNumber)
{
$this->fromAccountNumber = $fromAccountNumber;
}
/**
* @return string
*/
public function getFromAccountType(): string
{
return $this->fromAccountType;
}
/**
* @param string $fromAccountType
*/
public function setFromAccountType(string $fromAccountType)
{
$this->fromAccountType = $fromAccountType;
}
/**
* @return string
*/
public function getToAccountIban(): string
{
return $this->toAccountIban;
}
/**
* @param string $toAccountIban
*/
public function setToAccountIban(string $toAccountIban)
{
$this->toAccountIban = $toAccountIban;
}
/**
* @return int
*/
public function getToAccountId(): int
{
return $this->toAccountId;
}
/**
* @param int $toAccountId
*/
public function setToAccountId(int $toAccountId)
{
$this->toAccountId = $toAccountId;
}
/**
* @return string
*/
public function getToAccountName(): string
{
return $this->toAccountName;
}
/**
* @param string $toAccountName
*/
public function setToAccountName(string $toAccountName)
{
$this->toAccountName = $toAccountName;
}
/**
* @return string
*/
public function getToAccountNumber(): string
{
return $this->toAccountNumber;
}
/**
* @param string $toAccountNumber
*/
public function setToAccountNumber(string $toAccountNumber)
{
$this->toAccountNumber = $toAccountNumber;
}
/**
* @return string
*/
public function getToAccountType(): string
{
return $this->toAccountType;
}
/**
* @param string $toAccountType
*/
public function setToAccountType(string $toAccountType)
{
$this->toAccountType = $toAccountType;
}
}

130
app/Export/Entry/Entry.php Normal file
View File

@@ -0,0 +1,130 @@
<?php
/**
* Entry.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
/**
* To extend the exported object, in case of new features in Firefly III for example,
* do the following:
*
* - Add the field(s) to this class. If you add more than one related field, add a new object.
* - Make sure the "fromJournal"-routine fills these fields.
* - Add them to the static function that returns its type (key=value. Remember that the only
* valid types can be found in config/csv.php (under "roles").
*
* These new entries should be should be strings and numbers as much as possible.
*
*
*
* Class Entry
*
* @package FireflyIII\Export\Entry
*/
final class Entry
{
/** @var string */
public $amount;
/** @var EntryBill */
public $bill;
/** @var EntryBudget */
public $budget;
/** @var EntryCategory */
public $category;
/** @var string */
public $date;
/** @var string */
public $description;
/** @var EntryAccount */
public $destinationAccount;
/** @var Collection */
public $destinationAccounts;
/** @var EntryAccount */
public $sourceAccount;
/** @var Collection */
public $sourceAccounts;
/**
* Entry constructor.
*/
private function __construct()
{
$this->sourceAccounts = new Collection;
$this->destinationAccounts = new Collection;
}
/**
* @param TransactionJournal $journal
*
* @return Entry
*/
public static function fromJournal(TransactionJournal $journal)
{
$entry = new self;
$entry->description = $journal->description;
$entry->date = $journal->date->format('Y-m-d');
$entry->amount = TransactionJournal::amount($journal);
$entry->budget = new EntryBudget($journal->budgets->first());
$entry->category = new EntryCategory($journal->categories->first());
$entry->bill = new EntryBill($journal->bill);
$sources = TransactionJournal::sourceAccountList($journal);
$destinations = TransactionJournal::destinationAccountList($journal);
$entry->sourceAccount = new EntryAccount($sources->first());
$entry->destinationAccount = new EntryAccount($destinations->first());
foreach ($sources as $source) {
$entry->sourceAccounts->push(new EntryAccount($source));
}
foreach ($destinations as $destination) {
$entry->destinationAccounts->push(new EntryAccount($destination));
}
return $entry;
}
/**
* @return array
*/
public static function getFieldsAndTypes(): array
{
// key = field name (see top of class)
// value = field type (see csv.php under 'roles')
return [
'description' => 'description',
'amount' => 'amount',
'date' => 'date-transaction',
'source_account_id' => 'account-id',
'source_account_name' => 'account-name',
'source_account_iban' => 'account-iban',
'source_account_type' => '_ignore',
'source_account_number' => 'account-number',
'destination_account_id' => 'opposing-id',
'destination_account_name' => 'opposing-name',
'destination_account_iban' => 'opposing-iban',
'destination_account_type' => '_ignore',
'destination_account_number' => 'account-number',
'budget_id' => 'budget-id',
'budget_name' => 'budget-name',
'category_id' => 'category-id',
'category_name' => 'category-name',
'bill_id' => 'bill-id',
'bill_name' => 'bill-name',
];
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* EntryAccount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\Account;
/**
* Class EntryAccount
*
* @package FireflyIII\Export\Entry
*/
class EntryAccount
{
/** @var int */
public $accountId;
/** @var string */
public $iban;
/** @var string */
public $name;
/** @var string */
public $number;
/** @var string */
public $type;
/**
* EntryAccount constructor.
*
* @param Account $account
*/
public function __construct(Account $account)
{
$this->accountId = $account->id;
$this->name = $account->name;
$this->iban = $account->iban;
$this->type = $account->accountType->type;
$this->number = $account->getMeta('accountNumber');
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* EntryBill.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\Bill;
/**
* Class EntryBill
*
* @package FireflyIII\Export\Entry
*/
class EntryBill
{
/** @var int */
public $billId = '';
/** @var string */
public $name = '';
/**
* EntryBill constructor.
*
* @param Bill $bill
*/
public function __construct(Bill $bill = null)
{
if (!is_null($bill)) {
$this->billId = $bill->id;
$this->name = $bill->name;
}
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* EntryBudget.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\Budget;
/**
* Class EntryBudget
*
* @package FireflyIII\Export\Entry
*/
class EntryBudget
{
/** @var int */
public $budgetId = '';
/** @var string */
public $name = '';
/**
* EntryBudget constructor.
*
* @param Budget $budget
*/
public function __construct(Budget $budget = null)
{
if (!is_null($budget)) {
$this->budgetId = $budget->id;
$this->name = $budget->name;
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* EntryCategory.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\Category;
/**
* Class EntryCategory
*
* @package FireflyIII\Export\Entry
*/
class EntryCategory
{
/** @var int */
public $categoryId = '';
/** @var string */
public $name = '';
/**
* EntryCategory constructor.
*
* @param Category $category
*/
public function __construct(Category $category = null)
{
if (!is_null($category)) {
$this->categoryId = $category->id;
$this->name = $category->name;
}
}
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* BasicExporter.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Exporter;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* CsvExporter.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,10 +7,14 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Exporter;
use FireflyIII\Export\Entry;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Export\Entry\EntryAccount;
use FireflyIII\Models\ExportJob;
use Illuminate\Support\Collection;
use League\Csv\Writer;
use SplFileObject;
@@ -54,27 +57,114 @@ class CsvExporter extends BasicExporter implements ExporterInterface
// necessary for CSV writer:
$fullPath = storage_path('export') . DIRECTORY_SEPARATOR . $this->fileName;
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
$rows = [];
// create CSV writer:
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
// all rows:
$rows = [];
// add header:
$first = $this->getEntries()->first();
$rows[] = array_keys(get_object_vars($first));
// then the rest:
// Count the maximum number of sources and destinations each entry has. May need to expand the number of export fields:
$maxSourceAccounts = 1;
$maxDestAccounts = 1;
/** @var Entry $entry */
foreach ($this->getEntries() as $entry) {
$rows[] = array_values(get_object_vars($entry));
$sources = $entry->sourceAccounts->count();
$destinations = $entry->destinationAccounts->count();
$maxSourceAccounts = max($maxSourceAccounts, $sources);
$maxDestAccounts = max($maxDestAccounts, $destinations);
}
$rows[] = array_keys($this->getFieldsAndTypes($maxSourceAccounts, $maxDestAccounts));
/** @var Entry $entry */
foreach ($this->getEntries() as $entry) {
// order is defined in Entry::getFieldsAndTypes.
$current = [$entry->description, $entry->amount, $entry->date];
$sourceData = $this->getAccountData($maxSourceAccounts, $entry->sourceAccounts);
$current = array_merge($current, $sourceData);
$destData = $this->getAccountData($maxDestAccounts, $entry->destinationAccounts);
$current = array_merge($current, $destData);
$rest = [$entry->budget->budgetId, $entry->budget->name, $entry->category->categoryId, $entry->category->name, $entry->bill->billId,
$entry->bill->name];
$current = array_merge($current, $rest);
$rows[] = $current;
}
$writer->insertAll($rows);
return true;
}
/**
* @param int $max
* @param Collection $accounts
*
* @return array
*/
private function getAccountData(int $max, Collection $accounts): array
{
$current = [];
for ($i = 0; $i < $max; $i++) {
/** @var EntryAccount $source */
$source = $accounts->get($i);
$currentId = '';
$currentName = '';
$currentIban = '';
$currentType = '';
$currentNumber = '';
if ($source) {
$currentId = $source->accountId;
$currentName = $source->name;
$currentIban = $source->iban;
$currentType = $source->type;
$currentNumber = $source->number;
}
$current[] = $currentId;
$current[] = $currentName;
$current[] = $currentIban;
$current[] = $currentType;
$current[] = $currentNumber;
}
unset($source);
return $current;
}
/**
* @param int $sources
* @param int $destinations
*
* @return array
*/
private function getFieldsAndTypes(int $sources, int $destinations): array
{
// key = field name (see top of class)
// value = field type (see csv.php under 'roles')
$array = [
'description' => 'description',
'amount' => 'amount',
'date' => 'date-transaction',
];
for ($i = 0; $i < $sources; $i++) {
$array['source_account_' . $i . '_id'] = 'account-id';
$array['source_account_' . $i . '_name'] = 'account-name';
$array['source_account_' . $i . '_iban'] = 'account-iban';
$array['source_account_' . $i . '_type'] = '_ignore';
$array['source_account_' . $i . '_number'] = 'account-number';
}
for ($i = 0; $i < $destinations; $i++) {
$array['destination_account_' . $i . '_id'] = 'account-id';
$array['destination_account_' . $i . '_name'] = 'account-name';
$array['destination_account_' . $i . '_iban'] = 'account-iban';
$array['destination_account_' . $i . '_type'] = '_ignore';
$array['destination_account_' . $i . '_number'] = 'account-number';
}
$array['budget_id'] = 'budget-id';
$array['budget_name'] = 'budget-name';
$array['category_id'] = 'category-id';
$array['category_name'] = 'category-name';
$array['bill_id'] = 'bill-id';
$array['bill_name'] = 'bill-name';
return $array;
}
private function tempFile()
{
$this->fileName = $this->job->key . '-records.csv';

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* ExporterInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Exporter;
use Illuminate\Support\Collection;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* Processor.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,16 +7,19 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export;
use Auth;
use Config;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Export\Collector\AttachmentCollector;
use FireflyIII\Export\Collector\UploadCollector;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Models\ExportJob;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalCollector;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Collection;
use Log;
use Storage;
use ZipArchive;
@@ -78,9 +80,11 @@ class Processor
*/
public function collectAttachments(): bool
{
$attachmentCollector = app('FireflyIII\Export\Collector\AttachmentCollector', [$this->job]);
/** @var AttachmentCollector $attachmentCollector */
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
$attachmentCollector->run();
$this->files = $this->files->merge($attachmentCollector->getFiles());
return true;
}
@@ -89,17 +93,10 @@ class Processor
*/
public function collectJournals(): bool
{
$args = [$this->accounts, Auth::user(), $this->settings['startDate'], $this->settings['endDate']];
/** @var JournalCollector $journalCollector */
$journalCollector = app('FireflyIII\Repositories\Journal\JournalCollector', $args);
$this->journals = $journalCollector->collect();
Log::debug(
'Collected ' .
$this->journals->count() . ' journals (between ' .
$this->settings['startDate']->format('Y-m-d') . ' and ' .
$this->settings['endDate']->format('Y-m-d')
. ').'
);
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$this->journals = $repository->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
return true;
}
@@ -108,10 +105,12 @@ class Processor
*/
public function collectOldUploads(): bool
{
$uploadCollector = app('FireflyIII\Export\Collector\UploadCollector', [$this->job]);
/** @var UploadCollector $uploadCollector */
$uploadCollector = app(UploadCollector::class, [$this->job]);
$uploadCollector->run();
$this->files = $this->files->merge($uploadCollector->getFiles());
return true;
}
@@ -126,7 +125,7 @@ class Processor
$this->exportEntries->push(Entry::fromJournal($journal));
$count++;
}
Log::debug('Converted ' . $count . ' journals to "Entry" objects.');
return true;
}
@@ -135,8 +134,9 @@ class Processor
*/
public function createConfigFile(): bool
{
$this->configurationMaker = app('FireflyIII\Export\ConfigurationFile', [$this->job]);
$this->configurationMaker = app(ConfigurationFile::class, [$this->job]);
$this->files->push($this->configurationMaker->make());
return true;
}
@@ -149,7 +149,6 @@ class Processor
$zip = new ZipArchive;
$file = $this->job->key . '.zip';
$fullPath = storage_path('export') . '/' . $file;
Log::debug('Will create zip file at ' . $fullPath);
if ($zip->open($fullPath, ZipArchive::CREATE) !== true) {
throw new FireflyException('Cannot store zip file.');
@@ -159,20 +158,14 @@ class Processor
foreach ($this->getFiles() as $entry) {
// is part of this job?
$zipFileName = str_replace($this->job->key . '-', '', $entry);
$result = $zip->addFromString($zipFileName, $disk->get($entry));
if (!$result) {
Log::error('Could not add "' . $entry . '" into zip file as "' . $zipFileName . '".');
}
$zip->addFromString($zipFileName, $disk->get($entry));
}
$zip->close();
// delete the files:
foreach ($this->getFiles() as $file) {
Log::debug('Will now delete file "' . $file . '".');
$disk->delete($file);
}
Log::debug('Done!');
$this->deleteFiles($disk);
return true;
}
@@ -181,13 +174,12 @@ class Processor
*/
public function exportJournals(): bool
{
$exporterClass = Config::get('firefly.export_formats.' . $this->exportFormat);
$exporterClass = config('firefly.export_formats.' . $this->exportFormat);
$exporter = app($exporterClass, [$this->job]);
Log::debug('Going to export ' . $this->exportEntries->count() . ' export entries into ' . $this->exportFormat . ' format.');
$exporter->setEntries($this->exportEntries);
$exporter->run();
$this->files->push($exporter->getFileName());
Log::debug('Added "' . $exporter->getFileName() . '" to the list of files to include in the zip.');
return true;
}
@@ -198,4 +190,14 @@ class Processor
{
return $this->files;
}
/**
* @param FilesystemAdapter $disk
*/
private function deleteFiles(FilesystemAdapter $disk)
{
foreach ($this->getFiles() as $file) {
$disk->delete($file);
}
}
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* AccountChartGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
@@ -42,10 +43,10 @@ interface AccountChartGeneratorInterface
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
* @param array $labels
* @param array $dataSet
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end): array;
public function single(Account $account, array $labels, array $dataSet): array;
}

View File

@@ -1,11 +1,18 @@
<?php
/**
* ChartJsAccountChartGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
use Steam;
/**
* Class ChartJsAccountChartGenerator
@@ -29,28 +36,6 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
'labels' => [], 'datasets' => [[
'label' => trans('firefly.spent'),
'data' => []]]];
$start->subDay();
$ids = $this->getIdsFromCollection($accounts);
$startBalances = Steam::balancesById($ids, $start);
$endBalances = Steam::balancesById($ids, $end);
$accounts->each(
function (Account $account) use ($startBalances, $endBalances) {
$id = $account->id;
$startBalance = $this->isInArray($startBalances, $id);
$endBalance = $this->isInArray($endBalances, $id);
$diff = bcsub($endBalance, $startBalance);
$account->difference = round($diff, 2);
}
);
$accounts = $accounts->sortByDesc(
function (Account $account) {
return $account->difference;
}
);
foreach ($accounts as $account) {
if ($account->difference > 0) {
$data['labels'][] = $account->name;
@@ -80,7 +65,7 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
}
foreach ($accounts as $account) {
$set = [
$data['datasets'][] = [
'label' => $account->name,
'fillColor' => 'rgba(220,220,220,0.2)',
'strokeColor' => 'rgba(220,220,220,1)',
@@ -88,20 +73,8 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
'pointStrokeColor' => '#fff',
'pointHighlightFill' => '#fff',
'pointHighlightStroke' => 'rgba(220,220,220,1)',
'data' => [],
'data' => $account->balances,
];
$current = clone $start;
$range = Steam::balanceInRange($account, $start, clone $end);
$previous = round(array_values($range)[0], 2);
while ($current <= $end) {
$format = $current->format('Y-m-d');
$balance = isset($range[$format]) ? round($range[$format], 2) : $previous;
$set['data'][] = $balance;
$previous = $balance;
$current->addDay();
}
$data['datasets'][] = $set;
}
$data['count'] = count($data['datasets']);
@@ -110,71 +83,25 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
* @param array $labels
* @param array $dataSet
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end): array
public function single(Account $account, array $labels, array $dataSet): array
{
// language:
$format = (string)trans('config.month_and_day');
$data = [
$data = [
'count' => 1,
'labels' => [],
'labels' => $labels,
'datasets' => [
[
'label' => $account->name,
'data' => [],
'data' => $dataSet,
],
],
];
$range = Steam::balanceInRange($account, $start, $end);
$current = clone $start;
$previous = array_values($range)[0];
while ($end >= $current) {
$theDate = $current->format('Y-m-d');
$balance = $range[$theDate] ?? $previous;
$data['labels'][] = $current->formatLocalized($format);
$data['datasets'][0]['data'][] = $balance;
$previous = $balance;
$current->addDay();
}
return $data;
}
/**
* @param Collection $collection
*
* @return array
*/
protected function getIdsFromCollection(Collection $collection): array
{
$ids = [];
foreach ($collection as $entry) {
$ids[] = $entry->id;
}
return array_unique($ids);
}
/**
* @param $array
* @param $entryId
*
* @return string
*/
protected function isInArray($array, $entryId): string
{
if (isset($array[$entryId])) {
return $array[$entryId];
}
return '0';
}
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* BillChartGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Bill;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* ChartJsBillChartGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Bill;
use FireflyIII\Models\Bill;
@@ -54,11 +55,7 @@ class ChartJsBillChartGenerator implements BillChartGeneratorInterface
public function single(Bill $bill, Collection $entries): array
{
$format = (string)trans('config.month');
$data = [
'count' => 3,
'labels' => [],
'datasets' => [],
];
$data = ['count' => 3, 'labels' => [], 'datasets' => [],];
$minAmount = [];
$maxAmount = [];
$actualAmount = [];
@@ -67,9 +64,7 @@ class ChartJsBillChartGenerator implements BillChartGeneratorInterface
$data['labels'][] = $entry->date->formatLocalized($format);
$minAmount[] = round($bill->amount_min, 2);
$maxAmount[] = round($bill->amount_max, 2);
/*
* journalAmount has been collected in BillRepository::getJournals
*/
// journalAmount has been collected in BillRepository::getJournals
$actualAmount[] = round(TransactionJournal::amountPositive($entry), 2);
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* BudgetChartGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Budget;
use Illuminate\Support\Collection;
@@ -19,19 +20,14 @@ use Illuminate\Support\Collection;
*/
interface BudgetChartGeneratorInterface
{
/**
* @param Collection $entries
*
* @return array
*/
public function budget(Collection $entries): array;
/**
* @param Collection $entries
* @param string $dateFormat
*
* @return array
*/
public function budgetLimit(Collection $entries): array;
public function budgetLimit(Collection $entries, string $dateFormat): array;
/**
* @param Collection $entries
@@ -47,6 +43,14 @@ interface BudgetChartGeneratorInterface
*/
public function multiYear(Collection $entries): array;
/**
* @param Collection $entries
* @param string $viewRange
*
* @return array
*/
public function period(Collection $entries, string $viewRange) : array;
/**
* @param Collection $budgets
* @param Collection $entries

View File

@@ -1,11 +1,18 @@
<?php
/**
* ChartJsBudgetChartGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Budget;
use Config;
use Illuminate\Support\Collection;
use Preferences;
use Navigation;
/**
* Class ChartJsBudgetChartGenerator
@@ -14,20 +21,17 @@ use Preferences;
*/
class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
{
/**
*
* @param Collection $entries
* @param string $dateFormat
*
* @return array
*/
public function budget(Collection $entries, $dateFormat = 'month'): array
public function budgetLimit(Collection $entries, string $dateFormat = 'month_and_day'): array
{
// language:
$language = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data;
$format = Config::get('firefly.' . $dateFormat . '.' . $language);
$data = [
$format = strval(trans('config.' . $dateFormat));
$data = [
'labels' => [],
'datasets' => [
[
@@ -49,17 +53,6 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
return $data;
}
/**
*
* @param Collection $entries
*
* @return array
*/
public function budgetLimit(Collection $entries): array
{
return $this->budget($entries, 'monthAndDay');
}
/**
* @param Collection $entries
*
@@ -139,6 +132,42 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
}
/**
* @param Collection $entries
* @param string $viewRange
*
* @return array
*/
public function period(Collection $entries, string $viewRange) : array
{
$data = [
'labels' => [],
'datasets' => [
0 => [
'label' => trans('firefly.budgeted'),
'data' => [],
],
1 => [
'label' => trans('firefly.spent'),
'data' => [],
],
],
'count' => 2,
];
foreach ($entries as $entry) {
$label = Navigation::periodShow($entry['date'], $viewRange);
$data['labels'][] = $label;
// data set 0 is budgeted
// data set 1 is spent:
$data['datasets'][0]['data'][] = $entry['budgeted'];
$data['datasets'][1]['data'][] = round(($entry['spent'] * -1), 2);
}
return $data;
}
/**
* @param Collection $budgets
* @param Collection $entries

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* CategoryChartGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Category;
use Illuminate\Support\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* ChartJsCategoryChartGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Category;
@@ -20,8 +28,6 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface
*/
public function all(Collection $entries): array
{
$data = [
'count' => 2,
'labels' => [],
@@ -42,8 +48,8 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface
$spent = $entry[2];
$earned = $entry[3];
$data['datasets'][0]['data'][] = bccomp($spent, '0') === 0 ? null : bcmul($spent, '-1');
$data['datasets'][1]['data'][] = bccomp($earned, '0') === 0 ? null : $earned;
$data['datasets'][0]['data'][] = bccomp($spent, '0') === 0 ? null : round(bcmul($spent, '-1'), 4);
$data['datasets'][1]['data'][] = bccomp($earned, '0') === 0 ? null : round($earned, 4);
}
return $data;
@@ -116,18 +122,9 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface
*/
public function multiYear(Collection $entries): array
{
// dataset:
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
// get labels from one of the categories (assuming there's at least one):
$first = $entries->first();
$keys = array_keys($first['spent']);
foreach ($keys as $year) {
$data['labels'][] = strval($year);
}
$data = ['count' => 0, 'labels' => array_keys($first['spent']), 'datasets' => [],];
// then, loop all entries and create datasets:
foreach ($entries as $entry) {
@@ -144,7 +141,6 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface
$data['count'] = count($data['datasets']);
return $data;
}
/**

View File

@@ -1,4 +1,12 @@
<?php
/**
* ChartJsPiggyBankChartGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\PiggyBank;
@@ -36,9 +44,9 @@ class ChartJsPiggyBankChartGenerator implements PiggyBankChartGeneratorInterface
],
];
$sum = '0';
foreach ($set as $entry) {
$date = new Carbon($entry->date);
$sum = bcadd($sum, $entry->sum);
foreach ($set as $key => $value) {
$date = new Carbon($key);
$sum = bcadd($sum, $value);
$data['labels'][] = $date->formatLocalized($format);
$data['datasets'][0]['data'][] = round($sum, 2);
}

View File

@@ -1,13 +1,14 @@
<?php
declare(strict_types = 1);
/**
* PiggyBankChartGenerator.php
* PiggyBankChartGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\PiggyBank;
use Illuminate\Support\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* ChartJsReportChartGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Report;

View File

@@ -1,13 +1,14 @@
<?php
declare(strict_types = 1);
/**
* ReportChartGenerator.php
* ReportChartGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Report;
use Illuminate\Support\Collection;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* AttachUserRole.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,12 +7,13 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\UserRegistration;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Log;
/**
* Class AttachUserRole
@@ -38,13 +38,11 @@ class AttachUserRole
*/
public function handle(UserRegistration $event)
{
Log::debug('Trigger attachuserrole');
/** @var UserRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\User\UserRepositoryInterface');
$repository = app(UserRepositoryInterface::class);
// first user ever?
if ($repository->count() == 1) {
Log::debug('Will attach role.');
$repository->attachRole($event->user, 'owner');
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* BudgetLimitEventHandler.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\BudgetLimitStored;
use FireflyIII\Events\BudgetLimitUpdated;
use FireflyIII\Models\LimitRepetition;
use Illuminate\Database\QueryException;
use Log;
/**
* Class BudgetLimitEventHandler
*
* @package FireflyIII\Handlers\Events
*/
class BudgetLimitEventHandler
{
/**
* Create the event listener.
*
*/
public function __construct()
{
}
/**
* In a perfect world, the store() routine should be different from the update()
* routine. It would not have to check count() == 0 because there could be NO
* limit repetitions at this point. However, the database can be wrong so we check.
*
* @param BudgetLimitStored $event
*/
public function store(BudgetLimitStored $event)
{
$budgetLimit = $event->budgetLimit;
$end = $event->end;
$set = $budgetLimit->limitrepetitions()
->where('startdate', $budgetLimit->startdate->format('Y-m-d 00:00:00'))
->where('enddate', $end->format('Y-m-d 00:00:00'))
->get();
if ($set->count() == 0) {
$repetition = new LimitRepetition;
$repetition->startdate = $budgetLimit->startdate;
$repetition->enddate = $end;
$repetition->amount = $budgetLimit->amount;
$repetition->budgetLimit()->associate($budgetLimit);
try {
$repetition->save();
} catch (QueryException $e) {
Log::error('Trying to save new LimitRepetition failed: ' . $e->getMessage());
}
}
if ($set->count() == 1) {
$repetition = $set->first();
$repetition->amount = $budgetLimit->amount;
$repetition->save();
}
}
/**
* @param BudgetLimitUpdated $event
*/
public function update(BudgetLimitUpdated $event)
{
$budgetLimit = $event->budgetLimit;
$end = $event->end;
$set = $budgetLimit->limitrepetitions()
->where('startdate', $budgetLimit->startdate->format('Y-m-d 00:00:00'))
->where('enddate', $end->format('Y-m-d 00:00:00'))
->get();
if ($set->count() == 0) {
$repetition = new LimitRepetition;
$repetition->startdate = $budgetLimit->startdate;
$repetition->enddate = $end;
$repetition->amount = $budgetLimit->amount;
$repetition->budgetLimit()->associate($budgetLimit);
try {
$repetition->save();
} catch (QueryException $e) {
Log::error('Trying to save new LimitRepetition failed: ' . $e->getMessage());
}
}
if ($set->count() == 1) {
$repetition = $set->first();
$repetition->amount = $budgetLimit->amount;
$repetition->save();
}
}
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* ConnectJournalToPiggyBank.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
@@ -44,7 +52,8 @@ class ConnectJournalToPiggyBank
$amount = TransactionJournal::amountPositive($journal);
// if piggy account matches source account, the amount is positive
if ($piggyBank->account_id == TransactionJournal::sourceAccount($journal)->id) {
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
if (in_array($piggyBank->account_id, $sources)) {
$amount = bcmul($amount, '-1');
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* ConnectTransactionToPiggyBank.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\TransactionStored;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
/**
* Class ConnectTransactionToPiggyBank
*
* @package FireflyIII\Handlers\Events
*/
class ConnectTransactionToPiggyBank
{
/**
* Connect a new transaction journal to any related piggy banks.
*
* @param TransactionStored $event
*
* @return bool
*/
public function handle(TransactionStored $event): bool
{
echo '<pre>';
/** @var PiggyBankRepositoryInterface $repository */
$repository = app(PiggyBankRepositoryInterface::class);
$transaction = $event->transaction;
$piggyBank = $repository->find($transaction['piggy_bank_id']);
// valid piggy:
if (is_null($piggyBank->id)) {
return true;
}
$amount = strval($transaction['amount']);
// piggy bank account something with amount:
if ($transaction['source_account_id'] == $piggyBank->account_id) {
// if the source of this transaction is the same as the piggy bank,
// the money is being removed from the piggy bank. So the
// amount must be negative:
$amount = bcmul($amount, '-1');
}
$repetition = $piggyBank->currentRelevantRep();
// add or remove the money from the piggy bank:
$newAmount = bcadd(strval($repetition->currentamount), $amount);
$repetition->currentamount = $newAmount;
$repetition->save();
// now generate a piggy bank event:
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'date' => $transaction['date'], 'amount' => $newAmount]);
return true;
}
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* FireRulesForStore.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
@@ -17,7 +18,6 @@ use FireflyIII\Models\RuleGroup;
use FireflyIII\Rules\Processor;
use FireflyIII\User;
use Illuminate\Support\Facades\Auth;
use Log;
/**
* Class FireRulesForStore
@@ -36,7 +36,6 @@ class FireRulesForStore
*/
public function handle(TransactionJournalStored $event): bool
{
Log::debug('Now running FireRulesForStore because TransactionJournalStored fired.');
// get all the user's rule groups, with the rules, order by 'order'.
/** @var User $user */
$user = Auth::user();
@@ -44,7 +43,6 @@ class FireRulesForStore
//
/** @var RuleGroup $group */
foreach ($groups as $group) {
Log::debug('Now processing group "' . $group->title . '".');
$rules = $group->rules()
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
->where('rule_triggers.trigger_type', 'user_action')
@@ -54,7 +52,6 @@ class FireRulesForStore
/** @var Rule $rule */
foreach ($rules as $rule) {
Log::debug('Now handling rule #' . $rule->id . ' (' . $rule->title . ')');
$processor = Processor::make($rule);
$processor->handleTransactionJournal($event->journal);

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* FireRulesForUpdate.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use Auth;
@@ -16,7 +17,6 @@ use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Rules\Processor;
use FireflyIII\User;
use Log;
/**
* Class FireRulesForUpdate
@@ -34,7 +34,6 @@ class FireRulesForUpdate
*/
public function handle(TransactionJournalUpdated $event): bool
{
Log::debug('Now running FireRulesForUpdate because TransactionJournalUpdated fired.');
// get all the user's rule groups, with the rules, order by 'order'.
/** @var User $user */
$user = Auth::user();
@@ -42,7 +41,6 @@ class FireRulesForUpdate
//
/** @var RuleGroup $group */
foreach ($groups as $group) {
Log::debug('Now processing group "' . $group->title . '".');
$rules = $group->rules()
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
->where('rule_triggers.trigger_type', 'user_action')
@@ -51,9 +49,6 @@ class FireRulesForUpdate
->get(['rules.*']);
/** @var Rule $rule */
foreach ($rules as $rule) {
Log::debug('Now handling rule #' . $rule->id . ' (' . $rule->title . ')');
Log::debug('Now handling rule #' . $rule->id . ' (' . $rule->title . ')');
$processor = Processor::make($rule);
$processor->handleTransactionJournal($event->journal);

View File

@@ -1,13 +1,14 @@
<?php
declare(strict_types = 1);
/**
* RescanJournalAfterStore.php
* ScanForBillsAfterStore.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\TransactionJournalStored;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* ScanForBillsAfterUpdate.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\TransactionJournalUpdated;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* SendRegistrationMail.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
@@ -60,6 +61,7 @@ class SendRegistrationMail
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* UpdateJournalConnection.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* UserConfirmation.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
@@ -47,6 +48,7 @@ class UserConfirmation
$user = $event->user;
$ipAddress = $event->ipAddress;
$this->doConfirm($user, $ipAddress);
return true;
}
@@ -62,6 +64,7 @@ class UserConfirmation
$user = $event->user;
$ipAddress = $event->ipAddress;
$this->doConfirm($user, $ipAddress);
return true;
}
@@ -71,35 +74,21 @@ class UserConfirmation
*/
private function doConfirm(User $user, string $ipAddress)
{
Log::debug('Trigger UserConfirmation::doConfirm');
// if user must confirm account, send email
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
// otherwise, auto-confirm:
if ($confirmAccount === false) {
Log::debug('Confirm account is false, so user will be auto-confirmed.');
Preferences::setForUser($user, 'user_confirmed', true);
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
Preferences::mark();
return;
}
// send email message:
$email = $user->email;
$code = str_random(16);
$route = route('do_confirm_account', [$code]);
// set preferences:
Preferences::setForUser($user, 'user_confirmed', false);
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
Preferences::setForUser($user, 'user_confirmed_code', $code);
Log::debug('Set preferences for user.');
// send email.
try {
Log::debug('Now in try block for user email message thing to ' . $email . '.');
Mail::send(
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
function (Message $message) use ($email) {
@@ -107,13 +96,10 @@ class UserConfirmation
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
} catch (Exception $e) {
Log::debug('Caught general exception.');
Log::error($e->getMessage());
}
Log::debug('Finished mail handling for activation.');
return;
}

View File

@@ -1,5 +1,4 @@
<?php
declare(strict_types = 1);
/**
* UserEventListener.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -8,6 +7,8 @@ declare(strict_types = 1);
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use Session;
@@ -21,7 +22,7 @@ class UserEventListener
{
/**
* Handle user logout events.
*
*
* @return bool
*/
public function onUserLogout(): bool

View File

@@ -1,9 +1,16 @@
<?php
/**
* AttachmentHelper.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Attachments;
use Auth;
use Config;
use Crypt;
use FireflyIII\Models\Attachment;
use Illuminate\Database\Eloquent\Model;
@@ -39,8 +46,8 @@ class AttachmentHelper implements AttachmentHelperInterface
*/
public function __construct()
{
$this->maxUploadSize = Config::get('firefly.maxUploadSize');
$this->allowedMimes = Config::get('firefly.allowedMimes');
$this->maxUploadSize = config('firefly.maxUploadSize');
$this->allowedMimes = config('firefly.allowedMimes');
$this->errors = new MessageBag;
$this->messages = new MessageBag;
$this->uploadDisk = Storage::disk('upload');
@@ -81,26 +88,14 @@ class AttachmentHelper implements AttachmentHelperInterface
*/
public function saveAttachmentsForModel(Model $model): bool
{
$files = null;
try {
if (Input::hasFile('attachments')) {
$files = Input::file('attachments');
}
} catch (TypeError $e) {
// Log it, do nothing else.
Log::error($e->getMessage());
$files = $this->getFiles();
if (!is_null($files) && !is_array($files)) {
$this->processFile($files, $model);
}
if (is_array($files)) {
foreach ($files as $entry) {
if (!is_null($entry)) {
$this->processFile($entry, $model);
}
}
} else {
if (!is_null($files)) {
$this->processFile($files, $model);
}
$this->processFiles($files, $model);
}
return true;
@@ -234,5 +229,39 @@ class AttachmentHelper implements AttachmentHelperInterface
return true;
}
/**
* @return array|null|UploadedFile
*/
private function getFiles()
{
$files = null;
try {
if (Input::hasFile('attachments')) {
$files = Input::file('attachments');
}
} catch (TypeError $e) {
// Log it, do nothing else.
Log::error($e->getMessage());
}
return $files;
}
/**
* @param array $files
*
* @return bool
*/
private function processFiles(array $files, Model $model): bool
{
foreach ($files as $entry) {
if (!is_null($entry)) {
$this->processFile($entry, $model);
}
}
return true;
}
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* AttachmentHelperInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Attachments;

View File

@@ -1,4 +1,12 @@
<?php
/**
* Account.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* Balance.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
@@ -59,5 +67,13 @@ class Balance
return $this->balanceLines;
}
/**
* @param Collection $balanceLines
*/
public function setBalanceLines(Collection $balanceLines)
{
$this->balanceLines = $balanceLines;
}
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* BalanceEntry.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* BalanceHeader.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,7 +1,16 @@
<?php
/**
* BalanceLine.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
use Carbon\Carbon;
use FireflyIII\Models\Budget as BudgetModel;
use Illuminate\Support\Collection;
@@ -24,6 +33,11 @@ class BalanceLine
/** @var BudgetModel */
protected $budget;
/** @var Carbon */
protected $startDate;
/** @var Carbon */
protected $endDate;
/** @var int */
protected $role = self::ROLE_DEFAULTROLE;
@@ -113,6 +127,39 @@ class BalanceLine
return '';
}
/**
* @return Carbon
*/
public function getStartDate()
{
return $this->startDate;
}
/**
* @param Carbon $startDate
*/
public function setStartDate($startDate)
{
$this->startDate = $startDate;
}
/**
* @return Carbon
*/
public function getEndDate()
{
return $this->endDate;
}
/**
* @param Carbon $endDate
*/
public function setEndDate($endDate)
{
$this->endDate = $endDate;
}
/**
* 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

View File

@@ -1,4 +1,12 @@
<?php
/**
* Bill.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* BillLine.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
@@ -141,5 +149,4 @@ class BillLine
$this->hit = $hit;
}
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* Budget.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* BudgetLine.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,4 +1,12 @@
<?php
/**
* Category.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;

View File

@@ -1,8 +1,15 @@
<?php
/**
* Expense.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
use Crypt;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use stdClass;
@@ -33,26 +40,32 @@ class Expense
*/
public function addOrCreateExpense(TransactionJournal $entry)
{
// add each account individually:
$destinations = TransactionJournal::destinationTransactionList($entry);
$accountId = $entry->account_id;
$amount = strval(round($entry->journalAmount, 2));
if (bccomp('0', $amount) === -1) {
$amount = bcmul($amount, '-1');
foreach ($destinations as $transaction) {
$amount = strval($transaction->amount);
$account = $transaction->account;
if (bccomp('0', $amount) === -1) {
$amount = bcmul($amount, '-1');
}
$object = new stdClass;
$object->amount = $amount;
$object->name = $account->name;
$object->count = 1;
$object->id = $account->id;
// overrule some properties:
if ($this->expenses->has($account->id)) {
$object = $this->expenses->get($account->id);
$object->amount = bcadd($object->amount, $amount);
$object->count++;
}
$this->expenses->put($account->id, $object);
}
if (!$this->expenses->has($accountId)) {
$newObject = new stdClass;
$newObject->amount = $amount;
$newObject->name = Crypt::decrypt($entry->account_name);
$newObject->count = 1;
$newObject->id = $accountId;
$this->expenses->put($accountId, $newObject);
} else {
$existing = $this->expenses->get($accountId);
$existing->amount = bcadd($existing->amount, $amount);
$existing->count++;
$this->expenses->put($accountId, $existing);
}
}
/**
@@ -60,8 +73,6 @@ class Expense
*/
public function addToTotal(string $add)
{
$add = strval(round($add, 2));
if (bccomp('0', $add) === -1) {
$add = bcmul($add, '-1');

View File

@@ -1,8 +1,15 @@
<?php
/**
* Income.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
use Crypt;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use stdClass;
@@ -34,21 +41,29 @@ class Income
*/
public function addOrCreateIncome(TransactionJournal $entry)
{
// add each account individually:
$sources = TransactionJournal::sourceTransactionList($entry);
$accountId = $entry->account_id;
if (!$this->incomes->has($accountId)) {
$newObject = new stdClass;
$newObject->amount = strval(round($entry->journalAmount, 2));
$newObject->name = Crypt::decrypt($entry->account_name);
$newObject->count = 1;
$newObject->id = $accountId;
$this->incomes->put($accountId, $newObject);
} else {
$existing = $this->incomes->get($accountId);
$existing->amount = bcadd($existing->amount, $entry->journalAmount);
$existing->count++;
$this->incomes->put($accountId, $existing);
foreach ($sources as $transaction) {
$amount = strval($transaction->amount);
$account = $transaction->account;
$amount = bcmul($amount, '-1');
$object = new stdClass;
$object->amount = $amount;
$object->name = $account->name;
$object->count = 1;
$object->id = $account->id;
// overrule some properties:
if ($this->incomes->has($account->id)) {
$object = $this->incomes->get($account->id);
$object->amount = bcadd($object->amount, $amount);
$object->count++;
}
$this->incomes->put($account->id, $object);
}
}
/**

View File

@@ -1,9 +1,16 @@
<?php
/**
* AccountId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
/**
* Class AccountId
@@ -18,17 +25,10 @@ class AccountId extends BasicConverter implements ConverterInterface
*/
public function convert(): Account
{
/** @var AccountRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
/** @var Account $account */
$account = $repository->find($this->mapped[$this->index][$this->value]);
} else {
/** @var Account $account */
$account = $repository->find($this->value);
}
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
$var = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$account = $crud->find($var);
return $account;
}

View File

@@ -1,4 +1,12 @@
<?php
/**
* Amount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;

View File

@@ -1,4 +1,12 @@
<?php
/**
* AmountComma.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;

View File

@@ -1,12 +1,20 @@
<?php
/**
* AssetAccountIban.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use Carbon\Carbon;
use FireflyIII\Crud\Account\AccountCrudInterface;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Log;
use FireflyIII\Models\AccountType;
/**
* Class AssetAccountIban
@@ -21,52 +29,61 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface
*/
public function convert(): Account
{
/** @var AccountRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
$account = $repository->find(intval($this->mapped[$this->index][$this->value]));
Log::debug('Found mapped account for value "' . $this->value . '". It is account #' . $account->id);
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
return $account;
}
if (strlen($this->value) > 0) {
// find or create new account:
$set = $repository->getAccounts(['Default account', 'Asset account']);
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->iban == $this->value) {
Log::debug('Found an account with the same IBAN ("' . $this->value . '"). It is account #' . $entry->id);
return $entry;
}
}
Log::debug('Found no account with the same IBAN ("' . $this->value . '"), so will create a new one.');
// create it if doesn't exist.
$accountData = [
'name' => $this->value,
'accountType' => 'asset',
'virtualBalance' => 0,
'virtualBalanceCurrency' => 1, // hard coded.
'active' => true,
'user' => Auth::user()->id,
'iban' => $this->value,
'accountNumber' => $this->value,
'accountRole' => null,
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $repository->store($accountData);
$account = $this->searchOrCreate($crud);
return $account;
}
return new Account;
}
/**
* @param AccountCrudInterface $crud
*
* @return Account
*/
private function searchOrCreate(AccountCrudInterface $crud)
{
// find or create new account:
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->iban == $this->value) {
return $entry;
}
}
// create it if doesn't exist.
$accountData = [
'name' => $this->value,
'accountType' => 'asset',
'virtualBalance' => 0,
'virtualBalanceCurrency' => 1, // hard coded.
'active' => true,
'user' => Auth::user()->id,
'iban' => $this->value,
'accountNumber' => $this->value,
'accountRole' => null,
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $crud->store($accountData);
return $account;
}
}

View File

@@ -1,11 +1,19 @@
<?php
/**
* AssetAccountName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Models\AccountType;
/**
* Class AssetAccountName
@@ -20,27 +28,21 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
*/
public function convert(): Account
{
/** @var AccountRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
$account = $repository->find(intval($this->mapped[$this->index][$this->value]));
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
return $account;
}
// find or create new account:
$set = $repository->getAccounts(['Default account', 'Asset account']);
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->name == $this->value) {
return $entry;
}
}
// create it if doesnt exist.
$accountData = [
'name' => $this->value,
'accountType' => 'asset',
@@ -54,10 +56,9 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $repository->store($accountData);
$account = $crud->store($accountData);
return $account;
}

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