Compare commits

..

1145 Commits
4.0.0 ... 4.3.0

Author SHA1 Message Date
James Cole
ad1e9c27e9 Merge branch 'release/4.3.0' 2016-12-26 10:46:22 +01:00
James Cole
ab761696bf New version indicator. 2016-12-26 10:45:45 +01:00
James Cole
0713273a99 New composer file. 2016-12-26 10:45:19 +01:00
James Cole
5668a3271b Updated change log. 2016-12-26 10:40:28 +01:00
James Cole
1eca105a91 Merge pull request #494 from JC5/l10n_develop
New Crowdin translations
2016-12-26 10:34:00 +01:00
James Cole
3883b99c24 New translations 2016-12-26 10:31:51 +01:00
James Cole
d6adbc697a New translations 2016-12-26 10:31:49 +01:00
James Cole
a5789b1085 New translations 2016-12-26 10:31:48 +01:00
James Cole
a6ccbcb795 New translations 2016-12-26 10:31:47 +01:00
James Cole
1a6067f7ae New translations 2016-12-26 10:31:46 +01:00
James Cole
cb735b18a9 New translations 2016-12-26 10:31:45 +01:00
James Cole
909bd11147 New translations 2016-12-26 10:31:42 +01:00
James Cole
1a76c606ed New translations 2016-12-26 10:31:41 +01:00
James Cole
8c9b6796a1 Approved. Step name: Proofread 2016-12-26 10:31:38 +01:00
James Cole
844ab608d4 More demo text [skip ci] 2016-12-26 10:23:47 +01:00
James Cole
dc39094975 New translations 2016-12-26 10:12:11 +01:00
James Cole
b32184d525 New translations 2016-12-26 10:12:09 +01:00
James Cole
d95ae53ce2 New translations 2016-12-26 10:12:07 +01:00
James Cole
5e3147ddeb New translations 2016-12-26 10:12:06 +01:00
James Cole
9e594c6075 New translations 2016-12-26 10:12:04 +01:00
James Cole
c0058c51ea New translations 2016-12-26 10:12:03 +01:00
James Cole
b0b68d4243 New translations 2016-12-26 10:12:00 +01:00
James Cole
22eb90212d New translations 2016-12-26 10:11:59 +01:00
James Cole
94e264b6ce Expand demo text [skip ci] 2016-12-26 10:00:40 +01:00
James Cole
7ea15761a6 Fix tests. 2016-12-26 09:50:37 +01:00
James Cole
1ced4a089d Update read me [skip ci] 2016-12-26 09:50:28 +01:00
James Cole
648e63628c Extra code for demo site. 2016-12-26 09:33:52 +01:00
James Cole
2847e2aff5 Code for the demo features. 2016-12-26 09:18:45 +01:00
James Cole
9dfaabb5d0 New translations 2016-12-26 09:12:28 +01:00
James Cole
6a21f98ea4 New translations 2016-12-26 09:12:22 +01:00
James Cole
4d5f4cc1c0 New translations 2016-12-26 09:12:14 +01:00
James Cole
970ce6cb0d New translations 2016-12-26 09:12:10 +01:00
James Cole
31cad5de00 New translations 2016-12-26 09:12:05 +01:00
James Cole
e06db9e620 New translations 2016-12-26 09:11:59 +01:00
James Cole
f57ac64dc2 New translations 2016-12-26 09:11:54 +01:00
James Cole
57d7c1623f New translations 2016-12-26 09:11:36 +01:00
James Cole
c86aa9cb3f Can no longer reset the demo user’s password. 2016-12-26 09:08:59 +01:00
James Cole
48209d0d22 Demo user cannot enable two factor auth. 2016-12-26 08:57:07 +01:00
James Cole
8f6a271cc0 Add the ability to prefix cache differently. 2016-12-25 13:38:30 +01:00
James Cole
a9b610f367 New translations 2016-12-25 13:12:12 +01:00
James Cole
1046930f29 New translations 2016-12-25 13:12:00 +01:00
James Cole
1b16e5e216 New translations 2016-12-25 13:11:56 +01:00
James Cole
e16ba9ac70 New translations 2016-12-25 13:11:53 +01:00
James Cole
71ac676b83 New translations 2016-12-25 13:11:47 +01:00
James Cole
1b6c0d5d86 New translations 2016-12-25 13:11:43 +01:00
James Cole
14db016e98 New translations 2016-12-25 13:11:27 +01:00
James Cole
7e2e1626ac Approved. Step name: Proofread 2016-12-25 13:11:15 +01:00
James Cole
bce4e7e2bf Add restrictions for demo accounts. 2016-12-25 13:09:29 +01:00
James Cole
ede327f3d3 Merge pull request #493 from JC5/l10n_develop
New Crowdin translations
2016-12-25 12:59:27 +01:00
James Cole
82718a74dc Fix tests 2016-12-25 12:55:22 +01:00
James Cole
eefd6141a1 Translated 2016-12-25 12:31:05 +01:00
James Cole
7894f1871e Make sure the attachment tests work. 2016-12-25 12:23:36 +01:00
James Cole
0ef9b5b462 Make sure database is present in tests. 2016-12-25 12:06:17 +01:00
James Cole
9ca75d134e This is the test database required to run the tests. 2016-12-25 12:03:21 +01:00
James Cole
b78776e1f7 This generates a lot of logging, let’s remove it. 2016-12-25 11:52:01 +01:00
James Cole
f2f9f8fbab Various bug fixes and extensions to test routine. 2016-12-25 11:50:42 +01:00
James Cole
5b5acba816 Clean up lots of models. 2016-12-24 17:36:51 +01:00
James Cole
9f2729d0ff Removed Firefly’s ability to generate test data. 2016-12-24 14:48:14 +01:00
James Cole
afe98cda9f Various code cleanup things and preparation for a new demo user. 2016-12-24 14:43:42 +01:00
James Cole
9c4d2e8791 Mention $other in chart cache. [skip ci] 2016-12-23 18:48:21 +01:00
James Cole
cea170359f Budget chart. 2016-12-23 18:34:58 +01:00
James Cole
70bb8fbc89 New translations 2016-12-23 17:53:16 +01:00
James Cole
82cd0adca6 New translations 2016-12-23 17:52:57 +01:00
James Cole
e821f5b2b6 New translations 2016-12-23 17:52:51 +01:00
James Cole
4cade467c6 New translations 2016-12-23 17:52:46 +01:00
James Cole
b6c9639948 New translations 2016-12-23 17:52:39 +01:00
James Cole
ca9319db34 New translations 2016-12-23 17:52:33 +01:00
James Cole
beaec9a4c1 New translations 2016-12-23 17:52:11 +01:00
James Cole
cbc44e8200 Approved. Step name: Proofread 2016-12-23 17:51:54 +01:00
James Cole
017b1a481a Committed bad code. 2016-12-23 17:51:33 +01:00
James Cole
e15932fe4a Make budget report actually more useful. 2016-12-23 17:50:26 +01:00
James Cole
08c044fe52 Merge pull request #491 from JC5/l10n_develop
New Crowdin translations
2016-12-23 15:52:34 +01:00
James Cole
0e11245cb4 Fix tests. 2016-12-23 15:52:12 +01:00
James Cole
cde494d3ef Fixed missing chart data. 2016-12-23 15:52:05 +01:00
James Cole
9a15decdff Translated 2016-12-23 15:02:25 +01:00
James Cole
186b986e02 New translations 2016-12-23 07:32:48 +01:00
James Cole
cdbf5653ac New translations 2016-12-23 07:32:34 +01:00
James Cole
c403dd7490 New translations 2016-12-23 07:32:28 +01:00
James Cole
d15d9fdf2a New translations 2016-12-23 07:32:24 +01:00
James Cole
0b618de44c New translations 2016-12-23 07:32:16 +01:00
James Cole
875f19f728 New translations 2016-12-23 07:32:11 +01:00
James Cole
7bb549732c New translations 2016-12-23 07:31:50 +01:00
James Cole
b9baa93ae4 Approved. Step name: Proofread 2016-12-23 07:31:36 +01:00
James Cole
315479fcd3 New translations [skip ci] 2016-12-23 07:24:38 +01:00
James Cole
1f1334a1fc Update chart to show sum 2016-12-23 07:20:47 +01:00
James Cole
bf0744e03a Updated some copyright notices [skip ci] 2016-12-23 07:02:45 +01:00
James Cole
8fb9577660 Add some debug, fix balance report bug. 2016-12-22 21:45:04 +01:00
James Cole
90d58c5c39 Update test scripts [skip ci] 2016-12-22 19:51:49 +01:00
James Cole
b6aa79bb38 Various code cleanup. Removed executable flags, added newlines. 2016-12-22 19:42:45 +01:00
James Cole
14a0de6b6a This should fix account-number. 2016-12-22 19:18:35 +01:00
James Cole
13e56b7249 Can handle account number, but do nothing with it. 2016-12-22 19:17:33 +01:00
James Cole
3753901e38 Expand flush routine because of issues. [skip ci] 2016-12-22 18:26:16 +01:00
James Cole
e76075e29f Various small fixes. 2016-12-22 18:19:50 +01:00
James Cole
284db7f90b Fixed some small display issues. 2016-12-22 17:04:41 +01:00
James Cole
cabdf4e380 This might fix the missing stack trace. [skip ci] 2016-12-22 16:55:27 +01:00
James Cole
9859052c4d Code for issue #489 2016-12-22 16:36:56 +01:00
James Cole
0feeac9160 Removed some unused imports [skip ci] 2016-12-22 15:24:16 +01:00
James Cole
54b33a0b69 Removed views no longer used. 2016-12-22 07:13:49 +01:00
James Cole
e08e7b2c9b Speed up some tests. 2016-12-22 07:13:37 +01:00
James Cole
782e2add88 Fix sort URI, smaller view [skip ci] 2016-12-21 20:34:47 +01:00
James Cole
f18a5a6f1b This fixes the broken tests. 2016-12-21 20:32:02 +01:00
James Cole
6fc971c4cb This is a fix for #487 2016-12-21 20:31:44 +01:00
James Cole
3250c4830d New seeds plus the preparation for some extended testing. 2016-12-21 19:56:06 +01:00
James Cole
9e1a69217d This fixes #484. 2016-12-21 17:50:00 +01:00
James Cole
46c26a64d8 Update import storage routine for issue #483, as suggested by @zjean 2016-12-21 17:21:36 +01:00
James Cole
2f12a70647 Add support for Spanish. [skip ci] 2016-12-20 17:21:16 +01:00
James Cole
be190d1fa0 Update favicon information. 2016-12-20 17:19:16 +01:00
James Cole
1e4888209b Fixed #479 2016-12-20 17:14:43 +01:00
James Cole
8aa2961c19 This should fix #482 2016-12-20 17:10:30 +01:00
James Cole
304cdabc96 Merge pull request #481 from JC5/l10n_develop
New Crowdin translations
2016-12-20 14:16:39 +01:00
James Cole
c60e272eb3 New translations 2016-12-20 10:42:06 +01:00
James Cole
c074f55cb2 New translations 2016-12-20 10:42:05 +01:00
James Cole
e6af29646e New translations 2016-12-20 10:42:03 +01:00
James Cole
b4213328fe New translations 2016-12-20 10:42:02 +01:00
James Cole
8a7628c9dc New translations 2016-12-20 10:42:00 +01:00
James Cole
d52c146e12 New translations 2016-12-20 10:41:58 +01:00
James Cole
1910a4bd4b New translations 2016-12-20 10:41:57 +01:00
James Cole
bd0c552f54 New translations 2016-12-20 10:41:55 +01:00
James Cole
b29ea98de4 New translations 2016-12-20 10:41:53 +01:00
James Cole
dd1db87806 New translations 2016-12-20 10:41:50 +01:00
James Cole
6f9e446577 New translations 2016-12-20 10:41:45 +01:00
James Cole
664230dca8 This fixes #478, again 2016-12-20 10:25:11 +01:00
James Cole
1a24e7e0aa Merge pull request #476 from JC5/l10n_develop
New Crowdin translations
2016-12-19 21:10:53 +01:00
James Cole
9239815ce6 Tiny view update. 2016-12-19 21:07:38 +01:00
James Cole
116e19ec06 These routines fix #477 2016-12-19 21:07:22 +01:00
James Cole
fc0ad622eb Clarify chart details [skip ci] 2016-12-19 20:47:26 +01:00
James Cole
2c5cdb8780 Clarify chart details [skip ci] 2016-12-19 20:46:24 +01:00
James Cole
9a309f32fa This fixes #478 2016-12-19 20:36:28 +01:00
James Cole
e2e54d342a This completes all controller acceptance tests 2016-12-19 20:21:14 +01:00
James Cole
42f7529495 Approved. Step name: Proofread 2016-12-19 20:01:50 +01:00
James Cole
f172151252 Expand read me [skip ci] 2016-12-19 17:31:23 +01:00
James Cole
e2ad38d3e0 Expand read me [skip ci] 2016-12-19 17:24:15 +01:00
James Cole
40cc32fc5a Updated favicon. 2016-12-19 17:15:31 +01:00
James Cole
436c034fdd New translations 2016-12-19 11:51:37 +01:00
James Cole
286b1848d9 New translations 2016-12-19 10:31:15 +01:00
James Cole
7fffebf6df New translations 2016-12-19 10:21:22 +01:00
James Cole
b1764478ec Translated 2016-12-19 10:11:53 +01:00
James Cole
6b6a799206 Translated 2016-12-18 21:41:01 +01:00
James Cole
0a82ed901e New translations 2016-12-18 21:12:00 +01:00
James Cole
d733c9ed14 New translations 2016-12-18 21:11:57 +01:00
James Cole
a752ea489c New translations 2016-12-18 21:11:51 +01:00
James Cole
876a24586f New translations 2016-12-18 21:11:47 +01:00
James Cole
ea2779cf9a New translations 2016-12-18 21:11:41 +01:00
James Cole
77aa36163d New translations 2016-12-18 21:11:38 +01:00
James Cole
b581d8ecb7 New translations 2016-12-18 21:11:18 +01:00
James Cole
83b404d01e More tests. 2016-12-18 21:04:53 +01:00
James Cole
8deb92c3e5 More tests. 2016-12-18 19:34:03 +01:00
James Cole
20a6e0170c New translations 2016-12-18 18:22:10 +01:00
James Cole
944a78807c New translations 2016-12-18 18:22:05 +01:00
James Cole
0b02d294f4 New translations 2016-12-18 18:22:00 +01:00
James Cole
a5d86536c3 New translations 2016-12-18 18:21:52 +01:00
James Cole
71c08cfe0c New translations 2016-12-18 18:21:48 +01:00
James Cole
8ab0d5fc48 New translations 2016-12-18 18:21:40 +01:00
James Cole
57f81ee4c8 Approved. Step name: Proofread 2016-12-18 18:21:29 +01:00
James Cole
5c28adf266 New tests. [skip ci] 2016-12-18 18:16:41 +01:00
James Cole
5a57398f81 New tests. 2016-12-18 17:54:11 +01:00
James Cole
8121a384ef Merge branch 'release/4.2.2' 2016-12-18 10:54:46 +01:00
James Cole
8666197e05 Changelog and version bump. 2016-12-18 10:48:05 +01:00
James Cole
1ea2b8bbcb Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Approved. Step name: Proofread
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
2016-12-18 10:41:49 +01:00
James Cole
a71cedd8a9 Merge pull request #474 from JC5/l10n_develop
New Crowdin translations
2016-12-18 10:41:39 +01:00
James Cole
04c5f583f6 Approved. Step name: Proofread 2016-12-18 10:41:08 +01:00
James Cole
7716ff4e8c Update various tests and the composer lock file. 2016-12-18 10:37:59 +01:00
James Cole
6b51a116d1 New translations 2016-12-18 09:41:52 +01:00
James Cole
b2f14dc177 New translations 2016-12-18 09:41:50 +01:00
James Cole
da1d3b82f9 New translations 2016-12-18 09:41:45 +01:00
James Cole
6282d8c828 New translations 2016-12-18 09:41:40 +01:00
James Cole
73129b0ce5 New translations 2016-12-18 09:41:35 +01:00
James Cole
f71e7a2f28 New translations 2016-12-18 09:41:31 +01:00
James Cole
341da327e3 New translations 2016-12-18 09:41:12 +01:00
James Cole
3d8adfa7e4 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
2016-12-18 09:27:42 +01:00
James Cole
279d7769f5 This fixes #470 2016-12-18 09:27:27 +01:00
James Cole
b7d3b40353 Merge pull request #471 from JC5/l10n_develop
New Crowdin translations
2016-12-18 09:16:27 +01:00
James Cole
7ecd691ee2 New tests. 2016-12-17 19:19:49 +01:00
James Cole
f3398c7dec This fixes #472 2016-12-17 17:09:46 +01:00
James Cole
90644e662d New translations 2016-12-17 08:41:52 +01:00
James Cole
f5c5cb7fb9 New translations 2016-12-17 08:41:47 +01:00
James Cole
312e79921a New translations 2016-12-17 08:41:43 +01:00
James Cole
b83d346a86 New translations 2016-12-17 08:41:37 +01:00
James Cole
3eed67f108 New translations 2016-12-17 08:41:33 +01:00
James Cole
15f0bc63b2 New translations 2016-12-17 08:41:27 +01:00
James Cole
0a4b0ec929 Approved. Step name: Proofread 2016-12-17 08:41:17 +01:00
James Cole
560f6cbf24 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii: (23 commits)
  New translations
  Approved. Step name: Proofread
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
  New translations
  Translated
  ...
2016-12-17 08:35:19 +01:00
James Cole
9165e0238f Import related tests. 2016-12-17 08:35:03 +01:00
James Cole
97d6be6809 Merge pull request #469 from JC5/l10n_develop
New Crowdin translations
2016-12-16 08:26:48 +01:00
James Cole
4de14eba0c Fix some routes for the budget report. 2016-12-16 08:07:31 +01:00
James Cole
6c64023bf7 New translations 2016-12-16 07:31:43 +01:00
James Cole
a923c288e6 Approved. Step name: Proofread 2016-12-16 07:31:41 +01:00
James Cole
4c1d8e8e85 New translations 2016-12-15 23:02:39 +01:00
James Cole
02f2def88b New translations 2016-12-15 23:02:38 +01:00
James Cole
4bcacc5d68 New translations 2016-12-15 23:02:35 +01:00
James Cole
913dbe6b1a New translations 2016-12-15 23:02:31 +01:00
James Cole
ce8164dd87 New translations 2016-12-15 23:02:28 +01:00
James Cole
a5b412f546 New translations 2016-12-15 23:02:26 +01:00
James Cole
82bb352624 New translations 2016-12-15 23:02:22 +01:00
James Cole
ebbf2659b1 New translations 2016-12-15 23:02:17 +01:00
James Cole
d0084becea New translations 2016-12-15 23:02:16 +01:00
James Cole
6af2b37ac2 New translations 2016-12-15 23:02:13 +01:00
James Cole
814fc6eabd New translations 2016-12-15 23:02:11 +01:00
James Cole
50278a679a New translations 2016-12-15 23:02:05 +01:00
James Cole
d42e9c75ef New translations 2016-12-15 23:02:03 +01:00
James Cole
00b3dced2c New translations 2016-12-15 23:02:02 +01:00
James Cole
5c0c00188f New translations 2016-12-15 23:01:59 +01:00
James Cole
2ec56626f3 Approved. Step name: Proofread 2016-12-15 23:01:56 +01:00
James Cole
e87456b2f8 New translations 2016-12-15 23:01:52 +01:00
James Cole
3609b515e5 Translated 2016-12-15 23:01:50 +01:00
James Cole
a1609542c3 Translated 2016-12-15 23:01:48 +01:00
James Cole
4c4625583a Approved. Step name: Proofread 2016-12-15 23:01:46 +01:00
James Cole
7b479316ea Approved. Step name: Proofread 2016-12-15 23:01:38 +01:00
James Cole
b021c7690f Basic edit user routine. 2016-12-15 22:56:31 +01:00
James Cole
2be060796e Merge pull request #468 from JC5/l10n_develop
New Crowdin translations
2016-12-15 21:56:24 +01:00
James Cole
1b4d55cca4 Fix various code style issues. 2016-12-15 21:35:33 +01:00
James Cole
a8cea4119d Approved. Step name: Proofread 2016-12-15 17:21:27 +01:00
James Cole
e247aace8d Various code cleanup. 2016-12-15 17:16:46 +01:00
James Cole
41553e9b86 New translations 2016-12-15 14:43:23 +01:00
James Cole
e875587260 New translations 2016-12-15 14:43:18 +01:00
James Cole
5377483345 New translations 2016-12-15 14:43:08 +01:00
James Cole
4112acfb8d New translations 2016-12-15 14:42:56 +01:00
James Cole
f3bc02e11c New translations 2016-12-15 14:42:46 +01:00
James Cole
8e411a898b New translations 2016-12-15 14:42:40 +01:00
James Cole
915edbecc9 New translations 2016-12-15 14:42:28 +01:00
James Cole
975a6c34bf Finished #452 2016-12-15 14:38:05 +01:00
James Cole
cdd988b4de Piggy banks and #452 2016-12-15 14:05:50 +01:00
James Cole
b58bc97422 Code for #452 2016-12-15 13:47:28 +01:00
James Cole
482688ac3c Merge pull request #467 from JC5/l10n_develop
New Crowdin translations
2016-12-15 11:20:24 +01:00
James Cole
aea31b5e28 Budget charts #452 2016-12-15 10:44:06 +01:00
James Cole
d7cbc53b4b Multiply by -1. 2016-12-15 10:41:56 +01:00
James Cole
f74c6c2d19 Updated budget charts [skip ci] 2016-12-15 10:41:10 +01:00
James Cole
3080d2ddc4 New translations 2016-12-15 10:03:53 +01:00
James Cole
4ad5881760 New translations 2016-12-15 10:03:43 +01:00
James Cole
7e55d1a4fd New translations 2016-12-15 10:03:36 +01:00
James Cole
7ef5eed6e2 New translations 2016-12-15 10:03:22 +01:00
James Cole
10aa41a7ea New translations 2016-12-15 10:03:15 +01:00
James Cole
1f9b362b6f New translations 2016-12-15 10:03:01 +01:00
James Cole
4bf9bfb521 Approved. Step name: Proofread 2016-12-15 10:02:26 +01:00
James Cole
1d7119114d New translations [skip ci] 2016-12-15 09:55:10 +01:00
James Cole
e1b6df6fb1 Include budgeted info as well. [skip ci] 2016-12-15 09:54:10 +01:00
James Cole
7cf38bb01e Include budgeted info as well. [skip ci] 2016-12-15 09:52:58 +01:00
James Cole
e34ec22845 Forgot to do * -1. [skip ci] 2016-12-15 09:51:22 +01:00
James Cole
46506abeb8 Forgot to do * -1. [skip ci] 2016-12-15 09:50:22 +01:00
James Cole
95654cc4d4 New budget chart generator 2016-12-15 09:49:35 +01:00
James Cole
47aded820d New test. 2016-12-15 08:53:10 +01:00
James Cole
24444ebf08 Merge pull request #466 from JC5/l10n_develop
New Crowdin translations
2016-12-15 08:41:53 +01:00
James Cole
bdc0df8350 Approved. Step name: Proofread 2016-12-15 08:31:26 +01:00
James Cole
b2c9a2973c Merge pull request #465 from JC5/l10n_develop
New Crowdin translations
2016-12-15 08:27:54 +01:00
James Cole
da2a347511 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
  Approved. Step name: Proofread
  Approved. Step name: Proofread
2016-12-15 08:17:17 +01:00
James Cole
6fbc3ba060 New screenshots [skip ci] 2016-12-15 08:16:34 +01:00
James Cole
02eff06cd3 New translations 2016-12-15 08:11:28 +01:00
James Cole
7586d4b494 New translations 2016-12-15 08:01:18 +01:00
James Cole
9059f0fee6 Translated 2016-12-15 07:51:13 +01:00
James Cole
c2af9e3d20 Merge pull request #464 from JC5/l10n_develop
New Crowdin translations
2016-12-14 22:53:58 +01:00
James Cole
0b51366526 New translations 2016-12-14 19:13:32 +01:00
James Cole
e40260bd9c New translations 2016-12-14 19:13:25 +01:00
James Cole
cf2842840d New translations 2016-12-14 19:13:18 +01:00
James Cole
17fa8fcb2c New translations 2016-12-14 19:13:06 +01:00
James Cole
0d2f9864e2 New translations 2016-12-14 19:12:59 +01:00
James Cole
89cbd91204 New translations 2016-12-14 19:12:46 +01:00
James Cole
f4d9b57887 Approved. Step name: Proofread 2016-12-14 19:12:39 +01:00
James Cole
4b2e4afca5 Approved. Step name: Proofread 2016-12-14 19:12:27 +01:00
James Cole
dd1ba30c48 Approved. Step name: Proofread 2016-12-14 19:12:18 +01:00
James Cole
3ba4570691 Merge pull request #463 from JC5/l10n_develop
New Crowdin translations
2016-12-14 18:59:39 +01:00
James Cole
848cfabcba Rearrange code [skip ci] 2016-12-14 18:59:12 +01:00
James Cole
1bbd10b909 New translations 2016-12-14 18:53:48 +01:00
James Cole
a16a4f813d New translations 2016-12-14 18:53:44 +01:00
James Cole
91cfa963b2 New translations 2016-12-14 18:53:42 +01:00
James Cole
a35557eb62 New translations 2016-12-14 18:53:34 +01:00
James Cole
aad4e47b6a New translations 2016-12-14 18:53:32 +01:00
James Cole
1b177723ae New translations 2016-12-14 18:53:25 +01:00
James Cole
99dba92bd3 New translations 2016-12-14 18:53:17 +01:00
James Cole
e13ccff056 New translations 2016-12-14 18:53:14 +01:00
James Cole
46528dd29d New translations 2016-12-14 18:53:08 +01:00
James Cole
4f611ad810 New translations 2016-12-14 18:52:57 +01:00
James Cole
af41985a64 New translations 2016-12-14 18:52:55 +01:00
James Cole
d0864e06b5 Translated 2016-12-14 18:52:41 +01:00
James Cole
6f0366e146 Translated 2016-12-14 18:52:38 +01:00
James Cole
e0cdbcb28c Approved. Step name: Proofread 2016-12-14 18:52:35 +01:00
James Cole
f19b99194c Wording 2016-12-14 18:47:32 +01:00
James Cole
43a55e2e35 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Translated
  Translated
  Approved. Step name: Proofread
  Approved. Step name: Proofread
2016-12-14 18:45:27 +01:00
James Cole
b2743825ca Sort account list by name [skip ci] 2016-12-14 18:44:56 +01:00
James Cole
d4f6cce56e New translations 2016-12-14 17:32:30 +01:00
James Cole
6092d206b6 New translations 2016-12-14 17:22:30 +01:00
James Cole
c8ad83cc91 New translations 2016-12-14 13:21:56 +01:00
James Cole
7d31071ff8 New translations 2016-12-14 13:12:12 +01:00
James Cole
c975ef15f1 Translated 2016-12-14 13:12:03 +01:00
James Cole
f855011d34 Translated 2016-12-14 13:12:00 +01:00
James Cole
fbcf0929d8 New translations 2016-12-14 13:01:30 +01:00
James Cole
d89e75cbe8 New translations 2016-12-14 12:51:23 +01:00
James Cole
ccaa42ad74 New translations 2016-12-14 12:41:14 +01:00
James Cole
56d8dce622 New translations 2016-12-14 12:31:07 +01:00
James Cole
c79baf98cf New translations 2016-12-14 12:21:22 +01:00
James Cole
d1cab9f68c Merge pull request #462 from JC5/l10n_develop
New Crowdin translations
2016-12-14 10:37:35 +01:00
James Cole
69c5c93353 This fixes the tests. 2016-12-13 21:09:04 +01:00
James Cole
28ebd683e4 New translations 2016-12-13 21:03:02 +01:00
James Cole
d752edd625 New translations 2016-12-13 21:02:58 +01:00
James Cole
1dab45d493 New translations 2016-12-13 21:02:54 +01:00
James Cole
b99982d02b New translations 2016-12-13 21:02:48 +01:00
James Cole
fff17ac6c1 New translations 2016-12-13 21:02:44 +01:00
James Cole
4086257983 New translations 2016-12-13 21:02:37 +01:00
James Cole
bd9e0ac281 New translations 2016-12-13 21:02:34 +01:00
James Cole
b075d6db5e New translations 2016-12-13 21:02:32 +01:00
James Cole
befd79cf14 New translations 2016-12-13 21:02:26 +01:00
James Cole
07f68d2b14 New translations 2016-12-13 21:02:22 +01:00
James Cole
d14889bd27 Translated 2016-12-13 21:02:11 +01:00
James Cole
91e40c14f9 Translated 2016-12-13 21:02:09 +01:00
James Cole
b7b2206262 Approved. Step name: Proofread 2016-12-13 21:02:01 +01:00
James Cole
f344d0319c Approved. Step name: Proofread 2016-12-13 21:01:50 +01:00
James Cole
0c8a1682b6 Wrong reference #461 [skip ci] 2016-12-13 20:58:51 +01:00
James Cole
39866be3f1 Translations. #461 2016-12-13 20:57:10 +01:00
James Cole
947e82fa0f Fixed final mails for #461 2016-12-13 20:51:10 +01:00
James Cole
0335a64a21 Code for #461 2016-12-13 20:37:38 +01:00
James Cole
a9e57e1c34 First set of code for #461 2016-12-13 17:21:28 +01:00
James Cole
8a8279f97a Merge pull request #459 from JC5/l10n_develop
New Crowdin translations
2016-12-12 20:22:49 +01:00
James Cole
b968889552 Approved. Step name: Proofread 2016-12-12 20:21:52 +01:00
James Cole
4068df5e50 Approved. Step name: Proofread 2016-12-12 20:21:33 +01:00
James Cole
dc42370322 Merge pull request #458 from JC5/l10n_develop
New Crowdin translations
2016-12-12 20:13:58 +01:00
James Cole
8c24f14ee5 New translations 2016-12-12 20:12:47 +01:00
James Cole
494d1743a2 New translations 2016-12-12 20:12:43 +01:00
James Cole
4a30d9f6bb New translations 2016-12-12 20:12:37 +01:00
James Cole
ed6d25067c New translations 2016-12-12 20:12:32 +01:00
James Cole
445ae7e10e New translations 2016-12-12 20:12:25 +01:00
James Cole
6f45609161 New translations 2016-12-12 20:12:20 +01:00
James Cole
f1230e47f7 New translations 2016-12-12 20:11:52 +01:00
James Cole
7e0ef6d43e Better view for accounts and I fixed a html error. 2016-12-12 20:02:33 +01:00
James Cole
14f9da544a This fixes #454 2016-12-12 19:39:54 +01:00
James Cole
5a84036e16 Merge pull request #457 from JC5/l10n_develop
New Crowdin translations
2016-12-12 17:42:05 +01:00
James Cole
4dccf7b7b5 Properly check hashes, issue #456 2016-12-12 17:17:36 +01:00
James Cole
66060dbed4 New translations 2016-12-12 15:32:47 +01:00
James Cole
cfb824588f New translations 2016-12-12 15:32:36 +01:00
James Cole
d2b4316d7a New translations 2016-12-12 15:32:24 +01:00
James Cole
3af69b433d New translations 2016-12-12 15:32:13 +01:00
James Cole
a6733fa255 Translated 2016-12-12 15:32:04 +01:00
James Cole
4277c54009 Approved. Step name: Proofread 2016-12-12 15:32:00 +01:00
James Cole
66baa7554a New translations 2016-12-12 15:31:48 +01:00
James Cole
ffca4b0543 More code for #456 2016-12-12 15:27:56 +01:00
James Cole
3e3c48314f Code for #456 2016-12-12 15:24:47 +01:00
James Cole
06ff450d31 Fixed sort 2016-12-12 08:14:38 +01:00
James Cole
07c57cc640 Merge pull request #453 from JC5/l10n_develop
New Crowdin translations
2016-12-12 07:45:59 +01:00
James Cole
a67f10c99e Wrote export tests. 2016-12-11 18:34:18 +01:00
James Cole
2882bcbf7b New translations 2016-12-11 17:51:47 +01:00
James Cole
67cc5b0280 New translations 2016-12-11 17:51:45 +01:00
James Cole
b42b178b71 New translations 2016-12-11 17:51:38 +01:00
James Cole
7de05cd173 New translations 2016-12-11 17:51:34 +01:00
James Cole
3db43743d9 New translations 2016-12-11 17:51:28 +01:00
James Cole
14638e4ed8 New translations 2016-12-11 17:51:25 +01:00
James Cole
e756b93810 New translations 2016-12-11 17:51:18 +01:00
James Cole
358d83dcfc Changed language strings [skip ci] 2016-12-11 17:49:02 +01:00
James Cole
331c231a94 Small bug fix in bill chart [skip ci] 2016-12-11 17:47:47 +01:00
James Cole
4403b65bae Experimental bill chart [skip ci] 2016-12-11 17:46:30 +01:00
James Cole
a27d80d765 Fix sort [skip ci] 2016-12-11 17:32:48 +01:00
James Cole
04272fff81 Fixed a small bug in the account frontpage chart. 2016-12-11 17:30:55 +01:00
James Cole
e963708c54 Remove from provider as well (#452) 2016-12-11 17:06:23 +01:00
James Cole
08c4542847 Clean up chart code. 2016-12-11 17:05:48 +01:00
James Cole
553e9270e5 More code for #452 2016-12-11 16:38:21 +01:00
James Cole
8a7297e131 Code for currency controller tests. 2016-12-11 16:25:46 +01:00
James Cole
0f260da8e6 More code for issue #452 2016-12-11 16:25:25 +01:00
James Cole
77560ab3a8 Wrote more tests. 2016-12-11 16:02:15 +01:00
James Cole
e3b2f2d9a8 Experimental code for issue #452 2016-12-11 16:02:04 +01:00
James Cole
74e01a52b9 More tests 2016-12-11 14:03:30 +01:00
James Cole
dc28ba42ef More tests 2016-12-11 13:28:13 +01:00
James Cole
406150620a Fixed more tests. 2016-12-11 13:16:56 +01:00
James Cole
43f59a1135 Fixed missing chart. 2016-12-11 11:15:19 +01:00
James Cole
5c02eaa66c Split controller tests. 2016-12-11 11:04:53 +01:00
James Cole
b4eac84097 Update tests, fixes some bugs. 2016-12-11 10:38:06 +01:00
James Cole
ec3b356f86 Fix mass edit and mass delete routes. [skip ci] 2016-12-10 17:55:47 +01:00
James Cole
bf99d5c299 Fixed the account view, changed routes. 2016-12-10 17:54:35 +01:00
James Cole
a297131440 Finished even more tests 2016-12-10 17:46:19 +01:00
James Cole
bae2161ee3 Expand tests. 2016-12-10 16:32:52 +01:00
James Cole
0fe0de1a7f New tests 2016-12-10 07:29:36 +01:00
James Cole
e7845115f6 New tests 2016-12-10 06:54:50 +01:00
James Cole
bc11c3fab2 Working but fairly useless budget report 2016-12-10 06:50:13 +01:00
James Cole
1b7546f3f9 Expand tests. 2016-12-09 18:53:13 +01:00
James Cole
663be30117 Fixed the account overview chart 2016-12-09 18:52:27 +01:00
James Cole
cf34713518 Fix some tests. 2016-12-09 16:30:33 +01:00
James Cole
3f56a8ec53 Expand test routines 2016-12-09 15:17:57 +01:00
James Cole
35d105588b Fix tag assignment for multiple deposits [skip ci] 2016-12-09 14:50:28 +01:00
James Cole
122d988ed2 Add some debug. [skip ci] 2016-12-09 14:42:14 +01:00
James Cole
9fcc5e7a67 Fix decryption bug. 2016-12-09 14:21:26 +01:00
James Cole
9a492c3731 Merge pull request #450 from JC5/l10n_develop
New Crowdin translations
2016-12-09 14:18:18 +01:00
James Cole
4f752031f3 New translations 2016-12-09 07:42:04 +01:00
James Cole
19be8bb891 New translations 2016-12-09 07:42:01 +01:00
James Cole
693e1b08c7 New translations 2016-12-09 07:41:55 +01:00
James Cole
9aad380518 New translations 2016-12-09 07:41:51 +01:00
James Cole
8c518c8d58 New translations 2016-12-09 07:41:44 +01:00
James Cole
9af89a19db New translations 2016-12-09 07:41:40 +01:00
James Cole
939b18b86c New translations 2016-12-09 07:41:31 +01:00
James Cole
108e775a15 New routes 2016-12-09 07:40:00 +01:00
James Cole
653692ade0 Try to test for confirmation errors. 2016-12-09 07:20:48 +01:00
James Cole
72c6bfee7e New bread crumb for user edit 2016-12-09 07:08:43 +01:00
James Cole
ac92939429 Test to see if bread crumb present. 2016-12-09 07:08:31 +01:00
James Cole
052957bbd0 New view for edit user 2016-12-09 07:08:20 +01:00
James Cole
97e6afe3dc New text to be translated. 2016-12-09 07:08:09 +01:00
James Cole
1fd028dfb8 First code for #426 2016-12-09 07:07:53 +01:00
James Cole
c73866f47c Fixed date [skip ci] 2016-12-09 06:28:51 +01:00
James Cole
b0e120abee New translations 2016-12-08 21:52:28 +01:00
James Cole
b2da38d401 New translations 2016-12-08 21:52:22 +01:00
James Cole
cabe2579fa New translations 2016-12-08 21:52:16 +01:00
James Cole
18a845ac55 New translations 2016-12-08 21:52:06 +01:00
James Cole
a4d14f8259 New translations 2016-12-08 21:52:01 +01:00
James Cole
9d084e62f7 New translations 2016-12-08 21:51:53 +01:00
James Cole
0393fcd704 Approved. Step name: Proofread 2016-12-08 21:51:30 +01:00
James Cole
edb5b2ed5e Initial code for new budget report #426 2016-12-08 21:50:20 +01:00
James Cole
529bab1112 Merge branch 'release/4.2.1' 2016-12-08 21:23:19 +01:00
James Cole
ab9212a4c9 last code for 4.2.1 2016-12-08 21:22:42 +01:00
James Cole
b2cbba0f3b Merge pull request #449 from JC5/l10n_develop
New Crowdin translations
2016-12-08 21:04:16 +01:00
James Cole
ca73ef8531 Approved. Step name: Proofread 2016-12-08 20:41:30 +01:00
James Cole
d13490cb6e Approved. Step name: Proofread 2016-12-08 20:41:27 +01:00
James Cole
73566e11c0 Removed some JS code that was not necessary. [skip ci] 2016-12-08 20:33:41 +01:00
James Cole
36ebd0f0ee Expand view. 2016-12-07 21:38:35 +01:00
James Cole
efe290d96c This fixes the tests. 2016-12-07 20:45:26 +01:00
James Cole
da3988cc63 New tests 2016-12-07 20:06:06 +01:00
James Cole
df6f4aecf8 Update tests. 2016-12-07 19:53:41 +01:00
Sander
db1a60b6df Fix display bug 2016-12-07 07:58:55 +00:00
James Cole
d79866f115 Fix route [skip ci] 2016-12-07 06:27:27 +01:00
James Cole
cdd18b229e Refactor some duplicated code 2016-12-06 16:58:39 +01:00
James Cole
cca2de9f1b This should remove some issues from scrutinizer. 2016-12-06 16:55:13 +01:00
James Cole
6a58dbb207 Generic code cleanup. 2016-12-06 16:44:58 +01:00
James Cole
779f461491 Merge pull request #447 from JC5/l10n_develop
New Crowdin translations
2016-12-06 16:44:39 +01:00
James Cole
085eca6c02 New translations 2016-12-06 14:42:07 +01:00
James Cole
25db11a8c7 Translated 2016-12-06 14:22:19 +01:00
James Cole
76bcc68ab9 Merge pull request #446 from JC5/l10n_develop
New Crowdin translations
2016-12-06 10:52:05 +01:00
James Cole
9daefaaca4 Fix sort [skip ci] 2016-12-06 10:42:49 +01:00
James Cole
fbbbcc4e74 Fix category report. 2016-12-06 10:42:13 +01:00
James Cole
2e1f31a7f8 Fix sort. 2016-12-06 10:19:43 +01:00
James Cole
8a0ac81fd0 Fix decrypt exception. 2016-12-06 10:13:48 +01:00
James Cole
cdd50dfdd2 Fix decrypt exception. 2016-12-06 10:12:08 +01:00
James Cole
a05c8ca351 New test files. 2016-12-06 09:16:36 +01:00
James Cole
2ca584f097 Fix test. 2016-12-06 09:12:04 +01:00
James Cole
687da83feb Remove unused collections [skip ci] 2016-12-06 09:09:05 +01:00
James Cole
c799fc655d Final set of route changes. 2016-12-06 09:07:50 +01:00
James Cole
27848f55ce New translations 2016-12-06 09:02:19 +01:00
James Cole
001a6e310e New translations 2016-12-06 09:02:13 +01:00
James Cole
ad00bc2806 New translations 2016-12-06 09:02:08 +01:00
James Cole
d8e3365345 New translations 2016-12-06 09:01:58 +01:00
James Cole
5849fe2c30 New translations 2016-12-06 09:01:55 +01:00
James Cole
690b498197 New translations 2016-12-06 09:01:47 +01:00
James Cole
d5ddd447bc Approved. Step name: Proofread 2016-12-06 09:01:26 +01:00
James Cole
628c7cd055 Many more route fixes. 2016-12-06 08:59:08 +01:00
James Cole
f4887bbbf7 More routes and pages fixed. 2016-12-06 08:15:53 +01:00
James Cole
d8f291be6e Clean up code after changing routes. 2016-12-06 07:48:41 +01:00
James Cole
02257e3887 More routes fixed. 2016-12-06 07:06:20 +01:00
James Cole
bebfbf0b90 Fixing routes 2016-12-06 06:52:17 +01:00
James Cole
9cb3bfaa57 Clean up routes 2016-12-06 06:15:42 +01:00
James Cole
8e2c035536 Cleaned up a lot of routes [skip ci] 2016-12-05 22:19:24 +01:00
James Cole
6b56c2bf7c Many new renamed routes that will break half of Firefly. 2016-12-05 21:58:23 +01:00
James Cole
d91b9e71d5 Remove unused code. 2016-12-05 20:44:20 +01:00
James Cole
344916d57e Catch encrypted opposing accounts. [skip ci] 2016-12-05 20:39:17 +01:00
James Cole
b1ef225bd0 Also fix income/expenses sum 2016-12-05 20:35:13 +01:00
James Cole
b713eae009 Fixed some issues with expense/income overview. 2016-12-05 20:19:26 +01:00
James Cole
098cc88d5f Fix various routes. 2016-12-05 20:01:01 +01:00
James Cole
2476dd38b3 Route clean up 2016-12-04 19:55:15 +01:00
James Cole
8fec569dbb Merge pull request #443 from JC5/l10n_develop
New Crowdin translations
2016-12-04 19:05:34 +01:00
James Cole
ba92aa207c New translations 2016-12-04 18:11:51 +01:00
James Cole
f7abf132e2 New translations 2016-12-04 18:11:44 +01:00
James Cole
38919ae300 New translations 2016-12-04 18:11:34 +01:00
James Cole
bba15cef24 New translations 2016-12-04 18:11:28 +01:00
James Cole
e8792fa218 Translated 2016-12-04 18:11:20 +01:00
James Cole
c5f81d4a94 Approved. Step name: Proofread 2016-12-04 18:11:19 +01:00
James Cole
a7b8c9d94d Translated 2016-12-04 18:11:16 +01:00
James Cole
f4b9b7ae84 Various report updates and code cleanup. 2016-12-04 18:02:19 +01:00
James Cole
905a2432c6 Remove todo from code, as we are supposed to. 2016-12-04 17:17:25 +01:00
James Cole
89e4c3de25 A fairly primitive data validation routine for split transactions. 2016-12-04 17:13:37 +01:00
James Cole
86ea9db37e Extend currency data for issue #439 2016-12-04 09:33:41 +01:00
James Cole
62a9fda1c2 New tests. 2016-12-04 08:11:29 +01:00
James Cole
49f7c1bbc1 Updated composer file [skip ci] 2016-12-03 21:53:08 +01:00
James Cole
9dc6f41c18 Include chart with report 2016-12-03 21:48:40 +01:00
James Cole
0a844e4313 Use format amount routine [skip ci] 2016-12-03 21:26:34 +01:00
James Cole
53daa89fcb Display optimisations. [skip ci] 2016-12-03 21:24:55 +01:00
James Cole
c5d31bccc5 Small table optimisations [skip ci] 2016-12-03 21:12:02 +01:00
James Cole
b032825342 Building report from issue #386 2016-12-03 21:03:20 +01:00
James Cole
8377a2a0de Building report from issue #386 2016-12-03 20:38:13 +01:00
James Cole
57e49c225b Merge pull request #438 from JC5/l10n_develop
New Crowdin translations
2016-12-01 08:05:21 +01:00
James Cole
6638f6fb5c Approved. Step name: Proofread 2016-12-01 08:01:07 +01:00
James Cole
71e1b58f1d Experimental code for issue #435. Let’s try this a few times, see how it works. 2016-11-29 19:34:54 +01:00
James Cole
a87cb0fc0b Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Translated
  Translated
  Translated
  New translations
  Translated
  Translated
  Translated
  New translations
  New translations
2016-11-29 19:34:11 +01:00
James Cole
2e65f63e4a Merge pull request #436 from JC5/l10n_develop
New Crowdin translations
2016-11-29 19:33:51 +01:00
James Cole
5fb2db4e28 New translations 2016-11-29 17:41:26 +01:00
James Cole
238ae125b5 New translations 2016-11-29 17:41:20 +01:00
James Cole
110d7f691c New translations 2016-11-29 17:31:42 +01:00
James Cole
9fb9c7e3ee New translations 2016-11-29 17:31:36 +01:00
James Cole
a95b1857fe New translations 2016-11-29 17:21:56 +01:00
James Cole
ea97b817fc New translations 2016-11-29 17:21:49 +01:00
James Cole
0eea85a884 Translated 2016-11-29 17:21:45 +01:00
James Cole
eae4e988be Translated 2016-11-29 17:21:43 +01:00
James Cole
bdf752bf7e Translated 2016-11-29 17:21:42 +01:00
James Cole
a19fed5959 New translations 2016-11-29 17:12:07 +01:00
James Cole
7474553832 Translated 2016-11-29 17:12:04 +01:00
James Cole
52567116c2 Translated 2016-11-29 17:12:02 +01:00
James Cole
a70b369aaf Translated 2016-11-29 17:12:00 +01:00
James Cole
33a9e80d9d New translations 2016-11-29 17:11:58 +01:00
James Cole
96ef409f75 Merge pull request #434 from JC5/l10n_develop
New Crowdin translations
2016-11-29 13:23:05 +01:00
James Cole
8f5152e185 Small code cleanup [skip ci] 2016-11-28 20:52:56 +01:00
James Cole
f5f17d1f40 New translations 2016-11-28 20:41:22 +01:00
James Cole
b960f50f38 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Approved. Step name: Proofread
  New translations
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
  New translations
2016-11-28 20:41:04 +01:00
James Cole
72e357b673 Merge pull request #433 from JC5/l10n_develop
New Crowdin translations
2016-11-28 20:40:39 +01:00
James Cole
b33aa733c7 Fix some minor scrutinizer issues. 2016-11-28 20:38:03 +01:00
James Cole
a6a2c0c182 Remove unused language files. 2016-11-28 20:35:12 +01:00
James Cole
3097ab84fa Approved. Step name: Proofread 2016-11-28 20:31:24 +01:00
James Cole
dd9ce3e06d New translations 2016-11-28 19:52:36 +01:00
James Cole
560fc8b01c New translations 2016-11-28 19:52:30 +01:00
James Cole
f72aba6939 New translations 2016-11-28 19:52:24 +01:00
James Cole
03bc74cae9 New translations 2016-11-28 19:52:16 +01:00
James Cole
7eaf8e3eeb New translations 2016-11-28 19:52:11 +01:00
James Cole
b2b4732657 Approved. Step name: Proofread 2016-11-28 19:51:57 +01:00
James Cole
70473b7635 New translations 2016-11-28 19:51:40 +01:00
James Cole
e4a9e23dfb Merge pull request #432 from JC5/l10n_develop
New Crowdin translations
2016-11-28 19:45:44 +01:00
James Cole
f0fd5324ea Fixes #417 2016-11-28 19:45:36 +01:00
James Cole
addebad810 Approved. Step name: Proofread 2016-11-28 19:41:17 +01:00
James Cole
253466c533 Translated 2016-11-28 19:41:15 +01:00
James Cole
885d0f1464 Merge pull request #431 from JC5/l10n_develop
New Crowdin translations
2016-11-28 19:35:46 +01:00
James Cole
4743cc40a2 New translations 2016-11-28 19:02:46 +01:00
James Cole
92bf9c9214 New translations 2016-11-28 19:02:40 +01:00
James Cole
cd80d82ad4 New translations 2016-11-28 19:02:37 +01:00
James Cole
1b7b6a676d New translations 2016-11-28 19:02:34 +01:00
James Cole
1c61afca07 New translations 2016-11-28 19:02:27 +01:00
James Cole
d4d812c195 New translations 2016-11-28 19:02:23 +01:00
James Cole
ab7803f210 New translations 2016-11-28 19:02:18 +01:00
James Cole
11007f0476 New translations 2016-11-28 19:02:13 +01:00
James Cole
6b1884a9e0 New translations 2016-11-28 19:02:10 +01:00
James Cole
1112a0761f Approved. Step name: Proofread 2016-11-28 19:02:04 +01:00
James Cole
807947fcd8 Approved. Step name: Proofread 2016-11-28 19:01:58 +01:00
James Cole
7afd8f99cb Translated 2016-11-28 19:01:53 +01:00
James Cole
b14a15ce49 New translations 2016-11-28 19:01:50 +01:00
James Cole
2e6ad0ce5d New translations 2016-11-28 19:01:48 +01:00
James Cole
8cdbc96aa5 Add BIC support. This fixes #430 2016-11-28 18:55:56 +01:00
James Cole
956019ff4a Merge branch 'release/4.2.0' 2016-11-27 16:00:47 +01:00
James Cole
8279cf0e88 New version. 2016-11-27 15:59:13 +01:00
James Cole
43c32abfe8 Various code cleanup. 2016-11-26 13:02:44 +01:00
James Cole
0e66939408 Various code cleanup. 2016-11-26 10:53:20 +01:00
James Cole
22d2a523fb Some minor code fixes. 2016-11-26 10:39:05 +01:00
James Cole
bc825a8603 Remove unused code. 2016-11-26 09:29:41 +01:00
James Cole
c9cfda34a1 Remove duplicate code. 2016-11-26 09:21:49 +01:00
James Cole
e8dfbff73f Various code cleanup. 2016-11-26 09:16:06 +01:00
James Cole
62e41f1997 Remove TODO annotations 2016-11-26 09:07:16 +01:00
James Cole
8c9f90f1b4 Some code cleanup. 2016-11-26 09:01:00 +01:00
James Cole
1453a78e49 Remove todo annotations. 2016-11-26 08:55:26 +01:00
James Cole
7efaf51595 Merge pull request #428 from JC5/l10n_develop
New Crowdin translations
2016-11-26 08:41:35 +01:00
James Cole
6bc6674ab1 Some code simplification. 2016-11-26 08:41:15 +01:00
James Cole
d6c7ff0ccb Chart for budget report will also include split journals. 2016-11-26 07:18:20 +01:00
James Cole
28f655dba1 This code makes sure the budget report also includes split expenses. 2016-11-26 07:09:02 +01:00
James Cole
6a3de12894 Approved. Step name: Proofread 2016-11-25 23:01:03 +01:00
James Cole
c7940333ec Approved. Step name: Proofread 2016-11-25 23:01:01 +01:00
James Cole
8860378757 Fix budget in split journals. 2016-11-25 19:06:06 +01:00
James Cole
728fda0116 This allows the user to set the “default” currency for an asset account (#305). It doesn’t do anything other than this yet. 2016-11-25 18:00:29 +01:00
James Cole
0c72e1831f Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
  Translated
  New translations
  New translations
2016-11-25 17:43:38 +01:00
James Cole
7da21976ec Merge pull request #425 from JC5/l10n_develop
New Crowdin translations
2016-11-25 17:43:17 +01:00
James Cole
b739859c64 Expand journal meta with soft delete. This pushes Firefly to 4.2.0. 2016-11-25 17:42:45 +01:00
James Cole
d25665f843 New translations 2016-11-25 17:02:24 +01:00
James Cole
1f41f7bd0f New translations 2016-11-25 17:02:20 +01:00
James Cole
dd8638ca98 New translations 2016-11-25 17:02:17 +01:00
James Cole
4ba9ff05b0 New translations 2016-11-25 17:02:12 +01:00
James Cole
618aad5432 New translations 2016-11-25 17:02:08 +01:00
James Cole
e46fc7501e New translations 2016-11-25 17:02:06 +01:00
James Cole
7b91e98d46 New translations 2016-11-25 17:01:58 +01:00
James Cole
85be218f92 New translations 2016-11-25 17:01:55 +01:00
James Cole
71206e395e New translations 2016-11-25 17:01:53 +01:00
James Cole
9b2d2e16b0 New translations 2016-11-25 17:01:48 +01:00
James Cole
5ae01b382e Approved. Step name: Proofread 2016-11-25 17:01:40 +01:00
James Cole
d92a0753a6 Translated 2016-11-25 17:01:35 +01:00
James Cole
f937a74507 New translations 2016-11-25 17:01:27 +01:00
James Cole
c3584ad20c New translations 2016-11-25 17:01:25 +01:00
James Cole
c049d5cfa6 Various small fixes. 2016-11-25 16:55:04 +01:00
James Cole
6c9990e0be Various Javascript related fixes. 2016-11-25 16:54:13 +01:00
James Cole
b34e4cd31b This fixes #422 2016-11-25 16:52:43 +01:00
James Cole
7852b8a785 Make sure ff does not create accounts when balance is said to be 0. 2016-11-25 16:26:03 +01:00
James Cole
6eeb60db5c Multiply sum by -1. 2016-11-24 21:37:09 +01:00
James Cole
d076cfc08f Attempt to fix issue #417 2016-11-24 21:35:23 +01:00
James Cole
68a93ff97c Made fonts local 2016-11-24 19:26:47 +01:00
James Cole
295dcb4f65 Whoops ;) 2016-11-24 19:20:04 +01:00
James Cole
d9849f60c0 Parse error 2016-11-24 19:16:15 +01:00
James Cole
7ebb68e36c This fixes #419 2016-11-24 19:15:16 +01:00
James Cole
f029f7607b Rewrote all email messages. 2016-11-22 21:21:11 +01:00
James Cole
2ba5733ebc Merge pull request #415 from JC5/l10n_develop
New Crowdin translations
2016-11-22 19:31:51 +01:00
James Cole
3fe1d1d368 New translations 2016-11-22 19:12:25 +01:00
James Cole
438c372583 New translations 2016-11-22 19:12:19 +01:00
James Cole
797aa4858e New translations 2016-11-22 19:12:13 +01:00
James Cole
8c858cd066 New translations 2016-11-22 19:12:05 +01:00
James Cole
85aebd39b9 New translations 2016-11-22 19:12:00 +01:00
James Cole
9a5a037424 Approved. Step name: Proofread 2016-11-22 19:11:48 +01:00
James Cole
7d557cbf91 New translations 2016-11-22 19:11:30 +01:00
James Cole
dbbc85a576 Hide some boxes when the user has no bills. 2016-11-22 19:10:38 +01:00
James Cole
eb78cf20c2 This fixes #414 2016-11-22 19:10:17 +01:00
James Cole
4a99399952 Fix chart for account/all overview. 2016-11-21 20:23:25 +01:00
James Cole
6075d75ee2 Fix debug code [skip ci] 2016-11-21 20:15:59 +01:00
James Cole
f4c56fee66 Merge pull request #412 from JC5/l10n_develop
New Crowdin translations
2016-11-20 19:32:54 +01:00
James Cole
04c59304da Add sorting to a report table [skip ci] 2016-11-20 19:11:10 +01:00
James Cole
4b3c31a11a Ignore deleted transactions. [skip ci] 2016-11-20 19:03:08 +01:00
James Cole
14576d2753 Approved. Step name: Proofread 2016-11-20 18:51:13 +01:00
James Cole
72ca1c20c7 Merge pull request #411 from JC5/l10n_develop
New Crowdin translations
2016-11-20 18:45:16 +01:00
James Cole
93645819b8 New translations 2016-11-20 18:41:48 +01:00
James Cole
39468f871b New translations 2016-11-20 18:41:42 +01:00
James Cole
faa47781d2 New translations 2016-11-20 18:41:37 +01:00
James Cole
2c196bab6d New translations 2016-11-20 18:41:30 +01:00
James Cole
9ae71075ef New translations 2016-11-20 18:41:26 +01:00
James Cole
0013cdfa78 Translated 2016-11-20 18:41:14 +01:00
James Cole
52f3f64f7b New translations 2016-11-20 18:41:03 +01:00
James Cole
670fa77dd7 New tests. 2016-11-20 18:34:49 +01:00
James Cole
8baea2feb9 Code for #385 2016-11-20 18:31:29 +01:00
James Cole
c56f937521 Improved sorting in various views. 2016-11-20 17:36:11 +01:00
James Cole
0b613c3b8c Improve sortability in various lists. 2016-11-20 15:30:16 +01:00
James Cole
78f297e18f Fixed some display bugs for split journals. 2016-11-20 14:17:16 +01:00
James Cole
bd8a285d6d Merge pull request #410 from JC5/l10n_develop
New Crowdin translations
2016-11-20 13:06:14 +01:00
James Cole
b44602fd55 New translations 2016-11-20 13:01:38 +01:00
James Cole
41238903e1 New translations 2016-11-20 13:01:33 +01:00
James Cole
a0c88e9b33 New translations 2016-11-20 13:01:30 +01:00
James Cole
5d184aa53e New translations 2016-11-20 13:01:23 +01:00
James Cole
9f9bf86a9f New translations 2016-11-20 13:01:19 +01:00
James Cole
53af9345eb Approved. Step name: Proofread 2016-11-20 13:01:10 +01:00
James Cole
da6bcf04df New translations 2016-11-20 13:00:58 +01:00
James Cole
ec4ec1a147 New (not implemented) tests. 2016-11-20 12:53:04 +01:00
James Cole
350e0b08b1 This implements #377 2016-11-20 12:51:33 +01:00
James Cole
9340ca09e6 Fixed #408 2016-11-20 12:08:43 +01:00
James Cole
a1cef5c339 Found a bug in the import routine where "default accounts" (an account type no longer used by default) is found. 2016-11-20 11:44:27 +01:00
James Cole
94875adb6c Various code cleanup. 2016-11-20 11:43:19 +01:00
James Cole
75a524c656 Added debug code for a possible import issue. 2016-11-20 11:40:05 +01:00
James Cole
e1e94a788c Register and use interface. 2016-11-20 08:57:48 +01:00
James Cole
8417f45d02 Fixed some tests. 2016-11-20 08:54:52 +01:00
James Cole
685310a368 First account controller tests 2016-11-20 08:46:02 +01:00
James Cole
45e7a4576a Extend some test stuff. 2016-11-20 08:30:25 +01:00
James Cole
f8c5c15655 Updated some tests. 2016-11-20 07:24:18 +01:00
James Cole
26190524f4 Skeletons for test 2016-11-19 20:30:30 +01:00
James Cole
5d901a7ecb Remove local development file. [skip ci] 2016-11-19 18:21:48 +01:00
James Cole
929d8b3adc Merge branch 'release/4.1.7' 2016-11-19 16:47:02 +01:00
James Cole
cd6e37b9cb Update composer.lock file. [skip ci] 2016-11-19 16:45:33 +01:00
James Cole
b647386541 New release imminent. [skip ci] 2016-11-19 16:44:17 +01:00
James Cole
174fd88435 Merge pull request #409 from JC5/l10n_develop
New Crowdin translations
2016-11-19 16:43:44 +01:00
James Cole
cc9211b7c2 Translated 2016-11-19 16:40:48 +01:00
James Cole
a9795fb095 Update ignore file [skip ci] 2016-11-19 16:34:52 +01:00
James Cole
8554aae21e Update read me file [skip ci] 2016-11-19 16:31:39 +01:00
James Cole
5a2ef36f2a Fix travis script. 2016-11-19 16:28:04 +01:00
James Cole
01e3f91ece Do not test hhvm. Fix script. 2016-11-19 16:17:04 +01:00
James Cole
7ec9c090cc Fix test script. 2016-11-19 16:13:57 +01:00
James Cole
b057d69f8e Correct travis configuration. 2016-11-19 16:07:02 +01:00
James Cole
ff4e1838bc Update travis configuration. 2016-11-19 16:03:59 +01:00
James Cole
e4ecd0b7ff Empty travis CI file. 2016-11-19 16:01:19 +01:00
James Cole
1ba35f73e1 Fixed a test 2016-11-19 16:00:20 +01:00
James Cole
240f3c126b Restored some tests. 2016-11-19 15:55:49 +01:00
James Cole
23925a0076 Enabled cache [skip ci] 2016-11-19 15:17:00 +01:00
James Cole
50b72cf229 More chart optimisations. 2016-11-19 13:37:44 +01:00
James Cole
ee6b72afa5 Fix some bugs related to cash accounts. 2016-11-19 12:57:35 +01:00
James Cole
781621960d Make sure chart is displayed. 2016-11-19 09:26:32 +01:00
James Cole
e15ea04186 Join two charts, simpler code. 2016-11-19 07:27:54 +01:00
James Cole
73f0cc705b Code cleanup. 2016-11-18 20:06:08 +01:00
James Cole
0c072c7d51 Some code cleanup. 2016-11-18 19:58:06 +01:00
James Cole
884bed85a1 Update composer file. 2016-11-18 19:54:21 +01:00
James Cole
a319264428 fixed #406 2016-11-18 18:58:48 +01:00
James Cole
6506e70a91 Merge pull request #407 from JC5/l10n_develop
New Crowdin translations
2016-11-18 10:03:08 +01:00
James Cole
e6fcb19db7 New translations 2016-11-18 02:01:10 +01:00
James Cole
a3fba53182 Translated 2016-11-18 02:01:03 +01:00
James Cole
f8438dd9d3 New translations 2016-11-18 01:51:04 +01:00
James Cole
028a0dcae1 New translations 2016-11-18 01:41:05 +01:00
James Cole
b4a06b5bbd Translated 2016-11-18 01:41:01 +01:00
James Cole
4fe1a5d527 New translations 2016-11-18 01:30:59 +01:00
James Cole
865930c5b2 New translations 2016-11-18 01:30:58 +01:00
James Cole
96b4e2c196 New translations 2016-11-18 01:20:59 +01:00
James Cole
b7e7c7e9e2 New translations 2016-11-18 01:11:02 +01:00
James Cole
7771669db7 New translations 2016-11-18 01:01:09 +01:00
James Cole
ef59eb6e1f Translated 2016-11-18 01:01:05 +01:00
James Cole
a14b2bc5a7 Translated 2016-11-18 01:01:04 +01:00
James Cole
47349589cb New translations 2016-11-18 00:51:00 +01:00
James Cole
79afe84f30 Merge pull request #405 from JC5/l10n_develop
New Crowdin translations
2016-11-17 20:35:32 +01:00
James Cole
171187b25c New translations 2016-11-17 20:12:21 +01:00
James Cole
7f1b661e61 New translations 2016-11-17 20:12:18 +01:00
James Cole
2c2a3a5475 New translations 2016-11-17 20:12:08 +01:00
James Cole
1677ca9619 New translations 2016-11-17 20:12:00 +01:00
James Cole
204da3e846 New translations 2016-11-17 20:11:55 +01:00
James Cole
f36d423b1e New translations 2016-11-17 20:11:46 +01:00
James Cole
79c7280046 New translations 2016-11-17 20:11:32 +01:00
James Cole
e10fc4a854 Forgotten a translation. 2016-11-17 20:04:53 +01:00
James Cole
5088df103f Finished category report. 2016-11-17 20:02:55 +01:00
James Cole
13b96f6136 New text for translations. 2016-11-16 20:59:32 +01:00
James Cole
757662ca4b Removed duplicate code. 2016-11-16 20:59:21 +01:00
James Cole
4ef324cf24 Optimized chart code. 2016-11-16 20:35:25 +01:00
James Cole
cb02e0ee71 Merge pull request #404 from JC5/l10n_develop
New Crowdin translations
2016-11-16 18:59:17 +01:00
James Cole
ec3a90688e New translations 2016-11-16 15:01:33 +01:00
James Cole
6dcecdcc64 New translations 2016-11-16 06:40:59 +01:00
James Cole
25d917240d Translated 2016-11-16 06:30:58 +01:00
James Cole
0906915a87 New translations 2016-11-16 06:30:57 +01:00
James Cole
9c92a94177 Translated 2016-11-16 06:20:52 +01:00
James Cole
1b125ecd22 New translations 2016-11-16 04:50:52 +01:00
James Cole
25a2bcd76e New translations 2016-11-16 04:20:53 +01:00
James Cole
b2e09f4240 New translations 2016-11-15 23:11:13 +01:00
James Cole
560165850f New translations 2016-11-15 23:01:17 +01:00
James Cole
0bb07e1eeb Small extension of category report. 2016-11-13 20:18:01 +01:00
James Cole
0c0f2109f6 Fix chart size [skip ci] 2016-11-13 11:31:48 +01:00
James Cole
f546670342 Merge pull request #403 from JC5/l10n_develop
New Crowdin translations
2016-11-12 21:58:23 +01:00
James Cole
eecb6c6679 Optimize again for account name [skip ci] 2016-11-12 21:08:14 +01:00
James Cole
750b9d8038 Reduce number of queries. 2016-11-12 21:06:48 +01:00
James Cole
9ce28fdd2e Remove unused route. [skip ci] 2016-11-12 20:54:05 +01:00
James Cole
07af64ada5 New translations 2016-11-12 20:51:40 +01:00
James Cole
a0ab0ec902 New translations 2016-11-12 20:51:33 +01:00
James Cole
752f8582aa New translations 2016-11-12 20:51:27 +01:00
James Cole
4d0eed8c9b New translations 2016-11-12 20:51:23 +01:00
James Cole
0d7a8305f3 New translations 2016-11-12 20:51:17 +01:00
James Cole
2e8c0ec537 Approved. Step name: Proofread 2016-11-12 20:51:12 +01:00
James Cole
3155ec9e2b New translations 2016-11-12 20:51:01 +01:00
James Cole
7bbca7f6a8 Final code check for something with the debug bar [skip ci] 2016-11-12 20:48:29 +01:00
James Cole
f7579db4ad Clean up config [skip ci] 2016-11-12 20:41:15 +01:00
James Cole
2f47c58df5 New string for translation [skip ci] 2016-11-12 20:30:39 +01:00
James Cole
7e7ac264d2 Fixed category chart 2016-11-12 20:29:16 +01:00
James Cole
98d6c90e90 Removed some duplicate code. 2016-11-12 19:22:03 +01:00
James Cole
da49afa37b Removed duplicate code. 2016-11-12 19:12:16 +01:00
James Cole
64364c3e77 Sending of error email message is optional but enabled. 2016-11-12 19:11:59 +01:00
James Cole
b6f0fd1949 Translated 2016-11-12 19:11:04 +01:00
James Cole
0663a18f3a Translated 2016-11-12 19:11:03 +01:00
James Cole
c5928897eb New translations 2016-11-12 19:01:05 +01:00
James Cole
570373e875 Merge pull request #402 from JC5/l10n_develop
New Crowdin translations
2016-11-12 19:00:18 +01:00
James Cole
228afc2eea New translations 2016-11-12 12:31:45 +01:00
James Cole
6b61621d6a New translations 2016-11-12 12:31:42 +01:00
James Cole
424133fa83 New translations 2016-11-12 12:31:35 +01:00
James Cole
02e30c1fcc New translations 2016-11-12 12:31:28 +01:00
James Cole
e17a9d559b New translations 2016-11-12 12:31:25 +01:00
James Cole
36744377f6 New translations 2016-11-12 12:31:07 +01:00
James Cole
7c479f73c0 New translations 2016-11-12 12:31:00 +01:00
James Cole
85b3c4683b Fix redraw bug in category report. 2016-11-12 12:23:55 +01:00
James Cole
c5d2fabfec Optimize some views for category report 2016-11-12 12:12:11 +01:00
James Cole
a294f757ff Fixes all charts in future category report. 2016-11-12 10:14:20 +01:00
James Cole
04515da0bc Fixed the charts 2016-11-12 07:02:32 +01:00
James Cole
6d60d64a82 Some extended code for the category report. 2016-11-12 06:48:38 +01:00
James Cole
32b5a84a0c Fixes #401 2016-11-12 06:34:54 +01:00
James Cole
4b42ef0db8 Fixes #398 2016-11-12 06:27:48 +01:00
James Cole
abc7b9912d Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
2016-11-11 20:53:07 +01:00
James Cole
727717931a Do something fancy with colours. 2016-11-11 20:52:48 +01:00
James Cole
1d66b16468 Merge pull request #397 from JC5/l10n_develop
New Crowdin translations
2016-11-11 11:26:59 +01:00
James Cole
b918429c43 New translations 2016-11-10 06:30:56 +01:00
James Cole
888273d4a0 New translations 2016-11-10 06:30:54 +01:00
James Cole
31b5d5ba72 New translations 2016-11-10 06:30:47 +01:00
James Cole
b148d0868e New translations 2016-11-10 06:30:39 +01:00
James Cole
c1491383a8 New translations 2016-11-10 06:30:36 +01:00
James Cole
5f07918682 New translations 2016-11-10 06:30:17 +01:00
James Cole
8de6bd7ceb New translations 2016-11-10 06:30:10 +01:00
James Cole
5d4f1bc76d First working example of category report. No content, just place holders. #396 2016-11-10 06:23:21 +01:00
James Cole
8583b574ac Multi year was not visible. 2016-11-09 21:46:32 +01:00
James Cole
3600e1b5e7 Extend report capability for issue #396 and related report issues. 2016-11-09 21:36:54 +01:00
James Cole
fe57648349 Allow report options to be pulled using AJAX. Ajax is cool. 2016-11-09 19:25:09 +01:00
James Cole
f0e0cdb49b New website 2016-11-09 11:04:14 +01:00
James Cole
cf69333c6d This fixes #395 2016-11-08 21:34:13 +01:00
James Cole
3f7e16d270 Merge pull request #394 from JC5/l10n_develop
New Crowdin translations
2016-11-08 20:50:57 +01:00
James Cole
a63f1638f4 Upgrade some libraries for #391 2016-11-08 20:50:05 +01:00
James Cole
8ec2a3a391 New translations 2016-11-08 20:41:15 +01:00
James Cole
d875f0e580 New translations 2016-11-08 20:41:12 +01:00
James Cole
729534b4f3 New translations 2016-11-08 20:41:06 +01:00
James Cole
bd6a56a55e New translations 2016-11-08 20:41:04 +01:00
James Cole
96976db350 New translations 2016-11-08 20:40:58 +01:00
James Cole
8735190461 New translations 2016-11-08 20:40:55 +01:00
James Cole
709a14e5c9 New translations 2016-11-08 20:40:53 +01:00
James Cole
c89d2a52b5 New translations 2016-11-08 20:40:48 +01:00
James Cole
6084d16ea8 New translations 2016-11-08 20:40:45 +01:00
James Cole
1688fdb786 Approved. Step name: Proofread 2016-11-08 20:40:38 +01:00
James Cole
6cfb5ee2e9 Approved. Step name: Proofread 2016-11-08 20:40:33 +01:00
James Cole
2db560ed7d New translations 2016-11-08 20:40:27 +01:00
James Cole
45567cdf65 New translations 2016-11-08 20:40:24 +01:00
James Cole
508ad5157b New translations 2016-11-08 20:40:21 +01:00
James Cole
8fc41e0226 Fixes #390 2016-11-08 20:37:53 +01:00
James Cole
a08dfe1e3c Add interface for journal collector. 2016-11-08 20:36:09 +01:00
James Cole
49cc8a97a3 Clean up code, fixes #392 2016-11-08 20:35:30 +01:00
James Cole
5b8583dd2b Make sure scripts don't crash when no database present. 2016-11-07 20:25:09 +01:00
James Cole
f653bc5f6e Expand firefly config. 2016-11-07 18:49:35 +01:00
James Cole
a6a9794fc7 Merge branch 'release/4.1.6' into develop 2016-11-06 16:18:20 +01:00
James Cole
fdb8f61e37 Merge branch 'release/4.1.6' 2016-11-06 16:18:19 +01:00
James Cole
69422cc796 Code for 4.1.6 2016-11-06 16:17:22 +01:00
James Cole
5f9a9bc89a Change log for 4.1.6 2016-11-06 16:16:05 +01:00
James Cole
4d0d05e0f8 Merge pull request #383 from JC5/l10n_develop
New Crowdin translations
2016-11-06 16:14:05 +01:00
James Cole
0113fedbd4 Translated 2016-11-06 15:10:25 +01:00
James Cole
a7d35cd1c3 Fix multi year report. [skip ci] 2016-11-06 15:09:44 +01:00
James Cole
43600fe6cb Merge pull request #382 from JC5/l10n_develop
New Crowdin translations
2016-11-06 15:09:23 +01:00
James Cole
0b5e25960f Fix small JS bug. 2016-11-06 15:04:35 +01:00
James Cole
0c8a1b51e9 Quick bug fix: missing class. 2016-11-06 15:01:04 +01:00
James Cole
cb49f5e8d8 New translations 2016-11-06 15:01:02 +01:00
James Cole
a0e3088ca3 New translations 2016-11-06 15:00:54 +01:00
James Cole
b86be6f52f New translations 2016-11-06 15:00:47 +01:00
James Cole
4c573e1300 New translations 2016-11-06 15:00:43 +01:00
James Cole
1a3d77f117 New translations 2016-11-06 15:00:36 +01:00
James Cole
2656da13b1 Approved. Step name: Proofread 2016-11-06 15:00:29 +01:00
James Cole
d272ebd95c New translations 2016-11-06 15:00:18 +01:00
James Cole
7612f1f91a Small changes to twig files. 2016-11-06 14:52:48 +01:00
James Cole
22a2fe3f61 Improved search. 2016-11-06 14:52:31 +01:00
James Cole
1ebb59b352 Remove .twig extension. [skip ci] 2016-11-06 08:11:43 +01:00
James Cole
77e2cf40df Removed more getJournals functions in favour of the collector. 2016-11-06 08:08:06 +01:00
James Cole
0edffd8ea1 Lighter icon [skip ci] 2016-11-05 18:57:45 +01:00
James Cole
ee6e047596 Do not order the count query. 2016-11-05 18:55:09 +01:00
James Cole
bd55636b3f Add repository move info. 2016-11-05 18:51:26 +01:00
James Cole
b24e97a449 Update version and change log. 2016-11-05 18:50:13 +01:00
James Cole
d45355fc3f Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Translated
2016-11-05 18:46:10 +01:00
James Cole
b2206f640a Merge pull request #381 from JC5/l10n_develop
New Crowdin translations
2016-11-05 18:45:42 +01:00
James Cole
962cad33e2 Code cleanup. 2016-11-05 18:43:18 +01:00
James Cole
d65214b75a Translated 2016-11-05 18:40:12 +01:00
James Cole
7b4c151df5 Merge pull request #380 from JC5/l10n_develop
New Crowdin translations
2016-11-05 18:30:52 +01:00
James Cole
28d6f51961 New translations 2016-11-05 18:10:55 +01:00
James Cole
d2f9deb82b New translations 2016-11-05 18:10:48 +01:00
James Cole
d9b05b5f59 New translations 2016-11-05 18:10:42 +01:00
James Cole
a8f4b33c57 New translations 2016-11-05 18:10:39 +01:00
James Cole
ee849ea12f New translations 2016-11-05 18:10:32 +01:00
James Cole
f9d3cf231f Approved. Step name: Proofread 2016-11-05 18:10:27 +01:00
James Cole
0713ca7709 New translations 2016-11-05 18:10:17 +01:00
James Cole
1e2124c5ed Moved more stuff to the journal collector. 2016-11-05 18:08:44 +01:00
James Cole
37435da459 Moved more stuff to the journal collector. 2016-11-05 17:47:50 +01:00
James Cole
05dbd30bbd Rename another collector. 2016-11-05 17:17:56 +01:00
James Cole
4b947638a7 Merge pull request #379 from JC5/l10n_develop
New Crowdin translations
2016-11-05 15:16:25 +01:00
James Cole
3d113b9aae New translations 2016-11-05 14:30:14 +01:00
James Cole
d1b3681bf3 New translations 2016-11-05 14:20:16 +01:00
James Cole
9dd4b07314 New translations 2016-11-05 14:20:15 +01:00
James Cole
3814f0f3c3 New translations 2016-11-05 14:20:13 +01:00
James Cole
b1e907fae9 New translations 2016-11-05 14:10:15 +01:00
James Cole
5c03a1a9c8 New translations 2016-11-05 14:10:14 +01:00
James Cole
20ac07a386 Translated 2016-11-05 14:10:11 +01:00
James Cole
13e1292bb7 Automated code cleanup [skip ci] 2016-11-05 11:47:21 +01:00
James Cole
8e542531b3 Move collecting journals to the collector. 2016-11-05 11:44:41 +01:00
James Cole
43afdb021a Move collecting journals to the collector. 2016-11-05 11:24:15 +01:00
James Cole
aeca2ef3b2 Move some code around 2016-11-05 10:42:31 +01:00
James Cole
205a593721 Removed unused method. 2016-11-05 10:28:10 +01:00
James Cole
46649fe228 Solved group thing. 2016-11-05 10:26:57 +01:00
James Cole
adb97fcb05 Fix small javascript bug. 2016-11-05 08:47:05 +01:00
James Cole
98160e9b63 Expand use of journal collector. 2016-11-05 08:46:55 +01:00
James Cole
9c5d192d90 Journal collector may not have been a bad idea after all! 2016-11-05 08:27:25 +01:00
James Cole
47bebb614e Only withdrawal can have a budget. 2016-11-05 07:43:23 +01:00
James Cole
5f7fb77db2 Code to fix #378 2016-11-04 16:04:36 +01:00
James Cole
1d15bc0b10 I am changing some string concatenations to sprintf() routines because they are more readable and safer. [skip ci] 2016-11-03 21:54:07 +01:00
James Cole
7bc4c6d115 Update change log [skip ci] 2016-11-03 21:49:08 +01:00
James Cole
45973a53f5 Merge pull request #376 from JC5/l10n_develop
New Crowdin translations
2016-11-03 21:45:55 +01:00
James Cole
8e5e3de8b0 Update change log (prematurely). [skip ci] 2016-11-03 21:45:35 +01:00
James Cole
8738cd4b04 Approved. Step name: Proofread 2016-11-03 21:40:29 +01:00
James Cole
24a7dac235 Approved. Step name: Proofread 2016-11-03 21:40:28 +01:00
James Cole
a3088f6806 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
  Approved. Step name: Proofread
  New translations
  New translations
  New translations
  Translated
2016-11-03 21:07:48 +01:00
James Cole
72f7b5f3ea This fixes #375 2016-11-03 21:07:12 +01:00
James Cole
a636c508a2 Merge pull request #374 from JC5/l10n_develop
New Crowdin translations
2016-11-03 16:42:52 +01:00
James Cole
599db95f73 New translations 2016-11-02 22:31:16 +01:00
James Cole
f5f78ab79b New translations 2016-11-02 22:31:15 +01:00
James Cole
9af9383c29 New translations 2016-11-02 22:31:08 +01:00
James Cole
4b97b86c09 New translations 2016-11-02 22:31:07 +01:00
James Cole
11fb46830c New translations 2016-11-02 22:31:00 +01:00
James Cole
e8dec6d95c New translations 2016-11-02 22:31:00 +01:00
James Cole
bb4ee7470d New translations 2016-11-02 22:30:57 +01:00
James Cole
2e8071db9e New translations 2016-11-02 22:30:54 +01:00
James Cole
4d2901aa02 New translations 2016-11-02 22:30:50 +01:00
James Cole
37bbfab20a Approved. Step name: Proofread 2016-11-02 22:30:46 +01:00
James Cole
fb9161b82d Approved. Step name: Proofread 2016-11-02 22:30:43 +01:00
James Cole
000c9d8974 New translations 2016-11-02 22:30:36 +01:00
James Cole
878b664930 New translations 2016-11-02 22:30:33 +01:00
James Cole
afe28b5581 New translations 2016-11-02 22:30:33 +01:00
James Cole
4106b2e4c0 Remove some help entries in favour of help pages in the top right corner. 2016-11-02 22:23:40 +01:00
James Cole
e1be4909b9 Redirect when 0 accounts.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 21:24:16 +01:00
James Cole
7a0347c0c2 Translated 2016-11-02 21:00:38 +01:00
James Cole
a7e0e3fc15 Small additions and bug fixes.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 20:52:40 +01:00
James Cole
5e480eca36 Clean up some report code.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 20:45:11 +01:00
James Cole
6c8d594df7 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  New translations
  New translations
  New translations
  New translations
  Approved. Step name: Proofread
  New translations
  New translations

Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 20:08:38 +01:00
James Cole
e24f5ec9f3 Multi year report move to AJAX.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 20:08:11 +01:00
James Cole
1379c0652e Merge pull request #373 from JC5/l10n_develop
New Crowdin translations
2016-11-02 19:50:10 +01:00
James Cole
1f87b0bd2d New translations 2016-11-02 14:41:56 +01:00
James Cole
787a437ca4 New translations 2016-11-02 14:41:44 +01:00
James Cole
c0bdb35cb3 New translations 2016-11-02 14:41:34 +01:00
James Cole
4b9cf67413 New translations 2016-11-02 14:41:26 +01:00
James Cole
86ff3be741 Approved. Step name: Proofread 2016-11-02 14:41:09 +01:00
James Cole
8bc8e8d9fe New translations 2016-11-02 14:40:59 +01:00
James Cole
227a12d75d New translations 2016-11-02 14:40:54 +01:00
James Cole
2ddd4314f1 Extend help pages. 2016-11-02 14:33:57 +01:00
James Cole
b980b5baea Small optimisations.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 07:23:11 +01:00
James Cole
4ba34ab511 Show sum [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 07:16:46 +01:00
James Cole
5be317d73c sprintf ALL THE THINGS
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 07:04:14 +01:00
James Cole
af16205965 Merge branch 'master' into develop
* master:
  New budget table for multi year report.
  Removed everything pointless from multi year report.

Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 07:03:17 +01:00
James Cole
39917b77c1 New GitHub move repository instructions
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 07:02:22 +01:00
James Cole
124ecb1372 New budget table for multi year report.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-02 04:55:44 +01:00
James Cole
33c0c1bea6 Removed everything pointless from multi year report.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-01 19:06:35 +01:00
James Cole
a66990459e Merge branch 'release/4.1.5' 2016-11-01 18:45:25 +01:00
James Cole
fecbdc7fbf New version.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-11-01 18:44:26 +01:00
James Cole
0369ace5f7 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii: (28 commits)
  Approved. Step name: Proofread
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  New translations
  ...
2016-11-01 18:41:15 +01:00
James Cole
1657048181 Fixed bug #370 2016-11-01 18:40:35 +01:00
James Cole
b9bdaa7a56 Merge pull request #369 from JC5/l10n_develop
New Crowdin translations
2016-11-01 11:43:00 +01:00
James Cole
f28d07e17b Approved. Step name: Proofread 2016-11-01 11:40:36 +01:00
James Cole
8b8bf1debc New translations 2016-10-31 18:41:44 +01:00
James Cole
aff1c1e3ef New translations 2016-10-31 18:41:40 +01:00
James Cole
169bb2c9bb New translations 2016-10-31 18:41:29 +01:00
James Cole
fb1eafef43 New translations 2016-10-31 18:41:26 +01:00
James Cole
bfe26ceb39 New translations 2016-10-31 18:41:25 +01:00
James Cole
050f305e80 New translations 2016-10-31 18:41:24 +01:00
James Cole
63a6a4f823 New translations 2016-10-31 18:41:23 +01:00
James Cole
a3b167cab5 New translations 2016-10-31 18:41:23 +01:00
James Cole
48327948e2 New translations 2016-10-31 18:41:22 +01:00
James Cole
93856d4577 New translations 2016-10-31 18:41:21 +01:00
James Cole
7ff068aa95 New translations 2016-10-31 18:41:20 +01:00
James Cole
b2f00c869e New translations 2016-10-31 18:41:18 +01:00
James Cole
b717cab8f6 New translations 2016-10-31 18:41:17 +01:00
James Cole
adaff52707 New translations 2016-10-31 18:41:16 +01:00
James Cole
54050edcc6 New translations 2016-10-31 18:41:16 +01:00
James Cole
9acbb69a6a New translations 2016-10-31 18:41:15 +01:00
James Cole
a5e6de047a New translations 2016-10-31 18:41:14 +01:00
James Cole
3d8d35207b New translations 2016-10-31 18:41:13 +01:00
James Cole
0a95f59813 New translations 2016-10-31 18:41:10 +01:00
James Cole
43a3d28dbd New translations 2016-10-31 18:41:09 +01:00
James Cole
685cb7a505 Translated 2016-10-31 18:41:06 +01:00
James Cole
dd82466d07 Translated 2016-10-31 18:41:05 +01:00
James Cole
2cbe4a013e Translated 2016-10-31 18:41:04 +01:00
James Cole
fb85341844 Translated 2016-10-31 18:41:03 +01:00
James Cole
116b3ecdad Approved. Step name: Proofread 2016-10-31 18:40:58 +01:00
James Cole
af85fbf0a3 New translations 2016-10-31 18:40:50 +01:00
James Cole
1d250593c0 New translations 2016-10-31 18:40:45 +01:00
James Cole
ed33a054ad This update will make the help method fall back to the English content, if it is available. 2016-10-31 18:31:52 +01:00
James Cole
4e3e015912 Fix multi year account report [skip ci] 2016-10-30 20:13:49 +01:00
James Cole
7821c52842 Ajax some report parts. 2016-10-30 18:29:26 +01:00
James Cole
0a6f299ae6 Merge branch 'release/4.1.4' 2016-10-30 08:56:35 +01:00
James Cole
73f87e30c2 Changelog.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-30 08:52:09 +01:00
James Cole
838ece2c89 Merge pull request #368 from JC5/l10n_develop
New Crowdin translations
2016-10-30 07:32:23 +01:00
James Cole
d8b88ea2c0 New translations 2016-10-30 07:20:17 +01:00
James Cole
5908951b75 New translations 2016-10-30 07:20:17 +01:00
James Cole
0b41f4c4d2 New translations 2016-10-30 07:20:16 +01:00
James Cole
35439d4fbc New translations 2016-10-30 07:20:16 +01:00
James Cole
fdce40310f New translations 2016-10-30 07:20:15 +01:00
James Cole
6b4785ae32 New translations 2016-10-30 07:20:15 +01:00
James Cole
f74e8e9cb7 New translations 2016-10-30 07:20:13 +01:00
James Cole
5a4eb7e09e New translations 2016-10-30 07:20:12 +01:00
James Cole
3bc4df03cc New translations 2016-10-30 07:20:11 +01:00
James Cole
5d585132fb New translations 2016-10-30 07:20:11 +01:00
James Cole
eff4905883 New translations 2016-10-30 07:20:10 +01:00
James Cole
8923ac4fe3 New translations 2016-10-30 07:20:09 +01:00
James Cole
073535e5ed New translations 2016-10-30 07:20:09 +01:00
James Cole
d304b90ca6 New translations 2016-10-30 07:20:08 +01:00
James Cole
816c26e14e New translations 2016-10-30 07:20:07 +01:00
James Cole
b1244ffa01 New translations 2016-10-30 07:20:07 +01:00
James Cole
fc1342bff9 New translations 2016-10-30 07:20:06 +01:00
James Cole
d7b95194b5 New translations 2016-10-30 07:20:04 +01:00
James Cole
b58bdeccd2 New translations 2016-10-30 07:20:04 +01:00
James Cole
f260b9bdee New translations 2016-10-30 07:20:02 +01:00
James Cole
fb1bdc9ec5 New translations 2016-10-30 07:20:01 +01:00
James Cole
697eff48fc New translations 2016-10-30 07:20:00 +01:00
James Cole
c05019339a Approved. Step name: Proofread 2016-10-30 07:20:00 +01:00
James Cole
8438efaf41 Approved. Step name: Proofread 2016-10-30 07:19:59 +01:00
James Cole
81c019cc99 Translated 2016-10-30 07:19:59 +01:00
James Cole
c773fdc435 Approved. Step name: Proofread 2016-10-30 07:19:58 +01:00
James Cole
c1406f51f1 Approved. Step name: Proofread 2016-10-30 07:19:58 +01:00
James Cole
92affd3440 Approved. Step name: Proofread 2016-10-30 07:19:57 +01:00
James Cole
d3da0652ef Approved. Step name: Proofread 2016-10-30 07:19:57 +01:00
James Cole
e3fbbd6cf1 Translated 2016-10-30 07:19:56 +01:00
James Cole
fcff13470c Approved. Step name: Proofread 2016-10-30 07:19:56 +01:00
James Cole
e3061ee7e7 Approved. Step name: Proofread 2016-10-30 07:19:55 +01:00
James Cole
0ee305fc4a Approved. Step name: Proofread 2016-10-30 07:19:55 +01:00
James Cole
58b93fd0c4 Approved. Step name: Proofread 2016-10-30 07:19:53 +01:00
James Cole
b30217fa2d Approved. Step name: Proofread 2016-10-30 07:19:52 +01:00
James Cole
ae48eec3a2 Translated 2016-10-30 07:19:52 +01:00
James Cole
948233ba27 Translated 2016-10-30 07:19:52 +01:00
James Cole
c2db9b183a New translations 2016-10-30 07:19:51 +01:00
James Cole
6d2b88fa0b New translations 2016-10-30 07:19:51 +01:00
James Cole
1d5da825c5 New translations 2016-10-30 07:19:50 +01:00
James Cole
330c9b53d6 New translations 2016-10-30 07:19:50 +01:00
James Cole
751fe7d4fb New translations 2016-10-30 07:19:49 +01:00
James Cole
9df1fc6e5d New translations 2016-10-30 07:19:48 +01:00
James Cole
8d660f1701 New translations 2016-10-30 07:19:46 +01:00
James Cole
4d61d3c4aa New translations 2016-10-30 07:19:46 +01:00
James Cole
0457088c99 New translations 2016-10-30 07:19:45 +01:00
James Cole
8e575da74e New translations 2016-10-30 07:19:45 +01:00
James Cole
48ed28888e Translated 2016-10-30 07:19:43 +01:00
James Cole
4084b1124e Translated 2016-10-30 07:19:42 +01:00
James Cole
60ba607027 Translated 2016-10-30 07:19:42 +01:00
James Cole
3df2c11b4a Translated 2016-10-30 07:19:41 +01:00
James Cole
c93221923a Translated 2016-10-30 07:19:41 +01:00
James Cole
375317e932 New translations 2016-10-30 07:19:40 +01:00
James Cole
7ce527957a New translations 2016-10-30 07:19:40 +01:00
James Cole
6946521199 New translations 2016-10-30 07:19:39 +01:00
James Cole
18ee20e680 Update crowdin file [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-30 06:37:00 +01:00
James Cole
c53da15219 Update composer.lock in anticipation of new release.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-30 06:20:18 +01:00
James Cole
d4995e342f Fixed #330 2016-10-30 06:14:07 +01:00
James Cole
c9f14da294 Translations. 2016-10-29 17:30:55 +02:00
James Cole
e9c2446cba Debug log for #366 2016-10-29 16:16:10 +02:00
James Cole
35f179625c New queries for #366 2016-10-29 16:11:54 +02:00
James Cole
39749aa113 First code set for #330 2016-10-29 15:14:33 +02:00
James Cole
ba65e982fd Forgot to include model [skip ci] 2016-10-29 11:42:04 +02:00
James Cole
b50e5d7e59 Can also change destination in new rule. 2016-10-29 09:22:51 +02:00
James Cole
a3148dc172 Code for #321 2016-10-29 09:03:14 +02:00
James Cole
73f1491d2d Updates for translations. 2016-10-29 07:44:46 +02:00
James Cole
28eb54dc96 Initial split for report options. 2016-10-28 19:01:52 +02:00
James Cole
21fb426524 Make sure date is localised. 2016-10-28 18:16:30 +02:00
James Cole
d5710ca809 Update Crowdin configuration file 2016-10-28 14:06:41 +02:00
James Cole
0ba6cdda17 Merge pull request #364 from schoentoon/develop
Added dockerfile
2016-10-27 19:40:27 +02:00
James Cole
afdcfa8525 Tweak reports. 2016-10-26 19:45:10 +02:00
James Cole
5db4f8512b Tweak reports. 2016-10-26 19:37:19 +02:00
James Cole
dc0c1b73bc Better view for expenses. 2016-10-26 19:32:19 +02:00
James Cole
f999257095 New verify database routine. 2016-10-26 19:32:07 +02:00
James Cole
7182909e28 Keep the box [skip ci] 2016-10-26 16:54:52 +02:00
James Cole
fe3f015171 Add more stuff to ajax controllers, making report controller simpler. 2016-10-26 16:46:43 +02:00
Toon Schoenmakers
5bb668be63 Added dockerfile 2016-10-26 15:07:36 +02:00
James Cole
01de147900 Display message about common error. 2016-10-26 06:41:50 +02:00
James Cole
a7e5fcc806 Move some stuff over to AJAX thing. 2016-10-25 18:53:54 +02:00
James Cole
e2d187d74b Various small bug fixes. 2016-10-24 18:01:15 +02:00
James Cole
48b0620629 New help thing. 2016-10-23 17:33:53 +02:00
James Cole
19e9f382e4 Add some rounding to make forms more neat. 2016-10-23 16:56:18 +02:00
James Cole
446eaf6588 Some code cleanup [skip ci] 2016-10-23 14:58:39 +02:00
James Cole
78deb1420d Some fixes for bills. 2016-10-23 14:56:05 +02:00
James Cole
e092515dff Better export. 2016-10-23 12:55:07 +02:00
James Cole
81f6fef978 Add new line to files [skip ci] 2016-10-23 12:42:44 +02:00
James Cole
6a2f8fa9ee No use models directly. 2016-10-23 12:41:54 +02:00
James Cole
a79a8c8874 Various small upgrades. 2016-10-23 12:37:12 +02:00
James Cole
c39659b064 Remove a lot of references to user id. 2016-10-23 12:19:32 +02:00
James Cole
9a30fbd05a Move stuff to request classes for #339 2016-10-23 12:10:22 +02:00
James Cole
83f48418f6 Small updates [skip ci] 2016-10-23 09:57:04 +02:00
James Cole
bcd7b41c91 Simplified export. 2016-10-23 09:44:14 +02:00
James Cole
cefb7d12bc Merge branch 'release/4.1.3' 2016-10-22 22:45:27 +02:00
James Cole
3c0c15103e This fixes #361 2016-10-22 22:44:57 +02:00
James Cole
a8a8afc2be More for #339 2016-10-22 22:03:00 +02:00
James Cole
49e32abd3f Move some code for #339 2016-10-22 21:40:31 +02:00
James Cole
7977eefaca Merge branch 'release/4.1.2' 2016-10-22 20:52:54 +02:00
James Cole
f1fa6c3108 Fixed a bug in the store transaction routine. 2016-10-22 20:50:20 +02:00
James Cole
2fa0d55f39 Merge branch 'release/4.1.1' 2016-10-22 12:03:34 +02:00
James Cole
5bff509346 New translations.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-22 12:03:11 +02:00
James Cole
a147e9b74a Fix edit screen.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-22 11:53:34 +02:00
James Cole
0d87f7c4ca Better implementation of markdown.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-22 11:50:33 +02:00
James Cole
8c675615df Support markdown in notes.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-22 11:47:47 +02:00
James Cole
7edd1bff40 Merge branch 'release/4.1.0' 2016-10-22 10:21:15 +02:00
James Cole
3bfcb1f3ab New change log. [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-22 10:20:25 +02:00
James Cole
7b6c63e6a8 New version number [skip ci]
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
2016-10-22 10:15:50 +02:00
James Cole
5500e5b0aa Remove debug classes 2016-10-22 10:13:56 +02:00
James Cole
e4d249e73c Piggy bank supports notes (#350) 2016-10-22 10:13:49 +02:00
James Cole
091f6e918b Fix some reported issues. 2016-10-22 09:44:47 +02:00
James Cole
5d9b68c3e7 Various code cleanup [skip ci] 2016-10-22 09:39:31 +02:00
James Cole
12a6a61100 Various code cleanup [skip ci] 2016-10-22 09:33:03 +02:00
James Cole
7ce3b8d4ef Updated events, fixes #345 2016-10-22 09:31:27 +02:00
James Cole
3d9b855849 Force larval 5.3.18 2016-10-22 07:52:17 +02:00
James Cole
2346d2ec05 Fine tuning split edit screens. 2016-10-22 07:28:31 +02:00
James Cole
a4c081c8a5 Fix unset variable. [skip ci] 2016-10-21 22:01:42 +02:00
James Cole
316980efbd Fix unset variable. [skip ci] 2016-10-21 22:00:45 +02:00
James Cole
a05bc0eed0 Fix route [skip ci] 2016-10-21 21:57:10 +02:00
James Cole
4d1c271da6 Renamed a route [skip ci] 2016-10-21 21:54:57 +02:00
James Cole
0dd7ecbfbe Remove code no longer used. 2016-10-21 21:43:12 +02:00
James Cole
0dc188b083 Removed old code 2016-10-21 21:41:50 +02:00
James Cole
6a553f77f3 Large update to fix split journals. 2016-10-21 21:41:31 +02:00
James Cole
a74cef439b For simplicity, split controller. 2016-10-21 19:20:03 +02:00
James Cole
9a3cd27700 Many updates to get split transactions and normal transactions working side by side. 2016-10-21 19:06:22 +02:00
James Cole
801c7c0ab6 Remove unused function. 2016-10-21 13:22:45 +02:00
James Cole
a95a4e783a Fix and simplify bill repos 2016-10-21 13:20:51 +02:00
James Cole
af1ee9db93 This fixes bills unpaid. 2016-10-21 07:29:25 +02:00
James Cole
fcdb6fd2a7 Do loop instead of while loop [skip ci] 2016-10-21 06:41:33 +02:00
James Cole
97c0fb389d More logs [skip ci] 2016-10-21 06:38:00 +02:00
James Cole
a9c3992331 Back to old method [skip ci] 2016-10-21 06:33:56 +02:00
James Cole
a38e057fa7 Rewrote some methods to fix #341 2016-10-21 06:26:12 +02:00
James Cole
f83aaf77f1 Improve bill things for issue #341 2016-10-20 21:40:45 +02:00
James Cole
d92768ecbf This code fixes #349 2016-10-20 19:10:43 +02:00
James Cole
b9308cd74a Test flash messages. 2016-10-20 16:51:05 +02:00
James Cole
78b577bc9d Better ip info [skip ci] 2016-10-18 06:50:35 +02:00
James Cole
7d247897ed Should correctly show user info. [skip ci] 2016-10-18 06:47:48 +02:00
James Cole
5dcbdec491 Update composer file and update routine. [skip ci] 2016-10-15 18:52:21 +02:00
James Cole
9bf980431e Remove unused methods. 2016-10-15 14:07:51 +02:00
James Cole
da60bfbcff Better text [skip ci] 2016-10-15 14:05:56 +02:00
James Cole
92553cbc7e Add icon, missing translation [skip ci] 2016-10-15 12:41:45 +02:00
James Cole
8e48e53f17 Restucturing some code. 2016-10-15 12:39:34 +02:00
James Cole
2f9a4bb79a Better text 2016-10-15 12:39:11 +02:00
James Cole
ac968dd6cd Extended the user admin. 2016-10-15 07:11:53 +02:00
James Cole
6e4f2c0c8a Small script to upgrade transactions. 2016-10-15 06:19:21 +02:00
James Cole
d662c18ed7 Fix sorting in chart. [skip ci] 2016-10-14 20:07:15 +02:00
James Cole
e4ea234707 New revenue accounts chart. 2016-10-14 20:01:17 +02:00
James Cole
0b526c0168 New revenue chart 2016-10-14 19:59:10 +02:00
James Cole
2acde5c72a Option to show deposit accounts on the front page. 2016-10-14 19:52:30 +02:00
James Cole
ec8cf2c459 New preferences screen. 2016-10-14 19:48:19 +02:00
James Cole
3598780d54 This should at least catch #357 2016-10-14 19:18:00 +02:00
James Cole
35dd8ac6e6 Revert "This should at least catch #357"
This reverts commit 5ff7c7ffab.
2016-10-14 19:16:39 +02:00
James Cole
5ff7c7ffab This should at least catch #357 2016-10-14 19:16:28 +02:00
James Cole
399db47826 Merge branch 'release/4.0.2' 2016-10-14 17:15:47 +02:00
James Cole
148956a60d Some code reformatting. 2016-10-14 17:14:54 +02:00
James Cole
3670053a58 Some code reformatting [skip ci] 2016-10-14 17:14:28 +02:00
James Cole
e8e2b9704f New translations. 2016-10-14 17:14:04 +02:00
James Cole
fcdeebcc06 Some last minute updated texts. 2016-10-14 16:51:38 +02:00
James Cole
586ed82e88 New changelog. 2016-10-14 16:26:05 +02:00
James Cole
cc400d1e2e Merge pull request #356 from telyn/require-intl
Require PHP intl extension
2016-10-12 10:32:28 +02:00
Telyn
6edbfb27aa Add ext-intl to dependencies 2016-10-12 09:22:21 +01:00
James Cole
8fc9251b93 Fix name of language. [skip ci] 2016-10-10 19:08:09 +02:00
James Cole
10af888a97 Expand view [skip ci] 2016-10-10 13:27:35 +02:00
James Cole
89f2328846 Forgot include [skip ci] 2016-10-10 13:25:27 +02:00
James Cole
48e8cd20b4 Removed unused Twig methods. 2016-10-10 13:08:02 +02:00
James Cole
394ef23eda New local names [skip ci] 2016-10-10 08:27:08 +02:00
James Cole
62aa1eb487 Updated translations [skip ci] 2016-10-10 08:19:00 +02:00
James Cole
1500018ccc A new language arrives! [skip ci] 2016-10-10 08:13:27 +02:00
James Cole
23fad62d46 Completely removed account crud class. 2016-10-10 08:03:03 +02:00
James Cole
3cbf00734f Remove storeMeta 2016-10-10 07:53:25 +02:00
James Cole
1dc17dd59d Move getActiveAccountsByType 2016-10-10 07:53:12 +02:00
James Cole
f8935c92ea Unrelated code cleanup. 2016-10-10 07:49:55 +02:00
James Cole
de6f838413 Moved getAccountsByType 2016-10-10 07:49:39 +02:00
James Cole
e8a095e543 Moved getAccountsById 2016-10-10 07:25:27 +02:00
James Cole
717c1d080e Copied (not yet removed) findByName 2016-10-10 07:20:49 +02:00
James Cole
0ae9afd325 Move findByIban 2016-10-10 07:16:05 +02:00
James Cole
d1b56c2afa Moved findByAccountNumber 2016-10-10 07:14:01 +02:00
James Cole
8ef7c5ac33 Moved find() method to new class. 2016-10-10 07:12:39 +02:00
James Cole
7180a40cd8 Refactored some methods surrounding the opening balance of an account. 2016-10-10 07:01:14 +02:00
James Cole
71804af624 Updated some model code. 2016-10-10 06:50:24 +02:00
James Cole
85dc7f3643 Moved another method. 2016-10-10 06:49:50 +02:00
James Cole
a866d13b75 Forgot to add argument 2016-10-10 06:49:39 +02:00
James Cole
fcb5e4eabc Moved leftOnAccount() 2016-10-10 06:47:42 +02:00
James Cole
ade1cf9c19 Fixed wrong listing. 2016-10-10 06:40:50 +02:00
James Cole
0f1ec7d003 Removed double method. 2016-10-09 21:49:31 +02:00
James Cole
7e038afece Must be unsigned 2016-10-09 21:36:22 +02:00
James Cole
9bb8e182fa Forgot a translation 2016-10-09 21:36:15 +02:00
James Cole
e94ae126fd Refactored accountRepository::getJournals > accountTasker > getJournals 2016-10-09 21:36:03 +02:00
James Cole
5bb8c6a366 This should fix #355 2016-10-09 20:18:46 +02:00
James Cole
30844df5d4 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Fixed issue causing all imported transactions to have unknown opposing account with ABN AMRO specific
2016-10-09 20:18:14 +02:00
James Cole
63e4a410a7 Merge pull request #354 from roberthorlings/bugfix/abn-amro-specific
Bugfix for issue with ABN AMRO specific
2016-10-09 20:00:48 +02:00
Robert Horlings
ee9a5d91e2 Merge branch 'develop' into bugfix/abn-amro-specific 2016-10-09 19:53:11 +02:00
Robert Horlings
171ab8a4c3 Fixed issue causing all imported transactions to have unknown opposing account with ABN AMRO specific 2016-10-09 17:19:00 +02:00
James Cole
96740aaac4 Extend transaction model for #351 2016-10-09 17:06:52 +02:00
James Cole
2017720096 Experimental new getJournals method. 2016-10-09 16:22:08 +02:00
James Cole
b77ea6d316 Add some phpdoc 2016-10-09 11:21:41 +02:00
James Cole
f5adb4047f Remove methods no longer used. 2016-10-09 10:59:28 +02:00
James Cole
b082858866 Removed unused blocks from the front page. Savings and piggy banks. 2016-10-09 10:58:54 +02:00
James Cole
a8a014189d Removed method that was already there under another name. 2016-10-09 10:57:06 +02:00
James Cole
39ea9e85a7 Various code cleanup and refactoring. Restored cache. 2016-10-09 10:53:37 +02:00
James Cole
a4d2ed74fc Make sure all journals are included. 2016-10-09 09:41:03 +02:00
James Cole
90f2e27f1f Refactoring income and expense reports. 2016-10-09 09:32:12 +02:00
James Cole
a3359ba47a Moved destroy() method from CRUD to Account repos. 2016-10-09 08:20:29 +02:00
James Cole
1d2d3523d6 Move CRUD method count() to account repository 2016-10-09 08:18:47 +02:00
James Cole
3f40751a1a Forgot to exclude a method. 2016-10-09 08:06:49 +02:00
James Cole
b5b55e862c Clean up code. 2016-10-09 07:59:14 +02:00
James Cole
c64771b76b Move some methods around, refactoring. 2016-10-09 07:58:27 +02:00
James Cole
ea7ee7ee9a Moved a report out of the controller. 2016-10-08 16:24:07 +02:00
James Cole
a1f797c4d1 Moved a method around. 2016-10-08 16:04:05 +02:00
James Cole
d0c92a2244 Clean up account report helper. 2016-10-08 15:59:58 +02:00
James Cole
6e90c033b1 Start of some remodelling. 2016-10-08 14:54:32 +02:00
James Cole
24f62b8fce Some minor refactoring. 2016-10-08 10:02:33 +02:00
James Cole
d43936155c Removed some unused code. 2016-10-07 16:33:17 +02:00
James Cole
39dab4fdd9 Remove unused class. 2016-10-07 12:28:14 +02:00
James Cole
c0fdf44ad2 Small cleaning up. 2016-10-07 11:40:03 +02:00
James Cole
4d91f7d23a This fixes #344 2016-10-07 09:40:50 +02:00
James Cole
49af6522a8 Some code cleanup. 2016-10-07 05:44:21 +02:00
James Cole
3c5f9487a8 Prep change log for next version [skip ci] 2016-10-07 05:43:47 +02:00
James Cole
f5cb87f5c3 Merge pull request #348 from SanderKleykens/feature/postgres-compatibility
PostgreSQL compatibility
2016-10-07 05:32:10 +02:00
Sander Kleykens
cf543613c9 Fix the CSV importer failing when using PostgreSQL
Add ordered column to the list of columns that are selected so PostgreSQL doesn't throw an error
2016-10-06 23:49:33 +02:00
Sander Kleykens
5c239c91db Convert raw XORs to a construct compatible with Laravel's query builder 2016-10-06 22:27:10 +02:00
James Cole
9920504232 Fixes #346 2016-10-06 05:26:38 +02:00
James Cole
5540697dbd Removed a method no longer necessary. 2016-10-05 16:09:37 +02:00
James Cole
b355c18e0c Some code cleanup and copyright cleanup. [skip ci] 2016-10-05 06:52:15 +02:00
James Cole
1e90485c5f Merge branch 'master' into develop
* master:
  added some comments
  removed some debug commands
  Better descriptions for ING accounts
2016-10-05 06:31:47 +02:00
James Cole
dc784c53b5 Fix for #343 2016-10-04 21:51:46 +02:00
James Cole
5a47391a64 Merge branch 'release/4.0.1' 2016-10-04 20:13:50 +02:00
James Cole
8a106bd16a Merge branch 'release/4.0.1' into develop 2016-10-04 20:13:50 +02:00
James Cole
a31ac79173 New version. 2016-10-04 20:13:40 +02:00
James Cole
0d0a604254 Changelog for 4.0.1 [skip ci] 2016-10-04 20:13:09 +02:00
James Cole
724d25f2c2 Merge branch 'develop'
* develop:
  Fixed some rare bugs.
  Extra clear button to reapply rules #307
  Fix trim when null [skip ci]
  Fixed a bug where incoming transactions would not be properly filtered in several reports.
  Removed for #334
  Fix #337 [skip ci]
  Fix #335
  Remove account extra text #336 [skip ci]
  Fixes bug #338
  Refer to correct page [skip ci]
  Catch unset row.
2016-10-04 20:08:35 +02:00
James Cole
8ed22d452d Merge pull request #342 from tomwerf/master
ING Import
2016-10-04 20:02:34 +02:00
Tom van der Werf
d7fef45a56 added some comments 2016-10-04 17:50:01 +00:00
Tom van der Werf
dc22802dec removed some debug commands 2016-10-04 17:30:49 +00:00
Tom van der Werf
ce5af7b1d9 Better descriptions for ING accounts 2016-10-03 17:08:24 +00:00
James Cole
0a147e5c9c Fixed some rare bugs. 2016-10-02 15:09:43 +02:00
James Cole
7d21255f7f Extra clear button to reapply rules #307 2016-10-02 08:14:11 +02:00
James Cole
13f952f182 Fix trim when null [skip ci] 2016-10-01 09:41:16 +02:00
James Cole
b494be228b Fixed a bug where incoming transactions would not be properly filtered in several reports. 2016-10-01 09:37:18 +02:00
James Cole
0fdaac53d0 Removed for #334 2016-10-01 08:49:33 +02:00
James Cole
e1b3a08878 Fix #337 [skip ci] 2016-10-01 08:49:02 +02:00
James Cole
dc893588b0 Fix #335 2016-10-01 08:48:13 +02:00
James Cole
b9fcc443ec Remove account extra text #336 [skip ci] 2016-10-01 08:45:14 +02:00
James Cole
d8586c8043 Fixes bug #338 2016-09-29 19:17:24 +02:00
James Cole
4252a3e53b Refer to correct page [skip ci] 2016-09-29 07:04:58 +02:00
James Cole
dbb5cdb9cf Catch unset row. 2016-09-29 07:02:47 +02:00
James Cole
3ec8a8c375 Merge branch 'release/4.0.0' into develop 2016-09-26 18:37:33 +02:00
948 changed files with 44822 additions and 27931 deletions

View File

@@ -35,13 +35,17 @@ MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
SEND_REGISTRATION_MAIL=true
MUST_CONFIRM_ACCOUNT=false
SEND_ERROR_MESSAGE=true
SHOW_INCOMPLETE_TRANSLATIONS=false
CACHE_PREFIX=firefly
ANALYTICS_ID=
SITE_OWNER=mail@example.com
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
DEMO_USERNAME=
DEMO_PASSWORD=

45
.env.testing Executable file
View File

@@ -0,0 +1,45 @@
APP_ENV=testing
APP_DEBUG=true
APP_FORCE_SSL=false
APP_FORCE_ROOT=
APP_KEY=TestTestTestTestTestTestTestTest
APP_LOG_LEVEL=debug
APP_URL=http://localhost
DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USERNAME=homestead
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
COOKIE_PATH="/"
COOKIE_DOMAIN=
COOKIE_SECURE=false
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
SEND_REGISTRATION_MAIL=true
SEND_ERROR_MESSAGE=true
SHOW_INCOMPLETE_TRANSLATIONS=false
ANALYTICS_ID=
SITE_OWNER=mail@example.com
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@ result.html
test-import.sh
test-import-report.txt
public/google*.html
.env.backup

17
.travis.yml Normal file
View File

@@ -0,0 +1,17 @@
language: php
sudo: false
php:
- '7.0'
install:
- phpenv config-rm xdebug.ini
- rm composer.lock
- composer update --no-scripts
- php artisan clear-compiled
- php artisan optimize
- php artisan env
- cp .env.testing .env
- mv storage/database/databasecopy.sqlite storage/database/database.sqlite
script:
- phpunit

View File

@@ -2,7 +2,228 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [4.0.0] - 2015-05-25
## [4.3.0] - 2015-12-26
### Added
- New method of keeping track of available budget, see issue #489
- Support for Spanish
- Firefly III now has an extended demo mode. Will expand further in the future.
### Changed
- New favicon
- Import routine no longer gives transactions a description #483
### Removed
- All test data generation code.
### Fixed
- Removed import accounts from search results #478
- Redirect after delete will no longer go back to deleted item #477
- Cannot math #482
- Fixed bug in virtual balance field #479
## [4.2.2] - 2016-12-18
### Added
- New budget report (still a bit of a beta)
- Can now edit user
### Changed
- New config for specific events. Still need to build Notifications.
### Fixed
- Various bugs
- Issue #472 thanks to @zjean
## [4.2.1] - 2016-12-09
### Added
- BIC support (see #430)
- New category report section and chart (see the general financial report)
### Changed
- Date range picker now also available on mobile devices (see #435)
- Extended range of amounts for issue #439
- Rewrote all routes. Old bookmarks may break.
## [4.2.0] - 2016-11-27
### Added
- Lots of (empty) tests
- Expanded transaction lists (#377)
- New charts at account view
- First code for #305
### Changed
- Updated all email messages.
- Made some fonts local
### Deprecated
- Initial release.
### Removed
- Initial release.
### Fixed
- Issue #408
- Various issues with split journals
- Issue #414, thx @zjean
- Issue #419, thx @schwalberich
- Issue #422, thx @xzaz
- Various import bugs, such as #416 (@zjean)
### Security
- Initial release.
## [4.1.7] - 2016-11-19
### Added
- Check for database table presence in console commands.
- Category report
- Reinstated old test routines.
### Changed
- Confirm account setting is no longer in `.env` file.
- Titles are now in reverse (current page > parent > firefly iii)
- Easier update of language files thanks to Github implementation.
- Uniform colours for charts.
### Fixed
- Made all pages more mobile friendly.
- Fixed #395 found by @marcoveeneman.
- Fixed #398 found by @marcoveeneman.
- Fixed #401 found by @marcoveeneman.
- Many optimizations.
- Updated many libraries.
- Various bugs found by myself.
## [4.1.6] - 2016-11-06
### Added
- New budget table for multi year report.
### Changed
- Greatly expanded help pages and their function.
- Built a new transaction collector, which I think was the idea of @roberthorlings originally.
- Rebuilt seach engine.
### Fixed
- #375, thanks to @schoentoon which made it impossible to resurrect currencies.
- #370 thanks to @ksmolder
- #378, thanks to @HomelessAvatar
## [4.1.5] - 2016-11-01
### Changed
- Report parts are loaded using AJAX, making a lot of code more simple.
- Help content will fall back to English.
- Help content is translated through Crowdin.
### Fixed
- Issue #370
## [4.1.4] - 2016-10-30
### Added
- New Dockerfile thanks to @schoentoon
- Added changing the destination account as rule action.
- Added changing the source account as rule action.
- Can convert transactions into different types.
### Changed
- Changed the export routine to be more future-proof.
- Improved help routine.
- Integrated CrowdIn translations.
- Simplified reports
- Change error message to refer to solution.
### Fixed
- #367 thanks to @HungryFeline
- #366 thanks to @3mz3t
- #362 and #341 thanks to @bnw
- #355 thanks to @roberthorlings
## [4.1.3] - 2016-10-22
### Fixed
- Some event handlers called the wrong method.
## [4.1.2] - 2016-10-22
### Fixed
- A bug is fixed in the journal event handler that prevented Firefly III from actually storing journals.
## [4.1.1] - 2016-10-22
### Added
- Option to show deposit accounts on the front page.
- Script to upgrade split transactions
- Can now save notes on piggy banks.
- Extend user admin options.
- Run import jobs from the command line
### Changed
- New preferences screen layout.
### Deprecated
- ``firefly:import`` is now ``firefly:start-import``
### Removed
- Lots of old code
### Fixed
- #357, where non utf-8 files would break Firefly.
- Tab delimiter is not properly loaded from import configuration (@roberthorlings)
- System response to yearly bills
## [4.0.2] - 2016-10-14
### Added
- Added ``intl`` dependency to composer file to ease installation (thanks @telyn)
- Added support for Croatian.
### Changed
- Updated all copyright notices to refer to the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)
- Fixed #344
- Fixed #346, thanks to @SanderKleykens
- #351
- Did some internal remodelling.
### Fixed
- PostgreSQL compatibility thanks to @SanderKleykens
- @RobertHorlings fixed a bug in the ABN Amro import specific.
## [4.0.1] - 2016-10-04
### Added
- New ING import specific by @tomwerf
- New Presidents Choice specific to fix #307
- Added some trimming (#335)
### Changed
- Initial release.
### Deprecated
- Initial release.
### Removed
- Initial release.
### Fixed
- Fixed a bug where incoming transactions would not be properly filtered in several reports.
- #334 by @cyberkov
- #337
- #336
- #338 found by @roberthorlings
### Security
- Initial release.
## [4.0.0] - 2015-09-26
### Added
- Upgraded to Laravel 5.3, most other libraries upgraded as well.
- Added GBP as currency, thanks to @Mortalife

42
Dockerfile Normal file
View File

@@ -0,0 +1,42 @@
FROM php:7-apache
RUN apt-get update -y && \
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
zlib1g-dev \
libjpeg62-turbo-dev \
libpng12-dev \
libicu-dev \
libmcrypt-dev \
libedit-dev \
libtidy-dev \
libxml2-dev \
libsqlite3-dev \
libbz2-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN docker-php-ext-install -j$(nproc) curl gd intl json mcrypt readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2
# Enable apache mod rewrite..
RUN a2enmod rewrite
# Setup the Composer installer
RUN curl -o /tmp/composer-setup.php https://getcomposer.org/installer && \
curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig && \
php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" && \
chmod +x /tmp/composer-setup.php && \
php /tmp/composer-setup.php && \
mv composer.phar /usr/local/bin/composer && \
rm -f /tmp/composer-setup.{php,sig}
ADD . /var/www/firefly-iii
RUN chown -R www-data:www-data /var/www/
ADD docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
USER www-data
WORKDIR /var/www/firefly-iii
RUN composer install --no-scripts --no-dev
USER root

View File

@@ -1,16 +1,24 @@
# 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)
# Firefly III: A personal finances manager
## A personal finances manager
[![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)
[![Screenshot](https://i.nder.be/hhfv03hp/400)](https://i.nder.be/hhfv03hp) [![Screenshot](https://i.nder.be/hhmwmqw9/400)](https://i.nder.be/hhmwmqw9)
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=master)](https://travis-ci.org/JC5/firefly-iii) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
[![Screenshot](https://i.nder.be/g63q05m0/400)](https://i.nder.be/g63q05m0) [![Screenshot](https://i.nder.be/c2g30ngg/400)](https://i.nder.be/c2g30ngg)
[![The index of Firefly III](https://i.nder.be/hurdhgyg/400)](https://i.nder.be/h2b37243) [![The account overview of Firefly III](https://i.nder.be/hnkfkdpr/400)](https://i.nder.be/hv70pbwc)
[![The useful financial reports of Firefly III](https://i.nder.be/h7sk6nb7/400)](https://i.nder.be/ccn0u2mp) [![Even more useful reports in Firefly III](https://i.nder.be/g237hr35/400)](https://i.nder.be/gm8hbh7z)
_(You can click on the images for a better view)_
"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.
## Try it out!
Try out Firefly III on the [demo site](https://firefly-iii.nder.be/).
## 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/).
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://firefly-iii.github.io/installation-guide/).
## More about Firefly III
@@ -25,6 +33,8 @@ Firefly works on the principle that if you know where you're money is going, you
- Firefly has lots of features without becoming fancy or bloated.
- 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/).
Firefly is pretty awesome. [You can read more about Firefly III, and its features, on the Github Pages](https://firefly-iii.github.io/).
If you like Firefly and if it helps you save lots of money, why not send me [a dime for every dollar saved](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA) (this is a joke, although the Paypal form works just fine, try it!)
If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com).

View File

@@ -3,8 +3,10 @@
* ConfigureLogging.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -0,0 +1,144 @@
<?php
/**
* CreateImport.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console\Commands;
use Artisan;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Illuminate\Console\Command;
use Log;
/**
* Class CreateImport
*
* @package FireflyIII\Console\Commands
*/
class CreateImport extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Use this command to create a new import. Your user ID can be found on the /profile page.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly:create-import {file} {configuration} {--user=1} {--type=csv} {--start}';
/**
* Create a new command instance.
*
*/
public function __construct()
{
parent::__construct();
}
/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
*/
public function handle()
{
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
$file = $this->argument('file');
$configuration = $this->argument('configuration');
$user = $userRepository->find(intval($this->option('user')));
$cwd = getcwd();
$type = strtolower($this->option('type'));
if (!$this->validArguments()) {
return;
}
$configurationData = json_decode(file_get_contents($configuration));
if (is_null($configurationData)) {
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return;
}
$this->info(sprintf('Going to create a job to import file: %s', $file));
$this->info(sprintf('Using configuration file: %s', $configuration));
$this->info(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
$this->info(sprintf('Type of import: %s', $type));
/** @var ImportJobRepositoryInterface $jobRepository */
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
$job = $jobRepository->create($type);
$this->line(sprintf('Created job "%s"...', $job->key));
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
$this->line('Stored import data...');
$job->configuration = $configurationData;
$job->status = 'settings_complete';
$job->save();
$this->line('Stored configuration...');
if ($this->option('start') === true) {
$this->line('The import will start in a moment. This process is not visible...');
Log::debug('Go for import!');
Artisan::call('firefly:start-import', ['key' => $job->key]);
$this->line('Done!');
}
return;
}
/**
* @return bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
*/
private function validArguments(): bool
{
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
$file = $this->argument('file');
$configuration = $this->argument('configuration');
$user = $userRepository->find(intval($this->option('user')));
$cwd = getcwd();
$validTypes = array_keys(config('firefly.import_formats'));
$type = strtolower($this->option('type'));
if (is_null($user->id)) {
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
return false;
}
if (!in_array($type, $validTypes)) {
$this->error(sprintf('Cannot import file of type "%s"', $type));
return false;
}
if (!file_exists($file)) {
$this->error(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
return false;
}
if (!file_exists($configuration)) {
$this->error(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
return true;
}
}

View File

@@ -3,8 +3,10 @@
* EncryptFile.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -3,8 +3,10 @@
* Import.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -16,6 +18,7 @@ use FireflyIII\Import\Logging\CommandHandler;
use FireflyIII\Models\ImportJob;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Log;
/**
@@ -30,14 +33,14 @@ class Import extends Command
*
* @var string
*/
protected $description = 'Import stuff into Firefly III.';
protected $description = 'This will start a new import.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly:import {key}';
protected $signature = 'firefly:start-import {key}';
/**
* Create a new command instance.
@@ -49,49 +52,33 @@ class Import extends Command
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Log::debug('Start start-import command');
$jobKey = $this->argument('key');
$job = ImportJob::whereKey($jobKey)->first();
if (!$this->isValid($job)) {
Log::error('Job is not valid for some reason. Exit.');
return;
}
$this->line('Going to import job with key "' . $job->key . '" of type ' . $job->file_type);
$this->line(sprintf('Going to import job with key "%s" of type "%s"', $job->key, $job->file_type));
$monolog = Log::getMonolog();
$handler = new CommandHandler($this);
$monolog->pushHandler($handler);
$importProcedure = new ImportProcedure;
$result = $importProcedure->runImport($job);
$result = ImportProcedure::runImport($job);
/**
* @var int $index
* @var TransactionJournal $journal
*/
foreach ($result as $index => $journal) {
if (!is_null($journal->id)) {
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
continue;
}
$this->error(sprintf('Could not store line #%d', $index));
}
// display result to user:
$this->presentResults($result);
$this->line('The import has completed.');
// get any errors from the importer:
$extendedStatus = $job->extended_status;
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
foreach ($extendedStatus['errors'] as $error) {
$this->error($error);
}
}
$this->presentErrors($job);
return;
}
@@ -117,4 +104,36 @@ class Import extends Command
return true;
}
/**
* @param ImportJob $job
*/
private function presentErrors(ImportJob $job)
{
$extendedStatus = $job->extended_status;
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
foreach ($extendedStatus['errors'] as $error) {
$this->error($error);
}
}
}
/**
* @param Collection $result
*/
private function presentResults(Collection $result)
{
/**
* @var int $index
* @var TransactionJournal $journal
*/
foreach ($result as $index => $journal) {
if (!is_null($journal->id)) {
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
continue;
}
$this->error(sprintf('Could not store line #%d', $index));
}
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* MoveRepository.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
/**
* Class MoveRepository
*
* @package FireflyIII\Console\Commands
*/
class MoveRepository extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Alerts the user that the Github repository will move, if they are interested to know this.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly:github-move';
/**
* Create a new command instance.
*
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
$moveDate = new Carbon('2017-01-01');
$final = new Carbon('2017-03-01');
$now = new Carbon;
// display message before 2017-01-01
if ($moveDate > $now) {
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
$this->line('The Github repository for Firefly III will MOVE');
$this->line('This move will be on January 1st 2017');
$this->line('');
$this->error('READ THIS WIKI PAGE FOR MORE INFORMATION');
$this->line('');
$this->info('https://github.com/firefly-iii/help/wiki/New-Github-repository');
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
}
// display message after 2017-01-01 but before 2017-03-01
if ($moveDate <= $now && $now <= $final) {
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
$this->line('The Github repository for Firefly III has MOVED');
$this->line('This move was on January 1st 2017!');
$this->line('');
$this->error('READ THIS WIKI PAGE FOR MORE INFORMATION');
$this->line('');
$this->info('https://github.com/firefly-iii/help/wiki/New-Github-repository');
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
}
}
}

View File

@@ -3,8 +3,10 @@
* ScanAttachments.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -58,42 +60,26 @@ class ScanAttachments extends Command
/** @var Attachment $attachment */
foreach ($attachments as $attachment) {
$fileName = $attachment->fileName();
// try to grab file content:
try {
$content = $disk->get($fileName);
} catch (FileNotFoundException $e) {
$this->error(sprintf('Could not find data for attachment #%d', $attachment->id));
continue;
}
// try to decrypt content.
try {
$decrypted = Crypt::decrypt($content);
} catch (DecryptException $e) {
$this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id));
continue;
}
// make temp file:
$tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII');
// store content in temp file:
file_put_contents($tmpfname, $decrypted);
// get md5 and mime
$md5 = md5_file($tmpfname);
$mime = mime_content_type($tmpfname);
// update attachment:
$md5 = md5_file($tmpfname);
$mime = mime_content_type($tmpfname);
$attachment->md5 = $md5;
$attachment->mime = $mime;
$attachment->save();
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
// find file:
}
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* UpgradeDatabase.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console\Commands;
use DB;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
use Log;
use Schema;
/**
* Class UpgradeDatabase
*
* @package FireflyIII\Console\Commands
*/
class UpgradeDatabase extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Will run various commands to update database records.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly:upgrade-database';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
$this->setTransactionIdentifier();
}
/**
* This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird.
*/
private function setTransactionIdentifier()
{
// if table does not exist, return false
if (!Schema::hasTable('transaction_journals')) {
return;
}
$subQuery = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->groupBy(['transaction_journals.id'])
->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]);
$result = DB::table(DB::raw('(' . $subQuery->toSql() . ') AS derived'))
->mergeBindings($subQuery->getQuery())
->where('t_count', '>', 2)
->select(['id', 't_count']);
$journalIds = array_unique($result->pluck('id')->toArray());
foreach ($journalIds as $journalId) {
// grab all positive transactiosn from this journal that are not deleted.
// for each one, grab the negative opposing one which has 0 as an identifier and give it the same identifier.
$identifier = 0;
$processed = [];
$transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get();
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
// find opposing:
$amount = bcmul(strval($transaction->amount), '-1');
try {
/** @var Transaction $opposing */
$opposing = Transaction::where('transaction_journal_id', $journalId)
->where('amount', $amount)->where('identifier', '=', 0)
->whereNotIn('id', $processed)
->first();
} catch (QueryException $e) {
Log::error($e->getMessage());
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
$this->error(sprintf('This field is required for Firefly III version %s to run.', config('firefly.version')));
$this->error('Please run "php artisan migrate" to add this field to the table.');
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
break 2;
}
if (!is_null($opposing)) {
// give both a new identifier:
$transaction->identifier = $identifier;
$transaction->save();
$opposing->identifier = $identifier;
$opposing->save();
$processed[] = $transaction->id;
$processed[] = $opposing->id;
$this->line(sprintf('Database upgrade for journal #%d, transactions #%d and #%d', $journalId, $transaction->id, $opposing->id));
}
$identifier++;
}
}
}
}

View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -61,21 +63,20 @@ class UpgradeFireflyInstructions extends Command
}
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
if (is_null($text)) {
$this->line('Thank you for installing Firefly III, v' . $version);
$this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
$this->info('There are no extra upgrade instructions.');
$this->line('Firefly III should be ready for use.');
} else {
$this->line('Thank you for installing Firefly III, v' . $version);
$this->line('If you are upgrading from a previous version,');
$this->line('please follow these upgrade instructions carefully:');
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
$this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
$this->info(wordwrap($text));
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
}
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
}
}

View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -13,16 +15,17 @@ namespace FireflyIII\Console\Commands;
use Crypt;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Eloquent\Builder;
use Schema;
use stdClass;
/**
@@ -58,16 +61,21 @@ class VerifyDatabase extends Command
*/
public function handle()
{
// if table does not exist, return false
if (!Schema::hasTable('users')) {
return;
}
$this->reportObject('budget');
$this->reportObject('category');
$this->reportObject('tag');
// accounts with no transactions.
$this->reportAccounts();
// budgets with no limits
$this->reportBudgetLimits();
// budgets with no transactions
$this->reportBudgets();
// categories with no transactions
$this->reportCategories();
// tags with no transactions
$this->reportTags();
// sum of transactions is not zero.
$this->reportSum();
// any deleted transaction journals that have transactions that are NOT deleted:
@@ -82,6 +90,9 @@ class VerifyDatabase extends Command
// transfers with budgets.
$this->reportTransfersBudgets();
// report on journals with the wrong types of accounts.
$this->reportIncorrectJournals();
}
/**
@@ -89,14 +100,13 @@ class VerifyDatabase extends Command
*/
private function reportAccounts()
{
$set = Account
::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
->whereNull('transactions.account_id')
->get(
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email']
);
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
->whereNull('transactions.account_id')
->get(
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email']
);
/** @var stdClass $entry */
foreach ($set as $entry) {
@@ -112,59 +122,19 @@ class VerifyDatabase extends Command
*/
private function reportBudgetLimits()
{
$set = Budget
::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
->groupBy(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email'])
->whereNull('budget_limits.id')
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
$set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
->groupBy(['budgets.id', 'budgets.name', 'budgets.encrypted', 'budgets.user_id', 'users.email'])
->whereNull('budget_limits.id')
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'budgets.encrypted', 'users.email']);
/** @var stdClass $entry */
/** @var Budget $entry */
foreach ($set as $entry) {
$line = 'Notice: User #' . $entry->user_id . ' (' . $entry->email . ') has budget #' . $entry->id . ' ("' . Crypt::decrypt($entry->name)
. '") which has no budget limits.';
$this->line($line);
}
}
/**
* Reports on budgets without any transactions.
*/
private function reportBudgets()
{
$set = Budget
::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
->distinct()
->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) {
$line = 'Notice: User #' . $entry->user_id . ' (' . $entry->email . ') has budget #' . $entry->id . ' ("' . Crypt::decrypt($entry->name)
. '") which has no transactions.';
$this->line($line);
}
}
/**
* Reports on categories without any transactions.
*/
private function reportCategories()
{
$set = Category
::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id')
->leftJoin('users', 'categories.user_id', '=', 'users.id')
->distinct()
->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) {
$line = 'Notice: User #' . $entry->user_id . ' (' . $entry->email . ') has category #' . $entry->id . ' ("' . Crypt::decrypt($entry->name)
. '") which has no transactions.';
$name = $entry->encrypted ? Crypt::decrypt($entry->name) : $entry->name;
$line = sprintf(
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
$entry->user_id, $entry->email, $entry->id, $name
);
$this->line($line);
}
}
@@ -174,55 +144,94 @@ class VerifyDatabase extends Command
*/
private function reportDeletedAccounts()
{
$set = Account
::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereNotNull('accounts.deleted_at')
->whereNotNull('transactions.id')
->where(
function (Builder $q) {
$q->whereNull('transactions.deleted_at');
$q->orWhereNull('transaction_journals.deleted_at');
}
)
->get(
['accounts.id as account_id', 'accounts.deleted_at as account_deleted_at', 'transactions.id as transaction_id',
'transactions.deleted_at as transaction_deleted_at', 'transaction_journals.id as journal_id',
'transaction_journals.deleted_at as journal_deleted_at']
);
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereNotNull('accounts.deleted_at')
->whereNotNull('transactions.id')
->where(
function (Builder $q) {
$q->whereNull('transactions.deleted_at');
$q->orWhereNull('transaction_journals.deleted_at');
}
)
->get(
['accounts.id as account_id', 'accounts.deleted_at as account_deleted_at', 'transactions.id as transaction_id',
'transactions.deleted_at as transaction_deleted_at', 'transaction_journals.id as journal_id',
'transaction_journals.deleted_at as journal_deleted_at']
);
/** @var stdClass $entry */
foreach ($set as $entry) {
$date = is_null($entry->transaction_deleted_at) ? $entry->journal_deleted_at : $entry->transaction_deleted_at;
$this->error(
'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' .
' Find it in the table called `accounts` and change the `deleted_at` field to: "' . $date . '"'
' Find it in the table called "accounts" and change the "deleted_at" field to: "' . $date . '"'
);
}
}
private function reportIncorrectJournals()
{
$configuration = [
// a withdrawal can not have revenue account:
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
// deposit cannot have an expense account:
TransactionType::DEPOSIT => [AccountType::EXPENSE],
// transfer cannot have either:
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
];
foreach ($configuration as $transactionType => $accountTypes) {
$set = TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin('account_types', 'account_types.id', 'accounts.account_type_id')
->leftJoin('users', 'users.id', '=', 'transaction_journals.user_id')
->where('transaction_types.type', $transactionType)
->whereIn('account_types.type', $accountTypes)
->whereNull('transaction_journals.deleted_at')
->get(
['transaction_journals.id', 'transaction_journals.user_id', 'users.email', 'account_types.type as a_type',
'transaction_types.type']
);
foreach ($set as $entry) {
$this->error(
sprintf(
'Transaction journal #%d (user #%d, %s) is of type "%s" but ' .
'is linked to a "%s". The transaction journal should be recreated.',
$entry->id,
$entry->user_id,
$entry->email,
$entry->type,
$entry->a_type
)
);
}
}
}
/**
* Any deleted transaction journals that have transactions that are NOT deleted:
*/
private function reportJournals()
{
$set = TransactionJournal
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNotNull('transaction_journals.deleted_at')// USE THIS
->whereNull('transactions.deleted_at')
->whereNotNull('transactions.id')
->get(
[
'transaction_journals.id as journal_id',
'transaction_journals.description',
'transaction_journals.deleted_at as journal_deleted',
'transactions.id as transaction_id',
'transactions.deleted_at as transaction_deleted_at']
);
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNotNull('transaction_journals.deleted_at')// USE THIS
->whereNull('transactions.deleted_at')
->whereNotNull('transactions.id')
->get(
[
'transaction_journals.id as journal_id',
'transaction_journals.description',
'transaction_journals.deleted_at as journal_deleted',
'transactions.id as transaction_id',
'transactions.deleted_at as transaction_deleted_at']
);
/** @var stdClass $entry */
foreach ($set as $entry) {
$this->error(
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
' Find it in the table called `transactions` and change the `deleted_at` field to: "' . $entry->journal_deleted . '"'
' Find it in the table called "transactions" and change the "deleted_at" field to: "' . $entry->journal_deleted . '"'
);
}
}
@@ -232,20 +241,52 @@ class VerifyDatabase extends Command
*/
private function reportNoTransactions()
{
$set = TransactionJournal
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->groupBy('transaction_journals.id')
->whereNull('transactions.transaction_journal_id')
->get(['transaction_journals.id']);
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->groupBy('transaction_journals.id')
->whereNull('transactions.transaction_journal_id')
->get(['transaction_journals.id']);
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
'Error: Journal #' . $entry->id . ' has zero transactions. Open table "transaction_journals" and delete the entry with id #' . $entry->id
);
}
}
/**
* @param string $name
*/
private function reportObject(string $name)
{
$plural = str_plural($name);
$class = sprintf('FireflyIII\Models\%s', ucfirst($name));
$field = $name == 'tag' ? 'tag' : 'name';
$set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id')
->leftJoin('users', $plural . '.user_id', '=', 'users.id')
->distinct()
->whereNull($name . '_transaction_journal.' . $name . '_id')
->whereNull($plural . '.deleted_at')
->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']);
/** @var stdClass $entry */
foreach ($set as $entry) {
$objName = $entry->name;
try {
$objName = Crypt::decrypt($objName);
} catch (DecryptException $e) {
// it probably was not encrypted.
}
$line = sprintf(
'Notice: User #%d (%s) has %s #%d ("%s") which has no transactions.',
$entry->user_id, $entry->email, $name, $entry->id, $objName
);
$this->line($line);
}
}
/**
* Reports for each user when the sum of their transactions is not zero.
*/
@@ -263,45 +304,23 @@ class VerifyDatabase extends Command
}
}
/**
* Reports on tags without any transactions.
*/
private function reportTags()
{
$set = Tag
::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')
->leftJoin('users', 'tags.user_id', '=', 'users.id')
->distinct()
->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) {
$line = 'Notice: User #' . $entry->user_id . ' (' . $entry->email . ') has tag #' . $entry->id . ' ("' . $entry->tag
. '") which has no transactions.';
$this->line($line);
}
}
/**
* Reports on deleted transactions that are connected to a not deleted journal.
*/
private function reportTransactions()
{
$set = Transaction
::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNotNull('transactions.deleted_at')
->whereNull('transaction_journals.deleted_at')
->get(
['transactions.id as transaction_id', 'transactions.deleted_at as transaction_deleted', 'transaction_journals.id as journal_id',
'transaction_journals.deleted_at']
);
$set = Transaction::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNotNull('transactions.deleted_at')
->whereNull('transaction_journals.deleted_at')
->get(
['transactions.id as transaction_id', 'transactions.deleted_at as transaction_deleted', 'transaction_journals.id as journal_id',
'transaction_journals.deleted_at']
);
/** @var stdClass $entry */
foreach ($set as $entry) {
$this->error(
'Error: Transaction journal #' . $entry->journal_id . ' should have been deleted, but has not.' .
' Find it in the table called `transaction_journals` and change the `deleted_at` field to: "' . $entry->transaction_deleted . '"'
' Find it in the table called "transaction_journals" and change the "deleted_at" field to: "' . $entry->transaction_deleted . '"'
);
}
}
@@ -311,12 +330,11 @@ class VerifyDatabase extends Command
*/
private function reportTransfersBudgets()
{
$set = TransactionJournal
::distinct()
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->where('transaction_types.type', TransactionType::TRANSFER)
->whereNotNull('budget_transaction_journal.budget_id')->get(['transaction_journals.id']);
$set = TransactionJournal::distinct()
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->where('transaction_types.type', TransactionType::TRANSFER)
->whereNotNull('budget_transaction_journal.budget_id')->get(['transaction_journals.id']);
/** @var TransactionJournal $entry */
foreach ($set as $entry) {

13
app/Console/Kernel.php Executable file → Normal file
View File

@@ -3,17 +3,22 @@
* Kernel.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console;
use FireflyIII\Console\Commands\CreateImport;
use FireflyIII\Console\Commands\EncryptFile;
use FireflyIII\Console\Commands\Import;
use FireflyIII\Console\Commands\MoveRepository;
use FireflyIII\Console\Commands\ScanAttachments;
use FireflyIII\Console\Commands\UpgradeDatabase;
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
use FireflyIII\Console\Commands\VerifyDatabase;
use Illuminate\Console\Scheduling\Schedule;
@@ -55,9 +60,11 @@ class Kernel extends ConsoleKernel
UpgradeFireflyInstructions::class,
VerifyDatabase::class,
Import::class,
CreateImport::class,
EncryptFile::class,
ScanAttachments::class,
UpgradeDatabase::class,
MoveRepository::class,
];
/**

View File

@@ -1,534 +0,0 @@
<?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 Carbon\Carbon;
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
*
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
*
* @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): bool
{
if (!is_null($moveTo->id)) {
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
}
if (!is_null($account)) {
$account->delete();
}
return true;
}
/**
* @param $accountId
*
* @return Account
*/
public function find(int $accountId): Account
{
$account = $this->user->accounts()->find($accountId);
if (is_null($account)) {
return new Account;
}
return $account;
}
/**
* @param string $number
* @param array $types
*
* @return Account
*/
public function findByAccountNumber(string $number, array $types): Account
{
$query = $this->user->accounts()
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('account_meta.name', 'accountNumber')
->where('account_meta.data', json_encode($number));
if (count($types) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $types);
}
/** @var Collection $accounts */
$accounts = $query->get(['accounts.*']);
if ($accounts->count() > 0) {
return $accounts->first();
}
return new Account;
}
/**
* @param string $iban
* @param array $types
*
* @return Account
*/
public function findByIban(string $iban, array $types): Account
{
$query = $this->user->accounts()->where('iban', '!=', '');
if (count($types) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $types);
}
$accounts = $query->get(['accounts.*']);
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->iban === $iban) {
return $account;
}
}
return new Account;
}
/**
* @param string $name
* @param array $types
*
* @return Account
*/
public function findByName(string $name, array $types): Account
{
$query = $this->user->accounts();
if (count($types) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $types);
}
Log::debug(sprintf('Searching for account named %s of the following type(s)', $name), ['types' => $types]);
$accounts = $query->get(['accounts.*']);
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->name === $name) {
Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id));
return $account;
}
}
Log::debug('Found nothing.');
return new 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
*/
public function store(array $data): Account
{
$newAccount = $this->storeAccount($data);
if (!is_null($newAccount->id)) {
$this->storeMetadata($newAccount, $data);
}
if ($data['openingBalance'] != 0) {
$this->storeInitialBalance($newAccount, $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);
$this->updateInitialBalance($account, $data);
return $account;
}
/**
* @param Account $account
* @param string $type
*
* @return Account
*/
public function updateAccountType(Account $account, string $type): Account
{
$type = AccountType::whereType($type)->first();
if (!is_null($type)) {
$account->accountType()->associate($type);
$account->save();
}
return $this->find($account->id);
}
/**
* @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()->toArray());
return new Account;
}
$newAccount = $existingAccount;
}
$newAccount->save();
return $newAccount;
}
/**
* @param Account $account
* @param array $data
*
* @return TransactionJournal
*/
protected function storeInitialBalance(Account $account, array $data): TransactionJournal
{
$amount = $data['openingBalance'];
$user = $data['user'];
$name = $data['name'];
$opposing = $this->storeOpposingAccount($amount, $user, $name);
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
$journal = TransactionJournal::create(
[
'user_id' => $data['user'],
'transaction_type_id' => $transactionType->id,
'transaction_currency_id' => $data['openingBalanceCurrency'],
'description' => 'Initial balance for "' . $account->name . '"',
'completed' => true,
'date' => $data['openingBalanceDate'],
'encrypted' => true,
]
);
$firstAccount = $account;
$secondAccount = $opposing;
$firstAmount = $amount;
$secondAmount = $amount * -1;
if ($data['openingBalance'] < 0) {
$firstAccount = $opposing;
$secondAccount = $account;
$firstAmount = $amount * -1;
$secondAmount = $amount;
}
$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 array $data
*
* @return bool
*/
protected function updateInitialBalance(Account $account, array $data): bool
{
$openingBalance = $this->openingBalanceTransaction($account);
if ($data['openingBalance'] != 0) {
if (!is_null($openingBalance->id)) {
$date = $data['openingBalanceDate'];
$amount = $data['openingBalance'];
return $this->updateJournal($account, $openingBalance, $date, $amount);
}
$this->storeInitialBalance($account, $data);
return true;
}
// else, delete it:
if ($openingBalance) { // opening balance is zero, should we delete it?
$openingBalance->delete(); // delete existing opening balance.
}
return true;
}
/**
* @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;
}
/**
* @param float $amount
* @param int $user
* @param string $name
*
* @return Account
*/
private function storeOpposingAccount(float $amount, int $user, string $name):Account
{
$type = $amount < 0 ? 'expense' : 'revenue';
$opposingData = [
'user' => $user,
'accountType' => $type,
'name' => $name . ' initial balance',
'active' => false,
'iban' => '',
'virtualBalance' => 0,
];
return $this->storeAccount($opposingData);
}
/**
* @param Account $account
* @param TransactionJournal $journal
* @param Carbon $date
* @param float $amount
*
* @return bool
*/
private function updateJournal(Account $account, TransactionJournal $journal, Carbon $date, float $amount): bool
{
// update date:
$journal->date = $date;
$journal->save();
// update transactions:
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if ($account->id == $transaction->account_id) {
$transaction->amount = $amount;
$transaction->save();
}
if ($account->id != $transaction->account_id) {
$transaction->amount = $amount * -1;
$transaction->save();
}
}
return true;
}
}

View File

@@ -1,109 +0,0 @@
<?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 string $number
* @param array $types
*
* @return Account
*/
public function findByAccountNumber(string $number, array $types): Account;
/**
* @param string $iban
* @param array $types
*
* @return Account
*/
public function findByIban(string $iban, array $types): Account;
/**
* @param string $name
* @param array $types
*
* @return Account
*/
public function findByName(string $name, array $types): 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;
/**
* @param Account $account
* @param string $type
*
* @return Account
*/
public function updateAccountType(Account $account, string $type): Account;
}

View File

@@ -1,216 +0,0 @@
<?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
{
$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 (isset($data['source_account_name']) && 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

@@ -1,47 +0,0 @@
<?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,41 @@
<?php
/**
* BlockedBadLogin.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
/**
* Class LockedOutUser
*
* @package FireflyIII\Events
*/
class BlockedBadLogin extends Event
{
use SerializesModels;
public $email;
public $ipAddress;
/**
* Create a new event instance. This event is triggered when a user gets themselves locked out.
*
* @param string $email
* @param string $ipAddress
*/
public function __construct(string $email, string $ipAddress)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* BlockedUseOfDomain.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
/**
* Class BlockedUseOfDomain
*
* @package FireflyIII\Events
*/
class BlockedUseOfDomain extends Event
{
use SerializesModels;
public $email;
public $ipAddress;
/**
* Create a new event instance. This event is triggered when a user tries to register with a banned domain (on blocked domain list).
*
* @param string $email
* @param string $ipAddress
*/
public function __construct(string $email, string $ipAddress)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* BlockedUseOfEmail.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
/**
* Class BlockedUseOfEmail
*
* @package FireflyIII\Events
*/
class BlockedUseOfEmail extends Event
{
use SerializesModels;
public $email;
public $ipAddress;
/**
* Create a new event instance. This event is triggered when a user tries to register with a banned email address (already used before).
*
* @param string $email
* @param string $ipAddress
*/
public function __construct(string $email, string $ipAddress)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -1,10 +1,12 @@
<?php
/**
* ResendConfirmation.php
* BlockedUserLogin.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -15,11 +17,11 @@ use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class ResendConfirmation
* Class BlockedUserLogin
*
* @package FireflyIII\Events
*/
class ResendConfirmation extends Event
class BlockedUserLogin extends Event
{
use SerializesModels;
@@ -27,9 +29,9 @@ class ResendConfirmation extends Event
public $user;
/**
* Create a new event instance.
* Create a new event instance. This event is triggered when a blocked user logs in.
*
* @param User $user
* @param User $user
* @param string $ipAddress
*/
public function __construct(User $user, string $ipAddress)

View File

@@ -1,10 +1,12 @@
<?php
/**
* UserRegistration.php
* ConfirmedUser.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -15,11 +17,11 @@ use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class UserRegistration
* Class ConfirmedUser
*
* @package FireflyIII\Events
*/
class UserRegistration extends Event
class ConfirmedUser extends Event
{
use SerializesModels;
@@ -27,7 +29,7 @@ class UserRegistration extends Event
public $user;
/**
* Create a new event instance.
* Create a new event instance. This event is triggered when a user confirms their new account.
*
* @param User $user
* @param string $ipAddress

View File

@@ -0,0 +1,38 @@
<?php
/**
* DeletedUser.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
/**
* Class DeletedUser
*
* @package FireflyIII\Events
*/
class DeletedUser extends Event
{
use SerializesModels;
public $email;
/**
* Create a new event instance. This event is triggered when a user deletes themselves.
*
* @param string $email
*/
public function __construct(string $email)
{
$this->email = $email;
}
}

View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -0,0 +1,41 @@
<?php
/**
* LockedOutUser.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
/**
* Class LockedOutUser
*
* @package FireflyIII\Events
*/
class LockedOutUser extends Event
{
use SerializesModels;
public $email;
public $ipAddress;
/**
* Create a new event instance. This event is triggered when a user gets themselves locked out.
*
* @param string $email
* @param string $ipAddress
*/
public function __construct(string $email, string $ipAddress)
{
$this->email = $email;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -1,10 +1,12 @@
<?php
/**
* UserIsDeleted.php
* RegisteredUser.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -15,11 +17,11 @@ use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class UserIsDeleted
* Class RegisteredUser
*
* @package FireflyIII\Events
*/
class UserIsDeleted extends Event
class RegisteredUser extends Event
{
use SerializesModels;
@@ -27,7 +29,7 @@ class UserIsDeleted extends Event
public $user;
/**
* Create a new event instance.
* Create a new event instance. This event is triggered when a new user registers.
*
* @param User $user
* @param string $ipAddress

View File

@@ -0,0 +1,46 @@
<?php
/**
* RequestedNewPassword.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Events;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class RequestedNewPassword
*
* @package FireflyIII\Events
*/
class RequestedNewPassword extends Event
{
use SerializesModels;
public $ipAddress;
public $token;
public $user;
/**
* Create a new event instance. This event is triggered when a users tries to reset his or her password.
*
* @param User $user
* @param string $token
* @param string $ipAddress
*/
public function __construct(User $user, string $token, string $ipAddress)
{
$this->user = $user;
$this->token = $token;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -1,10 +1,12 @@
<?php
/**
* UserIsConfirmed.php
* ResentConfirmation.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -15,11 +17,11 @@ use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class UserIsConfirmed
* Class ResentConfirmation
*
* @package FireflyIII\Events
*/
class UserIsConfirmed extends Event
class ResentConfirmation extends Event
{
use SerializesModels;
@@ -27,7 +29,7 @@ class UserIsConfirmed extends Event
public $user;
/**
* Create a new event instance.
* Create a new event instance. This event is triggered when a users wants a new confirmation.
*
* @param User $user
* @param string $ipAddress

View File

@@ -1,10 +1,12 @@
<?php
/**
* BudgetLimitStored.php
* StoredBudgetLimit.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class BudgetLimitStored
* Class StoredBudgetLimit
*
* @package FireflyIII\Events
*/
class BudgetLimitStored extends Event
class StoredBudgetLimit extends Event
{
use SerializesModels;

View File

@@ -1,10 +1,12 @@
<?php
/**
* TransactionJournalStored.php
* StoredTransactionJournal.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
/**
* Class TransactionJournalStored
* Class StoredTransactionJournal
*
* @package FireflyIII\Events
*/
class TransactionJournalStored extends Event
class StoredTransactionJournal extends Event
{
use SerializesModels;

View File

@@ -1,39 +0,0 @@
<?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,10 +1,12 @@
<?php
/**
* BudgetLimitUpdated.php
* UpdatedBudgetLimit.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class BudgetLimitUpdated
* Class UpdatedBudgetLimit
*
* @package FireflyIII\Events
*/
class BudgetLimitUpdated extends Event
class UpdatedBudgetLimit extends Event
{
use SerializesModels;

View File

@@ -1,10 +1,12 @@
<?php
/**
* TransactionJournalUpdated.php
* UpdatedTransactionJournal.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
/**
* Class TransactionJournalUpdated
* Class UpdatedTransactionJournal
*
* @package FireflyIII\Events
*/
class TransactionJournalUpdated extends Event
class UpdatedTransactionJournal extends Event
{
use SerializesModels;

View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

12
app/Exceptions/Handler.php Executable file → Normal file
View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -75,7 +77,8 @@ class Handler extends ExceptionHandler
*/
public function report(Exception $exception)
{
if ($exception instanceof FireflyException || $exception instanceof ErrorException) {
$doMailError = env('SEND_ERROR_MESSAGE', true);
if (($exception instanceof FireflyException || $exception instanceof ErrorException) && $doMailError) {
$userData = [
'id' => 0,
'email' => 'unknown@example.com',
@@ -106,7 +109,8 @@ class Handler extends ExceptionHandler
/**
* Convert an authentication exception into an unauthenticated response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\Response
*/
protected function unauthenticated($request)

View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -3,8 +3,10 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -3,19 +3,20 @@
* AttachmentCollector.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Collector;
use Amount;
use Carbon\Carbon;
use Crypt;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\ExportJob;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Collection;
@@ -29,12 +30,14 @@ use Storage;
*/
class AttachmentCollector extends BasicCollector implements CollectorInterface
{
/** @var string */
private $explanationString = '';
/** @var Carbon */
private $end;
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
private $exportDisk;
/** @var AttachmentRepositoryInterface */
private $repository;
/** @var Carbon */
private $start;
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
private $uploadDisk;
@@ -67,34 +70,17 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
$this->exportAttachment($attachment);
}
// 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);
$this->getFiles()->push($file);
return true;
}
/**
* @param Attachment $attachment
* @param Carbon $start
* @param Carbon $end
*/
private function explain(Attachment $attachment)
public function setDates(Carbon $start, Carbon $end)
{
/** @var TransactionJournal $journal */
$journal = $attachment->attachable;
$args = [
'attachment_name' => e($attachment->filename),
'attachment_id' => $attachment->id,
'type' => strtolower($journal->transactionType->type),
'description' => e($journal->description),
'journal_id' => $journal->id,
'date' => $journal->date->formatLocalized(strval(trans('config.month_and_day'))),
'amount' => Amount::formatJournal($journal, false),
];
$string = trans('firefly.attachment_explanation', $args) . "\n";
Log::debug('Appended explanation string', ['string' => $string]);
$this->explanationString .= $string;
$this->start = $start;
$this->end = $end;
}
/**
@@ -110,10 +96,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
$exportFile = $this->exportFileName($attachment);
$this->exportDisk->put($exportFile, $decrypted);
$this->getFiles()->push($exportFile);
$this->getEntries()->push($exportFile);
// explain:
$this->explain($attachment);
} catch (DecryptException $e) {
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
}
@@ -141,7 +125,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
*/
private function getAttachments(): Collection
{
$attachments = $this->repository->get();
$attachments = $this->repository->getBetween($this->start, $this->end);
return $attachments;
}

View File

@@ -3,8 +3,10 @@
* BasicCollector.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -25,7 +27,7 @@ class BasicCollector
/** @var ExportJob */
protected $job;
/** @var Collection */
private $files;
private $entries;
/**
* BasicCollector constructor.
@@ -34,24 +36,24 @@ class BasicCollector
*/
public function __construct(ExportJob $job)
{
$this->files = new Collection;
$this->job = $job;
$this->entries = new Collection;
$this->job = $job;
}
/**
* @return Collection
*/
public function getFiles(): Collection
public function getEntries(): Collection
{
return $this->files;
return $this->entries;
}
/**
* @param Collection $files
* @param Collection $entries
*/
public function setFiles(Collection $files)
public function setEntries(Collection $entries)
{
$this->files = $files;
$this->entries = $entries;
}

View File

@@ -3,8 +3,10 @@
* CollectorInterface.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -23,7 +25,7 @@ interface CollectorInterface
/**
* @return Collection
*/
public function getFiles(): Collection;
public function getEntries(): Collection;
/**
* @return bool
@@ -31,9 +33,9 @@ interface CollectorInterface
public function run(): bool;
/**
* @param Collection $files
* @param Collection $entries
*
*/
public function setFiles(Collection $files);
public function setEntries(Collection $entries);
}

View File

@@ -0,0 +1,347 @@
<?php
/**
* JournalExportCollector.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Collector;
use Carbon\Carbon;
use Crypt;
use DB;
use FireflyIII\Models\Transaction;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
/**
* Class JournalExportCollector
*
* @package FireflyIII\Export\Collector
*/
class JournalExportCollector extends BasicCollector implements CollectorInterface
{
/** @var Collection */
private $accounts;
/** @var Carbon */
private $end;
/** @var Carbon */
private $start;
/** @var Collection */
private $workSet;
/**
* @return bool
*/
public function run(): bool
{
/*
* Instead of collecting journals we collect transactions for the given accounts.
* We left join the OPPOSING transaction AND some journal data.
* After that we complement this info with budgets, categories, etc.
*
* This is way more efficient and will also work on split journals.
*/
$this->getWorkSet();
/*
* Extract:
* possible budget ids for journals
* possible category ids journals
* possible budget ids for transactions
* possible category ids for transactions
*
* possible IBAN and account numbers?
*
*/
$journals = $this->extractJournalIds();
$transactions = $this->extractTransactionIds();
// extend work set with category data from journals:
$this->categoryDataForJournals($journals);
// extend work set with category cate from transactions (overrules journals):
$this->categoryDataForTransactions($transactions);
// same for budgets:
$this->budgetDataForJournals($journals);
$this->budgetDataForTransactions($transactions);
$this->setEntries($this->workSet);
return true;
}
/**
* @param Collection $accounts
*/
public function setAccounts(Collection $accounts)
{
$this->accounts = $accounts;
}
/**
* @param Carbon $start
* @param Carbon $end
*/
public function setDates(Carbon $start, Carbon $end)
{
$this->start = $start;
$this->end = $end;
}
/**
* @param array $journals
*
* @return bool
*/
private function budgetDataForJournals(array $journals): bool
{
$set = DB::table('budget_transaction_journal')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->whereIn('budget_transaction_journal.transaction_journal_id', $journals)
->get(
[
'budget_transaction_journal.budget_id',
'budget_transaction_journal.transaction_journal_id',
'budgets.name',
'budgets.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_journal_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
if (isset($array[$obj->transaction_journal_id])) {
$obj->budget_id = $array[$obj->transaction_journal_id]['id'];
$obj->budget_name = $array[$obj->transaction_journal_id]['name'];
}
}
);
return true;
}
/**
* @param array $transactions
*
* @return bool
*/
private function budgetDataForTransactions(array $transactions): bool
{
$set = DB::table('budget_transaction')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction.budget_id')
->whereIn('budget_transaction.transaction_id', $transactions)
->get(
[
'budget_transaction.budget_id',
'budget_transaction.transaction_id',
'budgets.name',
'budgets.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
// first transaction
if (isset($array[$obj->id])) {
$obj->budget_id = $array[$obj->id]['id'];
$obj->budget_name = $array[$obj->id]['name'];
}
}
);
return true;
}
/**
* @param array $journals
*
* @return bool
*/
private function categoryDataForJournals(array $journals): bool
{
$set = DB::table('category_transaction_journal')
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
->whereIn('category_transaction_journal.transaction_journal_id', $journals)
->get(
[
'category_transaction_journal.category_id',
'category_transaction_journal.transaction_journal_id',
'categories.name',
'categories.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_journal_id] = ['id' => $obj->category_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
if (isset($array[$obj->transaction_journal_id])) {
$obj->category_id = $array[$obj->transaction_journal_id]['id'];
$obj->category_name = $array[$obj->transaction_journal_id]['name'];
}
}
);
return true;
}
/**
* @param array $transactions
*
* @return bool
*/
private function categoryDataForTransactions(array $transactions): bool
{
$set = DB::table('category_transaction')
->leftJoin('categories', 'categories.id', '=', 'category_transaction.category_id')
->whereIn('category_transaction.transaction_id', $transactions)
->get(
[
'category_transaction.category_id',
'category_transaction.transaction_id',
'categories.name',
'categories.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_id] = ['id' => $obj->category_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
// first transaction
if (isset($array[$obj->id])) {
$obj->category_id = $array[$obj->id]['id'];
$obj->category_name = $array[$obj->id]['name'];
}
}
);
return true;
}
/**
* @return array
*/
private function extractJournalIds(): array
{
return $this->workSet->pluck('transaction_journal_id')->toArray();
}
/**
* @return array
*/
private function extractTransactionIds()
{
$set = $this->workSet->pluck('id')->toArray();
$opposing = $this->workSet->pluck('opposing_id')->toArray();
$complete = $set + $opposing;
return array_unique($complete);
}
/**
*
*/
private function getWorkSet()
{
$accountIds = $this->accounts->pluck('id')->toArray();
$this->workSet = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin(
'transactions AS opposing', function (JoinClause $join) {
$join->on('opposing.transaction_journal_id', '=', 'transactions.transaction_journal_id')
->where('opposing.amount', '=', DB::raw('transactions.amount * -1'))
->where('transactions.identifier', '=', DB::raw('opposing.identifier'));
}
)
->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('accounts AS opposing_accounts', 'opposing.account_id', '=', 'opposing_accounts.id')
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', 'transaction_types.id')
->leftJoin('transaction_currencies', 'transaction_journals.transaction_currency_id', '=', 'transaction_currencies.id')
->whereIn('transactions.account_id', $accountIds)
->where('transaction_journals.user_id', $this->job->user_id)
->where('transaction_journals.date', '>=', $this->start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $this->end->format('Y-m-d'))
->where('transaction_journals.completed', 1)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->whereNull('opposing.deleted_at')
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transactions.identifier', 'ASC')
->get(
[
'transactions.id',
'transactions.amount',
'transactions.description',
'transactions.account_id',
'accounts.name as account_name',
'accounts.encrypted as account_name_encrypted',
'transactions.identifier',
'opposing.id as opposing_id',
'opposing.amount AS opposing_amount',
'opposing.description as opposing_description',
'opposing.account_id as opposing_account_id',
'opposing_accounts.name as opposing_account_name',
'opposing_accounts.encrypted as opposing_account_encrypted',
'opposing.identifier as opposing_identifier',
'transaction_journals.id as transaction_journal_id',
'transaction_journals.date',
'transaction_journals.description as journal_description',
'transaction_journals.encrypted as journal_encrypted',
'transaction_journals.transaction_type_id',
'transaction_types.type as transaction_type',
'transaction_journals.transaction_currency_id',
'transaction_currencies.code AS transaction_currency_code',
]
);
}
}

View File

@@ -3,8 +3,10 @@
* UploadCollector.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -24,16 +26,14 @@ use Storage;
*/
class UploadCollector extends BasicCollector implements CollectorInterface
{
/** @var string */
private $expected;
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
private $exportDisk;
private $importKeys = [];
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
private $uploadDisk;
/** @var string */
private $vintageFormat;
/**
*
* AttachmentCollector constructor.
*
* @param ExportJob $job
@@ -49,50 +49,74 @@ class UploadCollector extends BasicCollector implements CollectorInterface
$this->exportDisk = Storage::disk('export');
// file names associated with the old import routine.
$this->expected = 'csv-upload-' . auth()->user()->id . '-';
$this->vintageFormat = sprintf('csv-upload-%d-', auth()->user()->id);
// for the new import routine:
$this->getImportKeys();
}
/**
* Is called from the outside to actually start the export.
*
* @return bool
*/
public function run(): bool
{
// grab upload directory.
$files = $this->uploadDisk->files();
// collect old upload files (names beginning with "csv-upload".
$this->collectVintageUploads();
foreach ($files as $entry) {
$this->processUpload($entry);
// then collect current upload files:
$this->collectModernUploads();
return true;
}
/**
* This method collects all the uploads that are uploaded using the new importer. So after the summer of 2016.
*
* @return bool
*/
private function collectModernUploads(): bool
{
$set = $this->job->user->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
$keys = [];
if ($set->count() > 0) {
$keys = $set->pluck('key')->toArray();
}
foreach ($keys as $key) {
$this->processModernUpload($key);
}
return true;
}
/**
* This method collects all the uploads that are uploaded using the "old" importer. So from before the summer of 2016.
*
* @return bool
*/
private function getImportKeys()
private function collectVintageUploads(): bool
{
$set = auth()->user()->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
if ($set->count() > 0) {
$keys = $set->pluck('key')->toArray();
$this->importKeys = $keys;
// grab upload directory.
$files = $this->uploadDisk->files();
foreach ($files as $entry) {
$this->processVintageUpload($entry);
}
Log::debug('Valid import keys are ', $this->importKeys);
return true;
}
/**
* This method tells you when the vintage upload file was actually uploaded.
*
* @param string $entry
*
* @return string
*/
private function getOriginalUploadDate(string $entry): string
private function getVintageUploadDate(string $entry): string
{
// this is an original upload.
$parts = explode('-', str_replace(['.csv.encrypted', $this->expected], '', $entry));
$parts = explode('-', str_replace(['.csv.encrypted', $this->vintageFormat], '', $entry));
$originalUpload = intval($parts[1]);
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
@@ -100,33 +124,17 @@ class UploadCollector extends BasicCollector implements CollectorInterface
}
/**
* Tells you if a file name is a vintage upload.
*
* @param string $entry
*
* @return bool
*/
private function isImportFile(string $entry): bool
private function isVintageImport(string $entry): bool
{
$name = str_replace('.upload', '', $entry);
if (in_array($name, $this->importKeys)) {
Log::debug(sprintf('Import file "%s" is in array', $name), $this->importKeys);
return true;
}
Log::debug(sprintf('Import file "%s" is NOT in array', $name), $this->importKeys);
return false;
}
/**
* @param string $entry
*
* @return bool
*/
private function isOldImport(string $entry): bool
{
$len = strlen($this->expected);
$len = strlen($this->vintageFormat);
// file is part of the old import routine:
if (substr($entry, 0, $len) === $this->expected) {
if (substr($entry, 0, $len) === $this->vintageFormat) {
return true;
}
@@ -135,49 +143,62 @@ class UploadCollector extends BasicCollector implements CollectorInterface
}
/**
* @param $entry
* @param string $key
*
* @return bool
*/
private function processUpload(string $entry)
{
// file is old import:
if ($this->isOldImport($entry)) {
$this->saveOldImportFile($entry);
}
// file is current import.
if ($this->isImportFile($entry)) {
$this->saveImportFile($entry);
}
}
/**
* @param string $entry
*/
private function saveImportFile(string $entry)
private function processModernUpload(string $key): bool
{
// find job associated with import file:
$name = str_replace('.upload', '', $entry);
$job = auth()->user()->importJobs()->where('key', $name)->first();
$content = '';
try {
$content = Crypt::decrypt($this->uploadDisk->get($entry));
} catch (DecryptException $e) {
Log::error('Could not decrypt old import file ' . $entry . '. Skipped because ' . $e->getMessage());
$job = $this->job->user->importJobs()->where('key', $key)->first();
if (is_null($job)) {
return false;
}
if (!is_null($job) && strlen($content) > 0) {
// find the file for this import:
$content = '';
try {
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('%s.upload', $key)));
} catch (DecryptException $e) {
Log::error(sprintf('Could not decrypt old import file "%s". Skipped because: %s', $key, $e->getMessage()));
}
if (strlen($content) > 0) {
// add to export disk.
$date = $job->created_at->format('Y-m-d');
$file = sprintf('%s-Old %s import dated %s.%s', $this->job->key, strtoupper($job->file_type), $date, $job->file_type);
$this->exportDisk->put($file, $content);
$this->getFiles()->push($file);
$this->getEntries()->push($file);
}
return true;
}
/**
* If the file is a vintage upload, process it.
*
* @param string $entry
*
* @return bool
*/
private function processVintageUpload(string $entry): bool
{
if ($this->isVintageImport($entry)) {
$this->saveVintageImportFile($entry);
return true;
}
return false;
}
/**
* This will store the content of the old vintage upload somewhere.
*
* @param string $entry
*/
private function saveOldImportFile(string $entry)
private function saveVintageImportFile(string $entry)
{
$content = '';
try {
@@ -188,10 +209,10 @@ class UploadCollector extends BasicCollector implements CollectorInterface
if (strlen($content) > 0) {
// add to export disk.
$date = $this->getOriginalUploadDate($entry);
$date = $this->getVintageUploadDate($entry);
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
$this->exportDisk->put($file, $content);
$this->getFiles()->push($file);
$this->getEntries()->push($file);
}
}

View File

@@ -1,66 +0,0 @@
<?php
/**
* ConfigurationFile.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;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Models\ExportJob;
use Storage;
/**
* Class ConfigurationFile
*
* @package FireflyIII\Export
*/
class ConfigurationFile
{
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
private $exportDisk;
/** @var ExportJob */
private $job;
/**
* ConfigurationFile constructor.
*
* @param ExportJob $job
*/
public function __construct(ExportJob $job)
{
$this->job = $job;
$this->exportDisk = Storage::disk('export');
}
/**
* @return string
*/
public function make(): string
{
$fields = array_keys(Entry::getFieldsAndTypes());
$types = Entry::getFieldsAndTypes();
$configuration = [
'date-format' => 'Y-m-d', // unfortunately, this is hard-coded.
'has-headers' => true,
'map' => [], // we could build a map if necessary for easy re-import.
'roles' => [],
'mapped' => [],
'specifix' => [],
];
foreach ($fields as $field) {
$configuration['roles'][] = $types[$field];
}
$file = $this->job->key . '-configuration.json';
$this->exportDisk->put($file, json_encode($configuration, JSON_PRETTY_PRINT));
return $file;
}
}

View File

@@ -3,16 +3,17 @@
* 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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use Crypt;
/**
* To extend the exported object, in case of new features in Firefly III for example,
@@ -33,98 +34,77 @@ use Illuminate\Support\Collection;
*/
final class Entry
{
/** @var string */
public $amount;
/** @var EntryBill */
public $bill;
/** @var EntryBudget */
public $budget;
/** @var EntryCategory */
public $category;
/** @var string */
// @formatter:off
public $journal_id;
public $date;
/** @var string */
public $description;
/** @var EntryAccount */
public $destinationAccount;
/** @var Collection */
public $destinationAccounts;
/** @var EntryAccount */
public $sourceAccount;
/** @var Collection */
public $sourceAccounts;
public $currency_code;
public $amount;
public $transaction_type;
public $source_account_id;
public $source_account_name;
public $destination_account_id;
public $destination_account_name;
public $budget_id;
public $budget_name;
public $category_id;
public $category_name;
// @formatter:on
/**
* Entry constructor.
*/
private function __construct()
{
$this->sourceAccounts = new Collection;
$this->destinationAccounts = new Collection;
}
/**
* @param TransactionJournal $journal
* @param $object
*
* @return Entry
*/
public static function fromJournal(TransactionJournal $journal)
public static function fromObject($object): Entry
{
$entry = new self;
$entry = new self;
$entry->description = $journal->description;
$entry->date = $journal->date->format('Y-m-d');
$entry->amount = TransactionJournal::amount($journal);
// journal information:
$entry->journal_id = $object->transaction_journal_id;
$entry->description = $object->journal_encrypted === 1 ? Crypt::decrypt($object->journal_description) : $object->journal_description;
$entry->amount = round($object->amount, 2); // always positive
$entry->date = $object->date;
$entry->transaction_type = $object->transaction_type;
$entry->currency_code = $object->transaction_currency_code;
$entry->budget = new EntryBudget($journal->budgets->first());
$entry->category = new EntryCategory($journal->categories->first());
$entry->bill = new EntryBill($journal->bill);
// source information:
$entry->source_account_id = $object->account_id;
$entry->source_account_name = $object->account_name_encrypted === 1 ? Crypt::decrypt($object->account_name) : $object->account_name;
$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));
}
// destination information
$entry->destination_account_id = $object->opposing_account_id;
$entry->destination_account_name = $object->opposing_account_encrypted === 1 ? Crypt::decrypt($object->opposing_account_name)
: $object->opposing_account_name;
foreach ($destinations as $destination) {
$entry->destinationAccounts->push(new EntryAccount($destination));
// category and budget
$entry->category_id = $object->category_id ?? '';
$entry->category_name = $object->category_name ?? '';
$entry->budget_id = $object->budget_id ?? '';
$entry->budget_name = $object->budget_name ?? '';
// update description when transaction description is different:
if (!is_null($object->description) && $object->description != $entry->description) {
$entry->description = $entry->description . ' (' . $object->description . ')';
}
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

@@ -1,47 +0,0 @@
<?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

@@ -1,41 +0,0 @@
<?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

@@ -1,41 +0,0 @@
<?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

@@ -1,40 +0,0 @@
<?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

@@ -3,8 +3,10 @@
* BasicExporter.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -3,8 +3,10 @@
* CsvExporter.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -12,9 +14,7 @@ declare(strict_types = 1);
namespace FireflyIII\Export\Exporter;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Export\Entry\EntryAccount;
use FireflyIII\Models\ExportJob;
use Illuminate\Support\Collection;
use League\Csv\Writer;
use SplFileObject;
@@ -60,110 +60,24 @@ class CsvExporter extends BasicExporter implements ExporterInterface
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
$rows = [];
// 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) {
$sources = $entry->sourceAccounts->count();
$destinations = $entry->destinationAccounts->count();
$maxSourceAccounts = max($maxSourceAccounts, $sources);
$maxDestAccounts = max($maxDestAccounts, $destinations);
}
$rows[] = array_keys($this->getFieldsAndTypes($maxSourceAccounts, $maxDestAccounts));
// get field names for header row:
$first = $this->getEntries()->first();
$headers = array_keys(get_object_vars($first));
$rows[] = $headers;
/** @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;
$line = [];
foreach ($headers as $header) {
$line[] = $entry->$header;
}
$rows[] = $line;
}
$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()
{

View File

@@ -3,8 +3,10 @@
* ExporterInterface.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);

View File

@@ -3,8 +3,10 @@
* Processor.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
@@ -13,13 +15,13 @@ namespace FireflyIII\Export;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Export\Collector\AttachmentCollector;
use FireflyIII\Export\Collector\JournalExportCollector;
use FireflyIII\Export\Collector\UploadCollector;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Models\ExportJob;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Collection;
use Log;
use Storage;
use ZipArchive;
@@ -28,7 +30,7 @@ use ZipArchive;
*
* @package FireflyIII\Export
*/
class Processor
class Processor implements ProcessorInterface
{
/** @var Collection */
@@ -38,15 +40,11 @@ class Processor
/** @var bool */
public $includeAttachments;
/** @var bool */
public $includeConfig;
/** @var bool */
public $includeOldUploads;
/** @var ExportJob */
public $job;
/** @var array */
public $settings;
/** @var \FireflyIII\Export\ConfigurationFile */
private $configurationMaker;
/** @var Collection */
private $exportEntries;
/** @var Collection */
@@ -66,7 +64,6 @@ class Processor
$this->accounts = $settings['accounts'];
$this->exportFormat = $settings['exportFormat'];
$this->includeAttachments = $settings['includeAttachments'];
$this->includeConfig = $settings['includeConfig'];
$this->includeOldUploads = $settings['includeOldUploads'];
$this->job = $settings['job'];
$this->journals = new Collection;
@@ -82,8 +79,9 @@ class Processor
{
/** @var AttachmentCollector $attachmentCollector */
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
$attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
$attachmentCollector->run();
$this->files = $this->files->merge($attachmentCollector->getFiles());
$this->files = $this->files->merge($attachmentCollector->getEntries());
return true;
}
@@ -93,9 +91,13 @@ class Processor
*/
public function collectJournals(): bool
{
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$this->journals = $repository->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
/** @var JournalExportCollector $collector */
$collector = app(JournalExportCollector::class, [$this->job]);
$collector->setDates($this->settings['startDate'], $this->settings['endDate']);
$collector->setAccounts($this->settings['accounts']);
$collector->run();
$this->journals = $collector->getEntries();
Log::debug(sprintf('Count %d journals in collectJournals() ', $this->journals->count()));
return true;
}
@@ -109,7 +111,7 @@ class Processor
$uploadCollector = app(UploadCollector::class, [$this->job]);
$uploadCollector->run();
$this->files = $this->files->merge($uploadCollector->getFiles());
$this->files = $this->files->merge($uploadCollector->getEntries());
return true;
}
@@ -120,22 +122,11 @@ class Processor
public function convertJournals(): bool
{
$count = 0;
/** @var TransactionJournal $journal */
foreach ($this->journals as $journal) {
$this->exportEntries->push(Entry::fromJournal($journal));
foreach ($this->journals as $object) {
$this->exportEntries->push(Entry::fromObject($object));
$count++;
}
return true;
}
/**
* @return bool
*/
public function createConfigFile(): bool
{
$this->configurationMaker = app(ConfigurationFile::class, [$this->job]);
$this->files->push($this->configurationMaker->make());
Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
return true;
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* ProcessorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Export;
use Illuminate\Support\Collection;
/**
* Interface ProcessorInterface
*
* @package FireflyIII\Export
*/
interface ProcessorInterface
{
/**
* Processor constructor.
*
* @param array $settings
*/
public function __construct(array $settings);
/**
* @return bool
*/
public function collectAttachments(): bool;
/**
* @return bool
*/
public function collectJournals(): bool;
/**
* @return bool
*/
public function collectOldUploads(): bool;
/**
* @return bool
*/
public function convertJournals(): bool;
/**
* @return bool
*/
public function createZipFile(): bool;
/**
* @return bool
*/
public function exportJournals(): bool;
/**
* @return Collection
*/
public function getFiles(): Collection;
}

View File

@@ -1,52 +0,0 @@
<?php
/**
* AccountChartGeneratorInterface.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;
/**
* Interface AccountChartGeneratorInterface
*
* @package FireflyIII\Generator\Chart\Account
*/
interface AccountChartGeneratorInterface
{
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end): array;
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array;
/**
* @param Account $account
* @param array $labels
* @param array $dataSet
*
* @return array
*/
public function single(Account $account, array $labels, array $dataSet): array;
}

View File

@@ -1,107 +0,0 @@
<?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;
/**
* Class ChartJsAccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
{
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end): array
{
$data = [
'count' => 1,
'labels' => [], 'datasets' => [[
'label' => trans('firefly.spent'),
'data' => []]]];
foreach ($accounts as $account) {
if ($account->difference > 0) {
$data['labels'][] = $account->name;
$data['datasets'][0]['data'][] = $account->difference;
}
}
return $data;
}
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array
{
// language:
$format = (string)trans('config.month_and_day');
$data = ['count' => 0, 'labels' => [], 'datasets' => [],];
$current = clone $start;
while ($current <= $end) {
$data['labels'][] = $current->formatLocalized($format);
$current->addDay();
}
foreach ($accounts as $account) {
$data['datasets'][] = [
'label' => $account->name,
'fillColor' => 'rgba(220,220,220,0.2)',
'strokeColor' => 'rgba(220,220,220,1)',
'pointColor' => 'rgba(220,220,220,1)',
'pointStrokeColor' => '#fff',
'pointHighlightFill' => '#fff',
'pointHighlightStroke' => 'rgba(220,220,220,1)',
'data' => $account->balances,
];
}
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @param Account $account
* @param array $labels
* @param array $dataSet
*
* @return array
*/
public function single(Account $account, array $labels, array $dataSet): array
{
$data = [
'count' => 1,
'labels' => $labels,
'datasets' => [
[
'label' => $account->name,
'data' => $dataSet,
],
],
];
return $data;
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* ChartJsGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Basic;
use FireflyIII\Support\ChartColour;
/**
* Class ChartJsGenerator
*
* @package FireflyIII\Generator\Chart\Basic
*/
class ChartJsGenerator implements GeneratorInterface
{
/**
* Will generate a Chart JS compatible array from the given input. Expects this format
*
* Will take labels for all from first set.
*
* 0: [
* 'label' => 'label of set',
* 'type' => bar or line, optional
* 'yAxisID' => ID of yAxis, optional, will not be included when unused.
* 'fill' => if to fill a line? optional, will not be included when unused.
* 'entries' =>
* [
* 'label-of-entry' => 'value'
* ]
* ]
* 1: [
* 'label' => 'label of another set',
* 'type' => bar or line, optional
* 'yAxisID' => ID of yAxis, optional, will not be included when unused.
* 'fill' => if to fill a line? optional, will not be included when unused.
* 'entries' =>
* [
* 'label-of-entry' => 'value'
* ]
* ]
*
*
* @param array $data
*
* @return array
*/
public function multiSet(array $data): array
{
reset($data);
$first = current($data);
$labels = array_keys($first['entries']);
$chartData = [
'count' => count($data),
'labels' => $labels, // take ALL labels from the first set.
'datasets' => [],
];
unset($first, $labels);
foreach ($data as $set) {
$currentSet = [
'label' => $set['label'],
'type' => $set['type'] ?? 'line',
'data' => array_values($set['entries']),
];
if (isset($set['yAxisID'])) {
$currentSet['yAxisID'] = $set['yAxisID'];
}
if (isset($set['fill'])) {
$currentSet['fill'] = $set['fill'];
}
$chartData['datasets'][] = $currentSet;
}
return $chartData;
}
/**
* Expects data as:
*
* key => value
*
* @param array $data
*
* @return array
*/
public function pieChart(array $data): array
{
$chartData = [
'datasets' => [
0 => [],
],
'labels' => [],
];
$index = 0;
foreach ($data as $key => $value) {
// make larger than 0
if (bccomp($value, '0') === -1) {
$value = bcmul($value, '-1');
}
$chartData['datasets'][0]['data'][] = round($value, 2);
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
$chartData['labels'][] = $key;
$index++;
}
return $chartData;
}
/**
* Will generate a (ChartJS) compatible array from the given input. Expects this format:
*
* 'label-of-entry' => value
* 'label-of-entry' => value
*
* @param string $setLabel
* @param array $data
*
* @return array
*/
public function singleSet(string $setLabel, array $data): array
{
$chartData = [
'count' => 1,
'labels' => array_keys($data), // take ALL labels from the first set.
'datasets' => [
[
'label' => $setLabel,
'data' => array_values($data),
],
],
];
return $chartData;
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* GeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Basic;
/**
* Interface GeneratorInterface
*
* @package FireflyIII\Generator\Chart\Basic
*/
interface GeneratorInterface
{
/**
* Will generate a (ChartJS) compatible array from the given input. Expects this format:
*
* 0: [
* 'label' => 'label of set',
* 'entries' =>
* [
* 'label-of-entry' => 'value'
* ]
* ]
* 1: [
* 'label' => 'label of another set',
* 'entries' =>
* [
* 'label-of-entry' => 'value'
* ]
* ]
*
*
* @param array $data
*
* @return array
*/
public function multiSet(array $data): array;
/**
* Expects data as:
*
* key => value
*
* @param array $data
*
* @return array
*/
public function pieChart(array $data): array;
/**
* Will generate a (ChartJS) compatible array from the given input. Expects this format:
*
* 'label-of-entry' => value
* 'label-of-entry' => value
*
* @param string $setLabel
* @param array $data
*
* @return array
*/
public function singleSet(string $setLabel, array $data): array;
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* BillChartGeneratorInterface.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\Bill;
use FireflyIII\Models\Bill;
use Illuminate\Support\Collection;
/**
* Interface BillChartGeneratorInterface
*
* @package FireflyIII\Generator\Chart\Bill
*/
interface BillChartGeneratorInterface
{
/**
* @param string $paid
* @param string $unpaid
*
* @return array
*/
public function frontpage(string $paid, string $unpaid): array;
/**
* @param Bill $bill
* @param Collection $entries
*
* @return array
*/
public function single(Bill $bill, Collection $entries): array;
}

View File

@@ -1,91 +0,0 @@
<?php
/**
* ChartJsBillChartGenerator.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\Bill;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
/**
* Class ChartJsBillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
class ChartJsBillChartGenerator implements BillChartGeneratorInterface
{
/**
* @param string $paid
* @param string $unpaid
*
* @return array
*/
public function frontpage(string $paid, string $unpaid): array
{
$data = [
'datasets' => [
[
'data' => [round($unpaid, 2), round(bcmul($paid, '-1'), 2)],
'backgroundColor' => ['rgba(53, 124, 165,0.7)', 'rgba(0, 141, 76, 0.7)',],
],
],
'labels' => [strval(trans('firefly.unpaid')), strval(trans('firefly.paid'))],
];
return $data;
}
/**
* @param Bill $bill
* @param Collection $entries
*
* @return array
*/
public function single(Bill $bill, Collection $entries): array
{
$format = (string)trans('config.month');
$data = ['count' => 3, 'labels' => [], 'datasets' => [],];
$minAmount = [];
$maxAmount = [];
$actualAmount = [];
/** @var TransactionJournal $entry */
foreach ($entries as $entry) {
$data['labels'][] = $entry->date->formatLocalized($format);
$minAmount[] = round($bill->amount_min, 2);
$maxAmount[] = round($bill->amount_max, 2);
// journalAmount has been collected in BillRepository::getJournals
$actualAmount[] = round(TransactionJournal::amountPositive($entry), 2);
}
$data['datasets'][] = [
'type' => 'bar',
'label' => trans('firefly.minAmount'),
'data' => $minAmount,
];
$data['datasets'][] = [
'type' => 'line',
'label' => trans('firefly.billEntry'),
'data' => $actualAmount,
];
$data['datasets'][] = [
'type' => 'bar',
'label' => trans('firefly.maxAmount'),
'data' => $maxAmount,
];
$data['count'] = count($data['datasets']);
return $data;
}
}

View File

@@ -1,62 +0,0 @@
<?php
/**
* BudgetChartGeneratorInterface.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 Illuminate\Support\Collection;
/**
* Interface BudgetChartGeneratorInterface
*
* @package FireflyIII\Generator\Chart\Budget
*/
interface BudgetChartGeneratorInterface
{
/**
* @param Collection $entries
* @param string $dateFormat
*
* @return array
*/
public function budgetLimit(Collection $entries, string $dateFormat): array;
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries): array;
/**
* @param Collection $entries
*
* @return array
*/
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
*
* @return array
*/
public function year(Collection $budgets, Collection $entries): array;
}

View File

@@ -1,208 +0,0 @@
<?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 Illuminate\Support\Collection;
use Navigation;
/**
* Class ChartJsBudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
{
/**
*
* @param Collection $entries
* @param string $dateFormat
*
* @return array
*/
public function budgetLimit(Collection $entries, string $dateFormat = 'month_and_day'): array
{
$format = strval(trans('config.' . $dateFormat));
$data = [
'labels' => [],
'datasets' => [
[
'label' => 'Amount',
'data' => [],
],
],
];
/** @var array $entry */
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized($format);
$data['datasets'][0]['data'][] = $entry[1];
}
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries): array
{
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
$left = [];
$spent = [];
$overspent = [];
$filtered = $entries->filter(
function ($entry) {
return ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0);
}
);
foreach ($filtered as $entry) {
$data['labels'][] = $entry[0];
$left[] = round($entry[1], 2);
$spent[] = round(bcmul($entry[2], '-1'), 2); // spent is coming in negative, must be positive
$overspent[] = round(bcmul($entry[3], '-1'), 2); // same
}
$data['datasets'][] = [
'label' => trans('firefly.overspent'),
'data' => $overspent,
];
$data['datasets'][] = [
'label' => trans('firefly.left'),
'data' => $left,
];
$data['datasets'][] = [
'label' => trans('firefly.spent'),
'data' => $spent,
];
$data['count'] = 3;
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function multiYear(Collection $entries): array
{
// dataset:
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
// get labels from one of the budgets (assuming there's at least one):
$first = $entries->first();
$keys = array_keys($first['budgeted']);
foreach ($keys as $year) {
$data['labels'][] = strval($year);
}
// then, loop all entries and create datasets:
foreach ($entries as $entry) {
$name = $entry['name'];
$spent = $entry['spent'];
$budgeted = $entry['budgeted'];
$data['datasets'][] = ['label' => 'Spent on ' . $name, 'data' => array_values($spent)];
$data['datasets'][] = ['label' => 'Budgeted for ' . $name, 'data' => array_values($budgeted)];
}
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @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
*
* @return array
*/
public function year(Collection $budgets, Collection $entries): array
{
// language:
$format = (string)trans('config.month');
$data = [
'labels' => [],
'datasets' => [],
];
foreach ($budgets as $budget) {
$data['labels'][] = $budget->name;
}
// also add "no budget"
$data['labels'][] = strval(trans('firefly.no_budget'));
/** @var array $entry */
foreach ($entries as $entry) {
$array = [
'label' => $entry[0]->formatLocalized($format),
'data' => [],
];
array_shift($entry);
$array['data'] = $entry;
$data['datasets'][] = $array;
}
$data['count'] = count($data['datasets']);
return $data;
}
}

View File

@@ -1,67 +0,0 @@
<?php
/**
* CategoryChartGeneratorInterface.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;
use Illuminate\Support\Collection;
/**
* Interface CategoryChartGeneratorInterface
*
* @package FireflyIII\Generator\Chart\Category
*/
interface CategoryChartGeneratorInterface
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(Collection $entries): array;
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function earnedInPeriod(Collection $categories, Collection $entries): array;
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries): array;
/**
* @param Collection $entries
*
* @return array
*/
public function multiYear(Collection $entries): array;
/**
* @param Collection $entries
*
* @return array
*/
public function period(Collection $entries): array;
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function spentInPeriod(Collection $categories, Collection $entries): array;
}

View File

@@ -1,190 +0,0 @@
<?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;
use Illuminate\Support\Collection;
/**
* Class ChartJsCategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(Collection $entries): array
{
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => [],
],
[
'label' => trans('firefly.earned'),
'data' => [],
],
],
];
foreach ($entries as $entry) {
$data['labels'][] = $entry[1];
$spent = $entry[2];
$earned = $entry[3];
$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;
}
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function earnedInPeriod(Collection $categories, Collection $entries): array
{
// language:
$format = (string)trans('config.month');
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
foreach ($categories as $category) {
$data['labels'][] = $category->name;
}
foreach ($entries as $entry) {
$date = $entry[0]->formatLocalized($format);
array_shift($entry);
$data['count']++;
$data['datasets'][] = ['label' => $date, 'data' => $entry];
}
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries): array
{
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => [],
],
],
];
foreach ($entries as $entry) {
if ($entry->spent != 0) {
$data['labels'][] = $entry->name;
$data['datasets'][0]['data'][] = round(bcmul($entry->spent, '-1'), 2);
}
}
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function multiYear(Collection $entries): array
{
// get labels from one of the categories (assuming there's at least one):
$first = $entries->first();
$data = ['count' => 0, 'labels' => array_keys($first['spent']), 'datasets' => [],];
// then, loop all entries and create datasets:
foreach ($entries as $entry) {
$name = $entry['name'];
$spent = $entry['spent'];
$earned = $entry['earned'];
if (array_sum(array_values($spent)) != 0) {
$data['datasets'][] = ['label' => 'Spent in category ' . $name, 'data' => array_values($spent)];
}
if (array_sum(array_values($earned)) != 0) {
$data['datasets'][] = ['label' => 'Earned in category ' . $name, 'data' => array_values($earned)];
}
}
$data['count'] = count($data['datasets']);
return $data;
}
/**
*
* @param Collection $entries
*
* @return array
*/
public function period(Collection $entries): array
{
return $this->all($entries);
}
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function spentInPeriod(Collection $categories, Collection $entries): array
{
// language:
$format = (string)trans('config.month');
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
foreach ($categories as $category) {
$data['labels'][] = $category->name;
}
foreach ($entries as $entry) {
$date = $entry[0]->formatLocalized($format);
array_shift($entry);
$data['count']++;
$data['datasets'][] = ['label' => $date, 'data' => $entry];
}
return $data;
}
}

View File

@@ -1,56 +0,0 @@
<?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;
use Carbon\Carbon;
use Illuminate\Support\Collection;
/**
* Class ChartJsPiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
class ChartJsPiggyBankChartGenerator implements PiggyBankChartGeneratorInterface
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set): array
{
// language:
$format = (string)trans('config.month_and_day');
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => 'Diff',
'data' => [],
],
],
];
$sum = '0';
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);
}
return $data;
}
}

View File

@@ -1,29 +0,0 @@
<?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;
/**
* Interface PiggyBankChartGeneratorInterface
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
interface PiggyBankChartGeneratorInterface
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set): array;
}

View File

@@ -1,178 +0,0 @@
<?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;
use Illuminate\Support\Collection;
/**
* Class ChartJsReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
class ChartJsReportChartGenerator implements ReportChartGeneratorInterface
{
/**
* Same as above but other translations.
*
* @param Collection $entries
*
* @return array
*/
public function multiYearInOut(Collection $entries): array
{
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => [],
],
[
'label' => trans('firefly.expenses'),
'data' => [],
],
],
];
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized('%Y');
$data['datasets'][0]['data'][] = round($entry[1], 2);
$data['datasets'][1]['data'][] = round($entry[2], 2);
}
return $data;
}
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function multiYearInOutSummarized(string $income, string $expense, int $count): array
{
$data = [
'count' => 2,
'labels' => [trans('firefly.sum_of_years'), trans('firefly.average_of_years')],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => [],
],
[
'label' => trans('firefly.expenses'),
'data' => [],
],
],
];
$data['datasets'][0]['data'][] = round($income, 2);
$data['datasets'][1]['data'][] = round($expense, 2);
$data['datasets'][0]['data'][] = round(($income / $count), 2);
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function netWorth(Collection $entries) : array
{
$format = (string)trans('config.month_and_day');
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.net_worth'),
'data' => [],
],
],
];
foreach ($entries as $entry) {
$data['labels'][] = trim($entry['date']->formatLocalized($format));
$data['datasets'][0]['data'][] = round($entry['net-worth'], 2);
}
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries): array
{
// language:
$format = (string)trans('config.month');
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => [],
],
[
'label' => trans('firefly.expenses'),
'data' => [],
],
],
];
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized($format);
$data['datasets'][0]['data'][] = round($entry[1], 2);
$data['datasets'][1]['data'][] = round($entry[2], 2);
}
return $data;
}
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized(string $income, string $expense, int $count): array
{
$data = [
'count' => 2,
'labels' => [trans('firefly.sum_of_year'), trans('firefly.average_of_year')],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => [],
],
[
'label' => trans('firefly.expenses'),
'data' => [],
],
],
];
$data['datasets'][0]['data'][] = round($income, 2);
$data['datasets'][1]['data'][] = round($expense, 2);
$data['datasets'][0]['data'][] = round(($income / $count), 2);
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
return $data;
}
}

View File

@@ -1,63 +0,0 @@
<?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;
/**
* Interface ReportChartGeneratorInterface
*
* @package FireflyIII\Generator\Chart\Report
*/
interface ReportChartGeneratorInterface
{
/**
* @param Collection $entries
*
* @return array
*/
public function multiYearInOut(Collection $entries): array;
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function multiYearInOutSummarized(string $income, string $expense, int $count): array;
/**
* @param Collection $entries
*
* @return array
*/
public function netWorth(Collection $entries) : array;
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries): array;
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized(string $income, string $expense, int $count): array;
}

View File

@@ -0,0 +1,156 @@
<?php
/**
* MonthReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Audit;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use Illuminate\Support\Collection;
use Steam;
/**
* Class MonthReportGenerator
*
* @package FireflyIII\Generator\Report\Audit
*/
class MonthReportGenerator implements ReportGeneratorInterface
{
/** @var Collection */
private $accounts;
/** @var Carbon */
private $end;
/** @var Carbon */
private $start;
/**
* @return string
*/
public function generate(): string
{
$auditData = [];
$dayBefore = clone $this->start;
$dayBefore->subDay();
/** @var Account $account */
foreach ($this->accounts as $account) {
// balance the day before:
$id = $account->id;
$dayBeforeBalance = Steam::balance($account, $dayBefore);
$collector = new JournalCollector(auth()->user());
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end);
$journals = $collector->getJournals();
$journals = $journals->reverse();
$startBalance = $dayBeforeBalance;
/** @var Transaction $journal */
foreach ($journals as $transaction) {
$transaction->before = $startBalance;
$transactionAmount = $transaction->transaction_amount;
$newBalance = bcadd($startBalance, $transactionAmount);
$transaction->after = $newBalance;
$startBalance = $newBalance;
}
/*
* Reverse set again.
*/
$auditData[$id]['journals'] = $journals->reverse();
$auditData[$id]['exists'] = $journals->count() > 0;
$auditData[$id]['end'] = $this->end->formatLocalized(strval(trans('config.month_and_day')));
$auditData[$id]['endBalance'] = Steam::balance($account, $this->end);
$auditData[$id]['dayBefore'] = $dayBefore->formatLocalized(strval(trans('config.month_and_day')));
$auditData[$id]['dayBeforeBalance'] = $dayBeforeBalance;
}
$defaultShow = ['icon', 'description', 'balance_before', 'amount', 'balance_after', 'date', 'to'];
$reportType = 'audit';
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
$hideable = ['buttons', 'icon', 'description', 'balance_before', 'amount', 'balance_after', 'date',
'interest_date', 'book_date', 'process_date',
// three new optional fields.
'due_date', 'payment_date', 'invoice_date',
'from', 'to', 'budget', 'category', 'bill',
// more new optional fields
'internal_reference', 'notes',
'create_date', 'update_date',
];
return view('reports.audit.report', compact('reportType', 'accountIds', 'auditData', 'hideable', 'defaultShow'))
->with('start', $this->start)->with('end', $this->end)->with('accounts', $this->accounts)
->render();
}
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface
{
return $this;
}
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface
{
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface
{
$this->end = $date;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface
{
$this->start = $date;
return $this;
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* MultiYearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Audit;
/**
* Class MultiYearReportGenerator
*
* @package FireflyIII\Generator\Report\Audit
*/
class MultiYearReportGenerator extends MonthReportGenerator
{
/**
* Doesn't do anything different.
*/
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* YearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Audit;
/**
* Class YearReportGenerator
*
* @package FireflyIII\Generator\Report\Audit
*/
class YearReportGenerator extends MonthReportGenerator
{
/**
* Doesn't do anything different.
*/
}

View File

@@ -0,0 +1,247 @@
<?php
/**
* MonthReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Budget;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use FireflyIII\Generator\Report\Support;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
use Log;
/**
* Class MonthReportGenerator
*
* @package FireflyIII\Generator\Report\Budget
*/
class MonthReportGenerator extends Support implements ReportGeneratorInterface
{
/** @var Collection */
private $accounts;
/** @var Collection */
private $budgets;
/** @var Carbon */
private $end;
/** @var Collection */
private $expenses;
/** @var Collection */
private $income;
/** @var Carbon */
private $start;
/**
* MonthReportGenerator constructor.
*/
public function __construct()
{
$this->income = new Collection;
$this->expenses = new Collection;
}
/**
* @return string
*/
public function generate(): string
{
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
$budgetIds = join(',', $this->budgets->pluck('id')->toArray());
$expenses = $this->getExpenses();
$accountSummary = $this->summarizeByAccount($expenses);
$budgetSummary = $this->summarizeByBudget($expenses);
$averageExpenses = $this->getAverages($expenses, SORT_ASC);
$topExpenses = $this->getTopExpenses();
// render!
return view('reports.budget.month', compact('accountIds', 'budgetIds', 'accountSummary', 'budgetSummary', 'averageExpenses', 'topExpenses'))
->with('start', $this->start)->with('end', $this->end)
->with('budgets', $this->budgets)
->with('accounts', $this->accounts)
->render();
}
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface
{
$this->budgets = $budgets;
return $this;
}
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface
{
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface
{
$this->end = $date;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface
{
$this->start = $date;
return $this;
}
/**
* @param Collection $collection
* @param int $sortFlag
*
* @return array
*/
private function getAverages(Collection $collection, int $sortFlag): array
{
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
// opposing name and ID:
$opposingId = $transaction->opposing_account_id;
// is not set?
if (!isset($result[$opposingId])) {
$name = $transaction->opposing_account_name;
$result[$opposingId] = [
'name' => $name,
'count' => 1,
'id' => $opposingId,
'average' => $transaction->transaction_amount,
'sum' => $transaction->transaction_amount,
];
continue;
}
$result[$opposingId]['count']++;
$result[$opposingId]['sum'] = bcadd($result[$opposingId]['sum'], $transaction->transaction_amount);
$result[$opposingId]['average'] = bcdiv($result[$opposingId]['sum'], strval($result[$opposingId]['count']));
}
// sort result by average:
$average = [];
foreach ($result as $key => $row) {
$average[$key] = floatval($row['average']);
}
array_multisort($average, $sortFlag, $result);
return $result;
}
/**
* @return Collection
*/
private function getExpenses(): Collection
{
if ($this->expenses->count() > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
$collector = new JournalCollector(auth()->user());
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL])
->setBudgets($this->budgets)->withOpposingAccount()->disableFilter();
$accountIds = $this->accounts->pluck('id')->toArray();
$transactions = $collector->getJournals();
$transactions = self::filterExpenses($transactions, $accountIds);
$this->expenses = $transactions;
return $transactions;
}
/**
* @return Collection
*/
private function getTopExpenses(): Collection
{
$transactions = $this->getExpenses()->sortBy('transaction_amount');
return $transactions;
}
/**
* @param Collection $collection
*
* @return array
*/
private function summarizeByAccount(Collection $collection): array
{
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
$accountId = $transaction->account_id;
$result[$accountId] = $result[$accountId] ?? '0';
$result[$accountId] = bcadd($transaction->transaction_amount, $result[$accountId]);
}
return $result;
}
/**
* @param Collection $collection
*
* @return array
*/
private function summarizeByBudget(Collection $collection): array
{
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
$jrnlBudId = intval($transaction->transaction_journal_budget_id);
$transBudId = intval($transaction->transaction_budget_id);
$budgetId = max($jrnlBudId, $transBudId);
$result[$budgetId] = $result[$budgetId] ?? '0';
$result[$budgetId] = bcadd($transaction->transaction_amount, $result[$budgetId]);
}
return $result;
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* MultiYearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Budget;
/**
* Class MultiYearReportGenerator
*
* @package FireflyIII\Generator\Report\Budget
*/
class MultiYearReportGenerator extends MonthReportGenerator
{
/**
* Doesn't do anything different.
*/
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* YearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Budget;
/**
* Class YearReportGenerator
*
* @package FireflyIII\Generator\Report\Budget
*/
class YearReportGenerator extends MonthReportGenerator
{
/**
* Doesn't do anything different.
*/
}

View File

@@ -0,0 +1,328 @@
<?php
/**
* MonthReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Category;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use FireflyIII\Generator\Report\Support;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
use Log;
/**
* Class MonthReportGenerator
*
* @package FireflyIII\Generator\Report\Category
*/
class MonthReportGenerator extends Support implements ReportGeneratorInterface
{
/** @var Collection */
private $accounts;
/** @var Collection */
private $categories;
/** @var Carbon */
private $end;
/** @var Collection */
private $expenses;
/** @var Collection */
private $income;
/** @var Carbon */
private $start;
/**
* MonthReportGenerator constructor.
*/
public function __construct()
{
$this->income = new Collection;
$this->expenses = new Collection;
}
/**
* @return string
*/
public function generate(): string
{
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
$categoryIds = join(',', $this->categories->pluck('id')->toArray());
$reportType = 'category';
$expenses = $this->getExpenses();
$income = $this->getIncome();
$accountSummary = $this->getObjectSummary($this->summarizeByAccount($expenses), $this->summarizeByAccount($income));
$categorySummary = $this->getObjectSummary($this->summarizeByCategory($expenses), $this->summarizeByCategory($income));
$averageExpenses = $this->getAverages($expenses, SORT_ASC);
$averageIncome = $this->getAverages($income, SORT_DESC);
$topExpenses = $this->getTopExpenses();
$topIncome = $this->getTopIncome();
// render!
return view(
'reports.category.month',
compact(
'accountIds', 'categoryIds', 'topIncome', 'reportType', 'accountSummary', 'categorySummary', 'averageExpenses', 'averageIncome', 'topExpenses'
)
)
->with('start', $this->start)->with('end', $this->end)
->with('categories', $this->categories)
->with('accounts', $this->accounts)
->render();
}
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface
{
return $this;
}
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface
{
$this->categories = $categories;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface
{
$this->end = $date;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface
{
$this->start = $date;
return $this;
}
/**
* @param Collection $collection
* @param int $sortFlag
*
* @return array
*/
private function getAverages(Collection $collection, int $sortFlag): array
{
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
// opposing name and ID:
$opposingId = $transaction->opposing_account_id;
// is not set?
if (!isset($result[$opposingId])) {
$name = $transaction->opposing_account_name;
$result[$opposingId] = [
'name' => $name,
'count' => 1,
'id' => $opposingId,
'average' => $transaction->transaction_amount,
'sum' => $transaction->transaction_amount,
];
continue;
}
$result[$opposingId]['count']++;
$result[$opposingId]['sum'] = bcadd($result[$opposingId]['sum'], $transaction->transaction_amount);
$result[$opposingId]['average'] = bcdiv($result[$opposingId]['sum'], strval($result[$opposingId]['count']));
}
// sort result by average:
$average = [];
foreach ($result as $key => $row) {
$average[$key] = floatval($row['average']);
}
array_multisort($average, $sortFlag, $result);
return $result;
}
/**
* @return Collection
*/
private function getExpenses(): Collection
{
if ($this->expenses->count() > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
$collector = new JournalCollector(auth()->user());
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
->setCategories($this->categories)->withOpposingAccount()->disableFilter();
$accountIds = $this->accounts->pluck('id')->toArray();
$transactions = $collector->getJournals();
$transactions = self::filterExpenses($transactions, $accountIds);
$this->expenses = $transactions;
return $transactions;
}
/**
* @return Collection
*/
private function getIncome(): Collection
{
if ($this->income->count() > 0) {
return $this->income;
}
$collector = new JournalCollector(auth()->user());
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->setCategories($this->categories)->withOpposingAccount();
$accountIds = $this->accounts->pluck('id')->toArray();
$transactions = $collector->getJournals();
$transactions = self::filterIncome($transactions, $accountIds);
$this->income = $transactions;
return $transactions;
}
/**
* @param array $spent
* @param array $earned
*
* @return array
*/
private function getObjectSummary(array $spent, array $earned): array
{
$return = [];
/**
* @var int $accountId
* @var string $entry
*/
foreach ($spent as $objectId => $entry) {
if (!isset($return[$objectId])) {
$return[$objectId] = ['spent' => 0, 'earned' => 0];
}
$return[$objectId]['spent'] = $entry;
}
unset($entry);
/**
* @var int $accountId
* @var string $entry
*/
foreach ($earned as $objectId => $entry) {
if (!isset($return[$objectId])) {
$return[$objectId] = ['spent' => 0, 'earned' => 0];
}
$return[$objectId]['earned'] = $entry;
}
return $return;
}
/**
* @return Collection
*/
private function getTopExpenses(): Collection
{
$transactions = $this->getExpenses()->sortBy('transaction_amount');
return $transactions;
}
/**
* @return Collection
*/
private function getTopIncome(): Collection
{
$transactions = $this->getIncome()->sortByDesc('transaction_amount');
return $transactions;
}
/**
* @param Collection $collection
*
* @return array
*/
private function summarizeByAccount(Collection $collection): array
{
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
$accountId = $transaction->account_id;
$result[$accountId] = $result[$accountId] ?? '0';
$result[$accountId] = bcadd($transaction->transaction_amount, $result[$accountId]);
}
return $result;
}
/**
* @param Collection $collection
*
* @return array
*/
private function summarizeByCategory(Collection $collection): array
{
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
$jrnlCatId = intval($transaction->transaction_journal_category_id);
$transCatId = intval($transaction->transaction_category_id);
$categoryId = max($jrnlCatId, $transCatId);
$result[$categoryId] = $result[$categoryId] ?? '0';
$result[$categoryId] = bcadd($transaction->transaction_amount, $result[$categoryId]);
}
return $result;
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* MultiYearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Category;
/**
* Class MultiYearReportGenerator
*
* @package FireflyIII\Generator\Report\Audit
*/
class MultiYearReportGenerator extends MonthReportGenerator
{
/**
* Doesn't do anything different.
*/
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* YearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Category;
/**
* Class YearReportGenerator
*
* @package FireflyIII\Generator\Report\Audit
*/
class YearReportGenerator extends MonthReportGenerator
{
/**
* Doesn't do anything different.
*/
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* ReportGeneratorFactory.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
/**
* Class ReportGeneratorFactory
*
* @package FireflyIII\Generator\Report
*/
class ReportGeneratorFactory
{
/**
* @param string $type
* @param Carbon $start
* @param Carbon $end
*
* @return ReportGeneratorInterface
* @throws FireflyException
*/
public static function reportGenerator(string $type, Carbon $start, Carbon $end): ReportGeneratorInterface
{
$period = 'Month';
// more than two months date difference means year report.
if ($start->diffInMonths($end) > 1) {
$period = 'Year';
}
// more than one year date difference means multi year report.
if ($start->diffInMonths($end) > 12) {
$period = 'MultiYear';
}
$class = sprintf('FireflyIII\Generator\Report\%s\%sReportGenerator', $type, $period);
if (class_exists($class)) {
/** @var ReportGeneratorInterface $obj */
$obj = new $class;
$obj->setStartDate($start);
$obj->setEndDate($end);
return $obj;
}
throw new FireflyException(sprintf('Cannot generate report. There is no "%s"-report for period "%s".', $type, $period));
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* ReportGeneratorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report;
use Carbon\Carbon;
use Illuminate\Support\Collection;
/**
* Interface ReportGeneratorInterface
*
* @package FireflyIII\Generator\Report
*/
interface ReportGeneratorInterface
{
/**
* @return string
*/
public function generate(): string;
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface;
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface;
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface;
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface;
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface;
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* MonthReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Standard;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use Illuminate\Support\Collection;
/**
* Class MonthReportGenerator
*
* @package FireflyIII\Generator\Report\Standard
*/
class MonthReportGenerator implements ReportGeneratorInterface
{
/** @var Collection */
private $accounts;
/** @var Carbon */
private $end;
/** @var Carbon */
private $start;
/**
* @return string
*/
public function generate(): string
{
/** @var ReportHelperInterface $helper */
$helper = app(ReportHelperInterface::class);
$bills = $helper->getBillReport($this->start, $this->end, $this->accounts);
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
$reportType = 'default';
// continue!
return view(
'reports.default.month',
compact('bills', 'accountIds', 'reportType')
)->with('start', $this->start)->with('end', $this->end)->render();
}
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface
{
return $this;
}
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface
{
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface
{
$this->end = $date;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface
{
$this->start = $date;
return $this;
}
}

View File

@@ -0,0 +1,106 @@
<?php
/**
* MultiYearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Standard;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use Illuminate\Support\Collection;
/**
* Class MonthReportGenerator
*
* @package FireflyIII\Generator\Report\Standard
*/
class MultiYearReportGenerator implements ReportGeneratorInterface
{
/** @var Collection */
private $accounts;
/** @var Carbon */
private $end;
/** @var Carbon */
private $start;
/**
* @return string
*/
public function generate(): string
{
// and some id's, joined:
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
$reportType = 'default';
// continue!
return view(
'reports.default.multi-year',
compact('accountIds', 'reportType')
)->with('start', $this->start)->with('end', $this->end)->render();
}
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface
{
return $this;
}
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface
{
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface
{
$this->end = $date;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface
{
$this->start = $date;
return $this;
}
}

View File

@@ -0,0 +1,106 @@
<?php
/**
* YearReportGenerator.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report\Standard;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use Illuminate\Support\Collection;
/**
* Class MonthReportGenerator
*
* @package FireflyIII\Generator\Report\Standard
*/
class YearReportGenerator implements ReportGeneratorInterface
{
/** @var Collection */
private $accounts;
/** @var Carbon */
private $end;
/** @var Carbon */
private $start;
/**
* @return string
*/
public function generate(): string
{
// and some id's, joined:
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
$reportType = 'default';
// continue!
return view(
'reports.default.year',
compact('accountIds', 'reportType')
)->with('start', $this->start)->with('end', $this->end)->render();
}
/**
* @param Collection $accounts
*
* @return ReportGeneratorInterface
*/
public function setAccounts(Collection $accounts): ReportGeneratorInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* @param Collection $budgets
*
* @return ReportGeneratorInterface
*/
public function setBudgets(Collection $budgets): ReportGeneratorInterface
{
return $this;
}
/**
* @param Collection $categories
*
* @return ReportGeneratorInterface
*/
public function setCategories(Collection $categories): ReportGeneratorInterface
{
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setEndDate(Carbon $date): ReportGeneratorInterface
{
$this->end = $date;
return $this;
}
/**
* @param Carbon $date
*
* @return ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface
{
$this->start = $date;
return $this;
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Support.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Generator\Report;
use FireflyIII\Models\Transaction;
use Illuminate\Support\Collection;
use Log;
/**
* Class Support
*
* @package FireflyIII\Generator\Report\Category
*/
class Support
{
/**
* @param Collection $collection
* @param array $accounts
*
* @return Collection
*/
public static function filterExpenses(Collection $collection, array $accounts): Collection
{
$result = $collection->filter(
function (Transaction $transaction) use ($accounts) {
$opposing = $transaction->opposing_account_id;
// remove internal transfer
if (in_array($opposing, $accounts)) {
Log::debug(sprintf('Filtered #%d because its opposite is in accounts.', $transaction->id));
return null;
}
// remove positive amount
if (bccomp($transaction->transaction_amount, '0') === 1) {
Log::debug(sprintf('Filtered #%d because amount is %f.', $transaction->id, $transaction->transaction_amount));
return null;
}
return $transaction;
}
);
return $result;
}
/**
* @param Collection $collection
* @param array $accounts
*
* @return Collection
*/
public static function filterIncome(Collection $collection, array $accounts): Collection
{
$result = $collection->filter(
function (Transaction $transaction) use ($accounts) {
$opposing = $transaction->opposing_account_id;
// remove internal transfer
if (in_array($opposing, $accounts)) {
Log::debug(sprintf('Filtered #%d because its opposite is in accounts.', $transaction->id));
return null;
}
// remove positive amount
if (bccomp($transaction->transaction_amount, '0') === -1) {
Log::debug(sprintf('Filtered #%d because amount is %f.', $transaction->id, $transaction->transaction_amount));
return null;
}
return $transaction;
}
);
return $result;
}
}

View File

@@ -1,50 +0,0 @@
<?php
/**
* AttachUserRole.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\UserRegistration;
use FireflyIII\Repositories\User\UserRepositoryInterface;
/**
* Class AttachUserRole
*
* @package FireflyIII\Handlers\Events
*/
class AttachUserRole
{
/**
* Create the event listener.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param UserRegistration $event
*/
public function handle(UserRegistration $event)
{
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
// first user ever?
if ($repository->count() == 1) {
$repository->attachRole($event->user, 'owner');
}
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* BudgetEventHandler.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use Carbon\Carbon;
use FireflyIII\Events\StoredBudgetLimit;
use FireflyIII\Events\UpdatedBudgetLimit;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition;
use Illuminate\Database\QueryException;
use Log;
/**
* Handles budget related events.
*
* Class BudgetEventHandler
*
* @package FireflyIII\Handlers\Events
*/
class BudgetEventHandler
{
/**
* This method creates a new budget limit repetition when a new budget limit has been created.
*
* @param StoredBudgetLimit $budgetLimitEvent
*
* @return bool
*/
public function storeRepetition(StoredBudgetLimit $budgetLimitEvent): bool
{
return $this->processRepetitionChange($budgetLimitEvent->budgetLimit, $budgetLimitEvent->end);
}
/**
* Updates, if present the budget limit repetition part of a budget limit.
*
* @param UpdatedBudgetLimit $budgetLimitEvent
*
* @return bool
*/
public function updateRepetition(UpdatedBudgetLimit $budgetLimitEvent): bool
{
return $this->processRepetitionChange($budgetLimitEvent->budgetLimit, $budgetLimitEvent->end);
}
/**
* @param BudgetLimit $budgetLimit
* @param Carbon $date
*
* @return bool
*/
private function processRepetitionChange(BudgetLimit $budgetLimit, Carbon $date): bool
{
$set = $budgetLimit->limitrepetitions()
->where('startdate', $budgetLimit->startdate->format('Y-m-d 00:00:00'))
->where('enddate', $date->format('Y-m-d 00:00:00'))
->get();
if ($set->count() == 0) {
$repetition = new LimitRepetition;
$repetition->startdate = $budgetLimit->startdate;
$repetition->enddate = $date;
$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();
}
return true;
}
}

View File

@@ -1,107 +0,0 @@
<?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,70 +0,0 @@
<?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;
use FireflyIII\Events\TransactionJournalStored;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\TransactionJournal;
/**
* Class ConnectJournalToPiggyBank
*
* @package FireflyIII\Handlers\Events
*/
class ConnectJournalToPiggyBank
{
/**
* Connect a new transaction journal to any related piggy banks.
*
* @param TransactionJournalStored $event
*
* @return bool
*/
public function handle(TransactionJournalStored $event): bool
{
/** @var TransactionJournal $journal */
$journal = $event->journal;
$piggyBankId = $event->piggyBankId;
/** @var PiggyBank $piggyBank */
$piggyBank = auth()->user()->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
if (is_null($piggyBank)) {
return true;
}
// update piggy bank rep for date of transaction journal.
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
if (is_null($repetition)) {
return true;
}
$amount = TransactionJournal::amountPositive($journal);
// if piggy account matches source account, the amount is positive
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
if (in_array($piggyBank->account_id, $sources)) {
$amount = bcmul($amount, '-1');
}
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
$repetition->save();
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
return true;
}
}

View File

@@ -1,68 +0,0 @@
<?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
{
/** @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,66 +0,0 @@
<?php
/**
* FireRulesForStore.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;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Rules\Processor;
use FireflyIII\User;
/**
* Class FireRulesForStore
*
* @package FireflyIII\Handlers\Events
*/
class FireRulesForStore
{
/**
* Connect a new transaction journal to any related piggy banks.
*
* @param TransactionJournalStored $event
*
* @return bool
*/
public function handle(TransactionJournalStored $event): bool
{
// get all the user's rule groups, with the rules, order by 'order'.
/** @var User $user */
$user = auth()->user();
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
//
/** @var RuleGroup $group */
foreach ($groups as $group) {
$rules = $group->rules()
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
->where('rule_triggers.trigger_type', 'user_action')
->where('rule_triggers.trigger_value', 'store-journal')
->where('rules.active', 1)
->get(['rules.*']);
/** @var Rule $rule */
foreach ($rules as $rule) {
$processor = Processor::make($rule);
$processor->handleTransactionJournal($event->journal);
if ($rule->stop_processing) {
return true;
}
}
}
return true;
}
}

View File

@@ -1,40 +0,0 @@
<?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;
use FireflyIII\Support\Events\BillScanner;
/**
* Class RescanJournal
*
* @package FireflyIII\Handlers\Events
*/
class ScanForBillsAfterStore
{
/**
* Scan a transaction journal for possible links to bills, right after storing.
*
* @param TransactionJournalStored $event
*
* @return bool
*/
public function handle(TransactionJournalStored $event): bool
{
$journal = $event->journal;
BillScanner::scan($journal);
return true;
}
}

View File

@@ -1,39 +0,0 @@
<?php
/**
* ScanForBillsAfterUpdate.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\TransactionJournalUpdated;
use FireflyIII\Support\Events\BillScanner;
/**
* Class RescanJournal
*
* @package FireflyIII\Handlers\Events
*/
class ScanForBillsAfterUpdate
{
/**
* Scan a transaction journal for possibly related bills after it has been updated.
*
* @param TransactionJournalUpdated $event
*
* @return bool
*/
public function handle(TransactionJournalUpdated $event): bool
{
$journal = $event->journal;
BillScanner::scan($journal);
return true;
}
}

View File

@@ -1,67 +0,0 @@
<?php
/**
* SendRegistrationMail.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\UserRegistration;
use Illuminate\Mail\Message;
use Log;
use Mail;
use Swift_TransportException;
/**
* Class SendRegistrationMail
*
* @package FireflyIII\Handlers\Events
*/
class SendRegistrationMail
{
/**
* Create the event listener.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param UserRegistration $event
*
* @return bool
*/
public function handle(UserRegistration $event): bool
{
$sendMail = env('SEND_REGISTRATION_MAIL', true);
if (!$sendMail) {
return true;
}
// get the email address
$email = $event->user->email;
$address = route('index');
$ipAddress = $event->ipAddress;
// send email.
try {
Mail::send(
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Welcome to Firefly III! ');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
}

View File

@@ -0,0 +1,164 @@
<?php
/**
* StoredJournalEventHandler.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\StoredTransactionJournal;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Rules\Processor;
use FireflyIII\Support\Events\BillScanner;
use Log;
/**
* Class StoredJournalEventHandler
*
* @package FireflyIII\Handlers\Events
*/
class StoredJournalEventHandler
{
/**
* This method connects a new transfer to a piggy bank.
*
* @param StoredTransactionJournal $storedJournalEvent
*
* @return bool
*/
public function connectToPiggyBank(StoredTransactionJournal $storedJournalEvent): bool
{
/** @var TransactionJournal $journal */
$journal = $storedJournalEvent->journal;
$piggyBankId = $storedJournalEvent->piggyBankId;
Log::debug(sprintf('Trying to connect journal %d to piggy bank %d.', $journal->id, $piggyBankId));
/** @var PiggyBank $piggyBank */
$piggyBank = $journal->user->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
if (is_null($piggyBank)) {
Log::error('No such piggy bank!');
return true;
}
Log::debug(sprintf('Found piggy bank #%d: "%s"', $piggyBank->id, $piggyBank->name));
// update piggy bank rep for date of transaction journal.
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
if (is_null($repetition)) {
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
return true;
}
$amount = TransactionJournal::amountPositive($journal);
Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
// if piggy account matches source account, the amount is positive
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
if (in_array($piggyBank->account_id, $sources)) {
$amount = bcmul($amount, '-1');
Log::debug(sprintf('Account #%d is the source, so will remove amount from piggy bank.', $piggyBank->account_id));
}
// if the amount is positive:
// make sure it fits in piggy bank:
if (bccomp($amount, '0') === 1) {
// amount is positive
$room = bcsub(strval($piggyBank->targetamount), strval($repetition->currentamount));
Log::debug(sprintf('Room in piggy bank for extra money is %f', $room));
if (bccomp($room, $amount) === -1) {
// $room is smaller than $amount
Log::debug(sprintf('There is NO room to add %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
Log::debug(sprintf('New amount is %f', $room));
$amount = $room;
}
}
if (bccomp($amount, '0') === -1) {
// amount is negative
Log::debug(sprintf('Max amount to remove is %f', $repetition->currentamount));
$compare = bcmul($repetition->currentamount, '-1');
if (bccomp($compare, $amount) === 1) {
// $currentamount is smaller than $amount
Log::debug(sprintf('Cannot remove %f from piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
Log::debug(sprintf('New amount is %f', $compare));
$amount = $compare;
}
}
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
$repetition->save();
/** @var PiggyBankEvent $storedJournalEvent */
$storedJournalEvent = PiggyBankEvent::create(
['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]
);
Log::debug(sprintf('Created piggy bank event #%d', $storedJournalEvent->id));
return true;
}
/**
* This method grabs all the users rules and processes them.
*
* @param StoredTransactionJournal $storedJournalEvent
*
* @return bool
*/
public function processRules(StoredTransactionJournal $storedJournalEvent): bool
{
// get all the user's rule groups, with the rules, order by 'order'.
$journal = $storedJournalEvent->journal;
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
//
/** @var RuleGroup $group */
foreach ($groups as $group) {
$rules = $group->rules()
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
->where('rule_triggers.trigger_type', 'user_action')
->where('rule_triggers.trigger_value', 'store-journal')
->where('rules.active', 1)
->get(['rules.*']);
/** @var Rule $rule */
foreach ($rules as $rule) {
$processor = Processor::make($rule);
$processor->handleTransactionJournal($journal);
if ($rule->stop_processing) {
return true;
}
}
}
return true;
}
/**
* This method calls a special bill scanner that will check if the stored journal is part of a bill.
*
* @param StoredTransactionJournal $storedJournalEvent
*
* @return bool
*/
public function scanBills(StoredTransactionJournal $storedJournalEvent): bool
{
$journal = $storedJournalEvent->journal;
BillScanner::scan($journal);
return true;
}
}

View File

@@ -1,72 +0,0 @@
<?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;
use FireflyIII\Events\TransactionJournalUpdated;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\TransactionJournal;
/**
* Class UpdateJournalConnection
*
* @package FireflyIII\Handlers\Events
*/
class UpdateJournalConnection
{
/**
* Handle the event.
*
* @param TransactionJournalUpdated $event
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
*
* @return bool
*/
public function handle(TransactionJournalUpdated $event):bool
{
$journal = $event->journal;
if (!$journal->isTransfer()) {
return true;
}
// get the event connected to this journal:
/** @var PiggyBankEvent $event */
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
if (is_null($event)) {
return false;
}
$piggyBank = $event->piggyBank()->first();
$repetition = null;
if (!is_null($piggyBank)) {
/** @var PiggyBankRepetition $repetition */
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
}
if (is_null($repetition)) {
return false;
}
$amount = TransactionJournal::amount($journal);
$diff = bcsub($amount, $event->amount); // update current repetition
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
$repetition->save();
$event->amount = $amount;
$event->save();
return true;
}
}

View File

@@ -1,42 +1,45 @@
<?php
/**
* FireRulesForUpdate.php
* UpdatedJournalEventHandler.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.
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\TransactionJournalUpdated;
use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Rules\Processor;
use FireflyIII\User;
use FireflyIII\Support\Events\BillScanner;
/**
* Class FireRulesForUpdate
* Class UpdatedJournalEventHandler
*
* @package FireflyIII\Handlers\Events
*/
class FireRulesForUpdate
class UpdatedJournalEventHandler
{
/**
* Handle the event.
* This method will check all the rules when a journal is updated.
*
* @param TransactionJournalUpdated $event
* @param UpdatedTransactionJournal $updatedJournalEvent
*
* @return bool
*/
public function handle(TransactionJournalUpdated $event): bool
public function processRules(UpdatedTransactionJournal $updatedJournalEvent): bool
{
// get all the user's rule groups, with the rules, order by 'order'.
/** @var User $user */
$user = auth()->user();
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
$journal = $updatedJournalEvent->journal;
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
//
/** @var RuleGroup $group */
foreach ($groups as $group) {
@@ -49,7 +52,7 @@ class FireRulesForUpdate
/** @var Rule $rule */
foreach ($rules as $rule) {
$processor = Processor::make($rule);
$processor->handleTransactionJournal($event->journal);
$processor->handleTransactionJournal($journal);
if ($rule->stop_processing) {
break;
@@ -60,4 +63,19 @@ class FireRulesForUpdate
return true;
}
/**
* This method calls a special bill scanner that will check if the updated journal is part of a bill.
*
* @param UpdatedTransactionJournal $updatedJournalEvent
*
* @return bool
*/
public function scanBills(UpdatedTransactionJournal $updatedJournalEvent): bool
{
$journal = $updatedJournalEvent->journal;
BillScanner::scan($journal);
return true;
}
}

View File

@@ -1,107 +0,0 @@
<?php
/**
* UserConfirmation.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 Exception;
use FireflyIII\Events\ResendConfirmation;
use FireflyIII\Events\UserRegistration;
use FireflyIII\User;
use Illuminate\Mail\Message;
use Log;
use Mail;
use Preferences;
use Swift_TransportException;
/**
* Class UserConfirmation
*
* @package FireflyIII\Handlers\Events
*/
class UserConfirmation
{
/**
* Create the event listener.
*
*/
public function __construct()
{
//
}
/**
* @param ResendConfirmation $event
*
* @return bool
*/
public function resendConfirmation(ResendConfirmation $event): bool
{
$user = $event->user;
$ipAddress = $event->ipAddress;
$this->doConfirm($user, $ipAddress);
return true;
}
/**
* Handle the event.
*
* @param UserRegistration $event
*
* @return bool
*/
public function sendConfirmation(UserRegistration $event): bool
{
$user = $event->user;
$ipAddress = $event->ipAddress;
$this->doConfirm($user, $ipAddress);
return true;
}
/**
* @param User $user
* @param string $ipAddress
*/
private function doConfirm(User $user, string $ipAddress)
{
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
if ($confirmAccount === false) {
Preferences::setForUser($user, 'user_confirmed', true);
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
Preferences::mark();
return;
}
$email = $user->email;
$code = str_random(16);
$route = route('do_confirm_account', [$code]);
Preferences::setForUser($user, 'user_confirmed', false);
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
Preferences::setForUser($user, 'user_confirmed_code', $code);
try {
Mail::send(
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
function (Message $message) use ($email) {
$message->to($email, $email)->subject('Please confirm your Firefly III account');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
} catch (Exception $e) {
Log::error($e->getMessage());
}
return;
}
}

View File

@@ -0,0 +1,446 @@
<?php
/**
* UserEventHandler.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Handlers\Events;
use Exception;
use FireflyConfig;
use FireflyIII\Events\BlockedBadLogin;
use FireflyIII\Events\BlockedUseOfDomain;
use FireflyIII\Events\BlockedUseOfEmail;
use FireflyIII\Events\BlockedUserLogin;
use FireflyIII\Events\ConfirmedUser;
use FireflyIII\Events\DeletedUser;
use FireflyIII\Events\LockedOutUser;
use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword;
use FireflyIII\Events\ResentConfirmation;
use FireflyIII\Models\Configuration;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Mail\Message;
use Log;
use Mail;
use Preferences;
use Session;
use Swift_TransportException;
/**
* Class UserEventHandler
*
* This class responds to any events that have anything to do with the User object.
*
* The method name reflects what is being done. This is in the present tense.
*
*
* @package FireflyIII\Handlers\Events
*/
class UserEventHandler
{
/**
* This method will bestow upon a user the "owner" role if he is the first user in the system.
*
* @param RegisteredUser $event
*
* @return bool
*/
public function attachUserRole(RegisteredUser $event): bool
{
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
// first user ever?
if ($repository->count() === 1) {
$repository->attachRole($event->user, 'owner');
}
return true;
}
/**
* Handle user logout events.
*
* @return bool
*/
public function logoutUser(): bool
{
// dump stuff from the session:
Session::forget('twofactor-authenticated');
Session::forget('twofactor-authenticated-date');
return true;
}
/**
* @param BlockedBadLogin $event
*
* @return bool
*/
public function reportBadLogin(BlockedBadLogin $event)
{
$email = $event->email;
$owner = env('SITE_OWNER');
$ipAddress = $event->ipAddress;
/** @var Configuration $sendmail */
$sendmail = FireflyConfig::get('mail_for_bad_login', config('firefly.configuration.mail_for_bad_login'));
Log::debug(sprintf('Now in reportBadLogin for email address %s', $email));
Log::error(sprintf('User %s tried to login with bad credentials.', $email));
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
return true;
}
try {
Mail::send(
['emails.blocked-bad-creds-html', 'emails.blocked-bad-creds-text'], ['email' => $email, 'ip' => $ipAddress],
function (Message $message) use ($owner) {
$message->to($owner, $owner)->subject('Blocked login attempt with bad credentials');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* @param BlockedUserLogin $event
*
* @return bool
*/
public function reportBlockedUser(BlockedUserLogin $event): bool
{
$user = $event->user;
$owner = env('SITE_OWNER');
$email = $user->email;
$ipAddress = $event->ipAddress;
/** @var Configuration $sendmail */
$sendmail = FireflyConfig::get('mail_for_blocked_login', config('firefly.configuration.mail_for_blocked_login'));
Log::debug(sprintf('Now in reportBlockedUser for email address %s', $email));
Log::error(sprintf('User #%d (%s) has their accout blocked (blocked_code is "%s") but tried to login.', $user->id, $email, $user->blocked_code));
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
return true;
}
// send email message:
try {
Mail::send(
['emails.blocked-login-html', 'emails.blocked-login-text'],
[
'user_id' => $user->id,
'user_address' => $email,
'ip' => $ipAddress,
'code' => $user->blocked_code,
], function (Message $message) use ($owner, $user) {
$message->to($owner, $owner)->subject('Blocked login attempt of blocked user');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* @param LockedOutUser $event
*
* @return bool
*/
public function reportLockout(LockedOutUser $event): bool
{
$email = $event->email;
$owner = env('SITE_OWNER');
$ipAddress = $event->ipAddress;
/** @var Configuration $sendmail */
$sendmail = FireflyConfig::get('mail_for_lockout', config('firefly.configuration.mail_for_lockout'));
Log::debug(sprintf('Now in respondToLockout for email address %s', $email));
Log::error(sprintf('User %s was locked out after too many invalid login attempts.', $email));
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
return true;
}
// send email message:
try {
Mail::send(
['emails.locked-out-html', 'emails.locked-out-text'], ['email' => $email, 'ip' => $ipAddress], function (Message $message) use ($owner) {
$message->to($owner, $owner)->subject('User was locked out');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* @param BlockedUseOfDomain $event
*
* @return bool
*/
public function reportUseBlockedDomain(BlockedUseOfDomain $event): bool
{
$email = $event->email;
$owner = env('SITE_OWNER');
$ipAddress = $event->ipAddress;
$parts = explode('@', $email);
/** @var Configuration $sendmail */
$sendmail = FireflyConfig::get('mail_for_blocked_domain', config('firefly.configuration.mail_for_blocked_domain'));
Log::debug(sprintf('Now in reportUseBlockedDomain for email address %s', $email));
Log::error(sprintf('Somebody tried to register using an email address (%s) connected to a banned domain (%s).', $email, $parts[1]));
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
return true;
}
// send email message:
try {
Mail::send(
['emails.blocked-registration-html', 'emails.blocked-registration-text'],
[
'email_address' => $email,
'blocked_domain' => $parts[1],
'ip' => $ipAddress,
], function (Message $message) use ($owner) {
$message->to($owner, $owner)->subject('Blocked registration attempt with blocked domain');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* @param BlockedUseOfEmail $event
*
* @return bool
*/
public function reportUseOfBlockedEmail(BlockedUseOfEmail $event): bool
{
$email = $event->email;
$owner = env('SITE_OWNER');
$ipAddress = $event->ipAddress;
/** @var Configuration $sendmail */
$sendmail = FireflyConfig::get('mail_for_blocked_email', config('firefly.configuration.mail_for_blocked_email'));
Log::debug(sprintf('Now in reportUseOfBlockedEmail for email address %s', $email));
Log::error(sprintf('Somebody tried to register using email address %s which is blocked (SHA2 hash).', $email));
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
return true;
}
// send email message:
try {
Mail::send(
['emails.blocked-email-html', 'emails.blocked-email-text'],
[
'user_address' => $email,
'ip' => $ipAddress,
], function (Message $message) use ($owner) {
$message->to($owner, $owner)->subject('Blocked registration attempt with blocked email address');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* @param DeletedUser $event
*
* @return bool
*/
public function saveEmailAddress(DeletedUser $event): bool
{
Preferences::mark();
$email = hash('sha256', $event->email);
Log::debug(sprintf('Hash of email is %s', $email));
/** @var Configuration $configuration */
$configuration = FireflyConfig::get('deleted_users', []);
$content = $configuration->data;
if (!is_array($content)) {
$content = [];
}
$content[] = $email;
$configuration->data = $content;
Log::debug('New content of deleted_users is ', $content);
FireflyConfig::set('deleted_users', $content);
Preferences::mark();
return true;
}
/**
* This method will send a newly registered user a confirmation message, urging him or her to activate their account.
*
* @param RegisteredUser $event
*
* @return bool
*/
public function sendConfirmationMessage(RegisteredUser $event): bool
{
return $this->sendConfirmation($event->user, $event->ipAddress);
}
/**
* If the user has somehow lost his or her confirmation message, this event will send it to the user again.
*
* At the moment, this method is exactly the same as the ::sendConfirmationMessage method, but that will change.
*
* @param ResentConfirmation $event
*
* @return bool
*/
function sendConfirmationMessageAgain(ResentConfirmation $event): bool
{
return $this->sendConfirmation($event->user, $event->ipAddress);
}
/**
* @param RequestedNewPassword $event
*
* @return bool
*/
public function sendNewPassword(RequestedNewPassword $event): bool
{
$email = $event->user->email;
$ipAddress = $event->ipAddress;
$token = $event->token;
$url = route('password.reset', [$token]);
// send email.
try {
Mail::send(
['emails.password-html', 'emails.password-text'], ['url' => $url, 'ip' => $ipAddress], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Your password reset request');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* This method will send the user a registration mail, welcoming him or her to Firefly III.
* This message is only sent when the configuration of Firefly III says so.
*
* @param RegisteredUser $event
*
* @return bool
*/
public function sendRegistrationMail(RegisteredUser $event)
{
$sendMail = env('SEND_REGISTRATION_MAIL', true);
if (!$sendMail) {
return true;
}
// get the email address
$email = $event->user->email;
$address = route('index');
$ipAddress = $event->ipAddress;
// send email.
try {
Mail::send(
['emails.registered-html', 'emails.registered-text'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Welcome to Firefly III!');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
return true;
}
/**
* When the user is confirmed, this method stores the IP address of the user
* as a preference. Since this preference cannot be edited, it is effectively hidden
* from the user yet stored conveniently.
*
* @param ConfirmedUser $event
*
* @return bool
*/
public function storeConfirmationIpAddress(ConfirmedUser $event): bool
{
Preferences::setForUser($event->user, 'confirmation_ip_address', $event->ipAddress);
return true;
}
/**
* This message stores the users IP address on registration, in much the same
* fashion as the previous method.
*
* @param RegisteredUser $event
*
* @return bool
*/
public function storeRegistrationIpAddress(RegisteredUser $event): bool
{
Preferences::setForUser($event->user, 'registration_ip_address', $event->ipAddress);
return true;
}
/**
* @param User $user
* @param string $ipAddress
*
* @return bool
*/
private function sendConfirmation(User $user, string $ipAddress): bool
{
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'))->data;
if ($mustConfirmAccount === false) {
Preferences::setForUser($user, 'user_confirmed', true);
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
Preferences::mark();
return true;
}
$email = $user->email;
$code = str_random(16);
$route = route('do_confirm_account', [$code]);
Preferences::setForUser($user, 'user_confirmed', false);
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
Preferences::setForUser($user, 'user_confirmed_code', $code);
try {
Mail::send(
['emails.confirm-account-html', 'emails.confirm-account-text'], ['route' => $route, 'ip' => $ipAddress],
function (Message $message) use ($email) {
$message->to($email, $email)->subject('Please confirm your Firefly III account');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
} catch (Exception $e) {
Log::error($e->getMessage());
}
return true;
}
}

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