mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-17 02:05:34 +00:00
Compare commits
348 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
67cc611495 | ||
|
7e2c24b82e | ||
|
4a6bbd4dca | ||
|
166bfba5b9 | ||
|
87b8ac5f4e | ||
|
46b4100291 | ||
|
83090ade94 | ||
|
44b7a42d5a | ||
|
1a5617d430 | ||
|
fa818e0924 | ||
|
f87b531fe1 | ||
|
82fd0c4d37 | ||
|
26ceb9e3be | ||
|
743458b853 | ||
|
920e5f6fbe | ||
|
fc0dd22769 | ||
|
c7c61ce280 | ||
|
5f5a603f71 | ||
|
d611858883 | ||
|
dbc9ce76a0 | ||
|
62386e2e40 | ||
|
5aa7ab5e37 | ||
|
be1b57eab7 | ||
|
ad5c8b41e2 | ||
|
09752b25ad | ||
|
3f317f961b | ||
|
d6d6a62fda | ||
|
528833b831 | ||
|
95e2bca4a6 | ||
|
dfd3327108 | ||
|
653befbcd4 | ||
|
33202efcdc | ||
|
77a37411ba | ||
|
491f221741 | ||
|
e8e125a598 | ||
|
cb01ae0ac5 | ||
|
a09469c01f | ||
|
662f398b08 | ||
|
d7aef627b8 | ||
|
87bcf293aa | ||
|
0171831ebb | ||
|
50cc455f0f | ||
|
47a7729358 | ||
|
6d508e61a0 | ||
|
8ef9223d84 | ||
|
e58ea4d0c7 | ||
|
9629ba916e | ||
|
aad4df1596 | ||
|
30ed25f80a | ||
|
8b7000681c | ||
|
221adbf3db | ||
|
39129d8cd0 | ||
|
2c2d444906 | ||
|
04a1d785bf | ||
|
c0a0aa4652 | ||
|
21c24fd7f0 | ||
|
beb358f8ee | ||
|
e3cd11ec2e | ||
|
ee08fc2421 | ||
|
ae30f7920b | ||
|
f4786c3ec8 | ||
|
8b9e4d2539 | ||
|
d7ca7ed632 | ||
|
1346b25fc7 | ||
|
15d9314503 | ||
|
93f4006c9e | ||
|
16182fec6c | ||
|
99606ba936 | ||
|
be1ed56d42 | ||
|
d7fb6f83b8 | ||
|
665f1f470a | ||
|
7867f26120 | ||
|
8e195bf811 | ||
|
e3403dc87f | ||
|
5844e95488 | ||
|
cb3a1f2ff6 | ||
|
f95edb06a9 | ||
|
86d13060bc | ||
|
0b8c2f6f8d | ||
|
589cafc64f | ||
|
448dc7b5c3 | ||
|
10cfde6cab | ||
|
e48eb2ce2f | ||
|
20a30a2d1d | ||
|
2e5b8418ae | ||
|
054fd229d2 | ||
|
9bdf2c8877 | ||
|
04f858a355 | ||
|
a9bf405a65 | ||
|
463c866cfa | ||
|
03fe0c8fff | ||
|
102d9f3510 | ||
|
3cf9a40c42 | ||
|
ff33267296 | ||
|
f0dab5bdb9 | ||
|
209a907c61 | ||
|
c7984d4363 | ||
|
a388313e1c | ||
|
a3933cb307 | ||
|
89c82d9be9 | ||
|
6e6311a1a1 | ||
|
69b334ed8a | ||
|
a84b6f377f | ||
|
ee5db4e4cc | ||
|
20f3322e5a | ||
|
1e84bc3743 | ||
|
7f198cbd50 | ||
|
1c7d5ccefc | ||
|
41dc4d994e | ||
|
490733bdd1 | ||
|
ed8cf8c431 | ||
|
a7e1f85c4d | ||
|
4b8919420d | ||
|
9afc5d67a4 | ||
|
72afaddd7c | ||
|
8ae3182e1c | ||
|
9d7e16b390 | ||
|
3a2ed202ad | ||
|
9e4b9b98ab | ||
|
e65fb7d995 | ||
|
7197830edc | ||
|
687603ae84 | ||
|
23fc25f926 | ||
|
e0c1f07f92 | ||
|
9424aa3378 | ||
|
57e6e0945f | ||
|
d87a033f29 | ||
|
10481895e6 | ||
|
813432f386 | ||
|
aba78c9776 | ||
|
8dc56bcee0 | ||
|
32b6e030ef | ||
|
a27f5d2474 | ||
|
e2fe8cfb75 | ||
|
9f1c346365 | ||
|
3e56803e95 | ||
|
fc5feb054d | ||
|
8fc233e436 | ||
|
22303eb2ff | ||
|
d6477ff9ff | ||
|
a0f6f13650 | ||
|
1dd213d587 | ||
|
569e51afbe | ||
|
ff06a4ed0d | ||
|
ea3fdb0668 | ||
|
bd917f6484 | ||
|
ee96311222 | ||
|
135153ff9c | ||
|
fdb98133c8 | ||
|
ad4e2c0a85 | ||
|
e38cb263aa | ||
|
0922136389 | ||
|
2a05517a30 | ||
|
a0ee924aeb | ||
|
1595afce68 | ||
|
4919d730c8 | ||
|
1407d6cc66 | ||
|
55b092e7a0 | ||
|
93afb754f3 | ||
|
81c0ea8f5c | ||
|
6faacd3781 | ||
|
ea1e9e407f | ||
|
d4f5aa1578 | ||
|
1cbbf3fa5d | ||
|
dad3dc71ca | ||
|
afb1e9f230 | ||
|
c33dd1ecee | ||
|
7e31a29b12 | ||
|
9a69ce309e | ||
|
b99bfcd02e | ||
|
adb16e4560 | ||
|
953c38563b | ||
|
89ee9c058a | ||
|
bac7a73555 | ||
|
5fb6ff230b | ||
|
605a718418 | ||
|
994542c75d | ||
|
d5fdce02fa | ||
|
d3637de0c3 | ||
|
63acbb222d | ||
|
5e1fe157b6 | ||
|
8e811da967 | ||
|
fb23108f4e | ||
|
a0220eb5f8 | ||
|
c16cbd5bc8 | ||
|
2d0673e1bc | ||
|
a90e00d577 | ||
|
8db96025a3 | ||
|
595596d73f | ||
|
240797e92a | ||
|
6cafb91680 | ||
|
852ce3e32f | ||
|
6b9c9458fa | ||
|
970ce917b0 | ||
|
db46d450bf | ||
|
db806b92dd | ||
|
6765f08b07 | ||
|
99d75ba14b | ||
|
0e8ce5680c | ||
|
fd01b54a14 | ||
|
ce6253bbd7 | ||
|
4fd33f19c6 | ||
|
01ae278f09 | ||
|
7907c71e47 | ||
|
4e44733dcc | ||
|
dd1d7bb02a | ||
|
6f933b3bd1 | ||
|
243530b750 | ||
|
ea984281b0 | ||
|
92cd3d60b9 | ||
|
5920ccee04 | ||
|
569fec4610 | ||
|
5770edcde2 | ||
|
1fb0a64f31 | ||
|
fe66d089ad | ||
|
cef10b4d4e | ||
|
b45aa6446d | ||
|
61749312b2 | ||
|
842bb2c5a6 | ||
|
4358fe99b1 | ||
|
3fda8b3714 | ||
|
09f3274adc | ||
|
029224f708 | ||
|
e87cce12f8 | ||
|
7660667153 | ||
|
222b3008d5 | ||
|
398cf0b312 | ||
|
5ad8be2483 | ||
|
6fe319702d | ||
|
32c89f9a98 | ||
|
64f983786e | ||
|
16438b416d | ||
|
52cd292a69 | ||
|
53b501df19 | ||
|
477acafc4c | ||
|
ab9146b7c6 | ||
|
4d15913e18 | ||
|
63a91811e2 | ||
|
9df4da6173 | ||
|
643927799b | ||
|
2652e23089 | ||
|
b70c5ae41e | ||
|
c53d9b2855 | ||
|
2f6712be87 | ||
|
37f78985ae | ||
|
34ac9bc71a | ||
|
19ff2484fd | ||
|
b7ef2211d9 | ||
|
c5206a4559 | ||
|
894296f63d | ||
|
61526df245 | ||
|
92549c4485 | ||
|
6014892d4d | ||
|
9515ce6807 | ||
|
1adb0f2f0e | ||
|
00b1b54347 | ||
|
282ce041e1 | ||
|
3215c4ee4b | ||
|
fce00c95c9 | ||
|
0a69ab1dc2 | ||
|
94771d250a | ||
|
b8395a1dbb | ||
|
0436cd1584 | ||
|
2c774bb94c | ||
|
b879d90b0d | ||
|
ba52b5c328 | ||
|
bf61de13f4 | ||
|
b26e67ae07 | ||
|
edafd16c75 | ||
|
c62e3dcb78 | ||
|
68be58c9f2 | ||
|
a25a499ed4 | ||
|
97f67912f4 | ||
|
e2f3788ff5 | ||
|
fd1f06c2cb | ||
|
2db8d25038 | ||
|
d618ddc8c5 | ||
|
79aa0afc97 | ||
|
e53d294c1c | ||
|
aedc3fdff9 | ||
|
b67dfeced2 | ||
|
65dbfcba5c | ||
|
8f14c78ba1 | ||
|
be1b64bb78 | ||
|
a34c285820 | ||
|
298f0c194d | ||
|
f5ad569aba | ||
|
c70df01532 | ||
|
03e115e066 | ||
|
b88fce35ad | ||
|
d214e9ff49 | ||
|
bd8382c005 | ||
|
18cb815e45 | ||
|
800e8aca6e | ||
|
63a6e0754b | ||
|
4abc271805 | ||
|
22cca3858c | ||
|
b816fbdf82 | ||
|
d400060b8b | ||
|
c88cfa2d9d | ||
|
b060027304 | ||
|
d4787aca9c | ||
|
69ae2e93f8 | ||
|
82a37c62c1 | ||
|
ca69970242 | ||
|
fac3853d95 | ||
|
9dd2f447cc | ||
|
ecbd7ca95b | ||
|
0c52d54d7d | ||
|
78276ac66b | ||
|
ca0a22d755 | ||
|
47361fd77a | ||
|
1af6fd5d74 | ||
|
51df78ad2d | ||
|
84a3e68eb5 | ||
|
b2904e09d8 | ||
|
fc42a621e4 | ||
|
a1c4fb73cd | ||
|
c18f19db97 | ||
|
ebc712f6b5 | ||
|
ef0057d88d | ||
|
a8fdfdd5e0 | ||
|
89f7e1ba2a | ||
|
6508b4058f | ||
|
bec5d93af6 | ||
|
1125fcd6c5 | ||
|
ff43a547a6 | ||
|
ca8684146c | ||
|
44bea62383 | ||
|
8dc2faa5e5 | ||
|
f4867d1d09 | ||
|
8d172801b5 | ||
|
db6e6dfe4a | ||
|
61007a95a6 | ||
|
bf138670e8 | ||
|
0e59f7433c | ||
|
9a033ac62a | ||
|
789412ee6a | ||
|
91125d20ef | ||
|
292b3672e2 | ||
|
14ef6b753c | ||
|
55fcb97a10 | ||
|
6b8ec544c1 | ||
|
c0aad385cd | ||
|
ecfb5e4711 | ||
|
46c9967a68 | ||
|
176c44e2b9 | ||
|
5957cf5ff8 |
@@ -41,6 +41,8 @@ SHOW_INCOMPLETE_TRANSLATIONS=false
|
||||
|
||||
CACHE_PREFIX=firefly
|
||||
|
||||
EXCHANGE_RATE_SERVICE=fixerio
|
||||
|
||||
GOOGLE_MAPS_API_KEY=
|
||||
ANALYTICS_ID=
|
||||
SITE_OWNER=mail@example.com
|
||||
|
@@ -3,6 +3,7 @@ APP_DEBUG=true
|
||||
APP_FORCE_SSL=false
|
||||
APP_FORCE_ROOT=
|
||||
APP_KEY=TestTestTestTestTestTestTestTest
|
||||
APP_LOG=daily
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_URL=http://localhost
|
||||
|
||||
|
@@ -9,7 +9,6 @@ cache:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
install:
|
||||
- if [[ "$(php -v | grep 'PHP 7')" ]]; then phpenv config-rm xdebug.ini; fi
|
||||
- rm composer.lock
|
||||
- composer update --no-scripts
|
||||
- cp .env.testing .env
|
||||
@@ -18,9 +17,13 @@ install:
|
||||
- php artisan env
|
||||
- cp .env.testing .env
|
||||
- mv storage/database/databasecopy.sqlite storage/database/database.sqlite
|
||||
- mkdir -p build/logs
|
||||
|
||||
script:
|
||||
- phpunit
|
||||
- phpunit -c phpunit.coverage.xml
|
||||
|
||||
after_success:
|
||||
- travis_retry php vendor/bin/coveralls -x storage/build/clover.xml
|
||||
|
||||
# safelist
|
||||
branches:
|
||||
|
58
CHANGELOG.md
58
CHANGELOG.md
@@ -2,6 +2,37 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [4.4.1] - 2017-04-27
|
||||
|
||||
### Added
|
||||
- Support for deployment on Heroku
|
||||
|
||||
### Fixed
|
||||
- Bug in new-user routine.
|
||||
|
||||
## [4.4.0] - 2017-04-23
|
||||
### Added
|
||||
- Firefly III can now handle foreign currencies better, including some code to get the exchange rate live from the web.
|
||||
- Can now make rules for attachments, see #608, as suggested by dzaikos.
|
||||
|
||||
### Fixed
|
||||
- Fixed #629, reported by forcaeluz
|
||||
- Fixed #630, reported by welbert
|
||||
- And more various bug fixes.
|
||||
|
||||
## [4.3.8] - 2017-04-08
|
||||
|
||||
### Added
|
||||
- Better overview / show pages.
|
||||
- #628, as reported by [xzaz](https://github.com/xzaz).
|
||||
- Greatly expanded test coverage
|
||||
|
||||
### Fixed
|
||||
- #619, as reported by [dfiel](https://github.com/dfiel).
|
||||
- #620, as reported by [forcaeluz](https://github.com/forcaeluz).
|
||||
- Attempt to fix #624, as reported by [TheSerenin](https://github.com/TheSerenin).
|
||||
- Favicon link is relative now, fixed by [welbert](https://github.com/welbert).
|
||||
- Some search bugs
|
||||
|
||||
## [4.3.7] - 2017-03-06
|
||||
### Added
|
||||
@@ -188,13 +219,6 @@ An intermediate release because something in the Twig and Twigbridge libraries i
|
||||
- Updated all email messages.
|
||||
- Made some fonts local
|
||||
|
||||
|
||||
### Deprecated
|
||||
- Initial release.
|
||||
|
||||
### Removed
|
||||
- Initial release.
|
||||
|
||||
### Fixed
|
||||
- Issue #408
|
||||
- Various issues with split journals
|
||||
@@ -203,11 +227,6 @@ An intermediate release because something in the Twig and Twigbridge libraries i
|
||||
- Issue #422, thx [xzaz](https://github.com/xzaz)
|
||||
- Various import bugs, such as #416 ([zjean](https://github.com/zjean))
|
||||
|
||||
|
||||
### Security
|
||||
- Initial release.
|
||||
|
||||
|
||||
## [4.1.7] - 2016-11-19
|
||||
### Added
|
||||
- Check for database table presence in console commands.
|
||||
@@ -330,15 +349,6 @@ An intermediate release because something in the Twig and Twigbridge libraries i
|
||||
- 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](https://github.com/cyberkov)
|
||||
@@ -346,12 +356,6 @@ An intermediate release because something in the Twig and Twigbridge libraries i
|
||||
- #336
|
||||
- #338 found by [roberthorlings](https://github.com/roberthorlings)
|
||||
|
||||
### Security
|
||||
- Initial release.
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.0.0] - 2015-09-26
|
||||
### Added
|
||||
- Upgraded to Laravel 5.3, most other libraries upgraded as well.
|
||||
|
1
Procfile
Normal file
1
Procfile
Normal file
@@ -0,0 +1 @@
|
||||
web: vendor/bin/heroku-php-nginx -C nginx_app.conf public/
|
@@ -10,7 +10,7 @@
|
||||
|
||||
## Try it out!
|
||||
|
||||
Try out Firefly III on the [demo site](https://firefly-iii.nder.be/).
|
||||
[](https://heroku.com/deploy?template=https://github.com/firefly-iii/firefly-iii/tree/master)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -35,4 +35,4 @@ If you like Firefly and if it helps you save lots of money, why not send me [a d
|
||||
|
||||
If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com).
|
||||
|
||||
[](https://travis-ci.org/firefly-iii/firefly-iii) [](https://scrutinizer-ci.com/g/firefly-iii/firefly-iii/?branch=master)
|
||||
[](https://travis-ci.org/firefly-iii/firefly-iii) [](https://scrutinizer-ci.com/g/firefly-iii/firefly-iii/?branch=master) [](https://coveralls.io/github/firefly-iii/firefly-iii?branch=master)
|
||||
|
59
app.json
Normal file
59
app.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"name": "Firefly III",
|
||||
"description": "A free and open source personal finances manager",
|
||||
"repository": "https://github.com/firefly-iii/firefly-iii",
|
||||
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png",
|
||||
"keywords": [
|
||||
"finance",
|
||||
"finances",
|
||||
"manager",
|
||||
"management",
|
||||
"euro",
|
||||
"dollar",
|
||||
"laravel",
|
||||
"money",
|
||||
"currency",
|
||||
"financials",
|
||||
"financial",
|
||||
"budgets",
|
||||
"administration",
|
||||
"tool",
|
||||
"tooling",
|
||||
"help",
|
||||
"helper",
|
||||
"assistant",
|
||||
"planning",
|
||||
"organizing",
|
||||
"bills",
|
||||
"personal finance",
|
||||
"budgets",
|
||||
"budgeting",
|
||||
"budgeting tool",
|
||||
"budgeting application",
|
||||
"transactions",
|
||||
"self hosted",
|
||||
"self-hosted",
|
||||
"transfers",
|
||||
"management"
|
||||
],
|
||||
"website": "https://firefly-iii.github.io/",
|
||||
"addons": [
|
||||
{
|
||||
"plan": "heroku-postgresql"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"postdeploy": "export APP_KEY=$(php artisan --no-ansi key:generate --show)"
|
||||
},
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "heroku/php"
|
||||
}
|
||||
],
|
||||
"env": {
|
||||
"APP_KEY": {
|
||||
"description": "This key is used to encrypt your data.",
|
||||
"value": "base64:If1gJN4pyycXTq+WS5TjneDympKuu+8SKvTl6RZnhJg="
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ConfigureLogging.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\Bootstrap;
|
||||
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Foundation\Bootstrap\ConfigureLogging as IlluminateConfigureLogging;
|
||||
use Illuminate\Log\Writer;
|
||||
|
||||
/**
|
||||
* Class ConfigureLogging
|
||||
*
|
||||
* @package FireflyIII\Bootstrap
|
||||
*/
|
||||
class ConfigureLogging extends IlluminateConfigureLogging
|
||||
{
|
||||
|
||||
/**
|
||||
* Configure the Monolog handlers for the application.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @param \Illuminate\Log\Writer $log
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureDailyHandler(Application $app, Writer $log)
|
||||
{
|
||||
$config = $app->make('config');
|
||||
|
||||
$maxFiles = $config->get('app.log_max_files');
|
||||
|
||||
$log->useDailyFiles(
|
||||
$app->storagePath() . '/logs/firefly-iii.log', is_null($maxFiles) ? 5 : $maxFiles,
|
||||
$config->get('app.log_level', 'debug')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the Monolog handlers for the application.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @param \Illuminate\Log\Writer $log
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureSingleHandler(Application $app, Writer $log)
|
||||
{
|
||||
$log->useFiles(
|
||||
$app->storagePath() . '/logs/firefly-iii.log',
|
||||
$app->make('config')->get('app.log_level', 'debug')
|
||||
);
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
@@ -9,19 +9,28 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Schema;
|
||||
|
||||
/**
|
||||
@@ -60,8 +69,15 @@ class UpgradeDatabase extends Command
|
||||
{
|
||||
$this->setTransactionIdentifier();
|
||||
$this->migrateRepetitions();
|
||||
$this->repairPiggyBanks();
|
||||
$this->updateAccountCurrencies();
|
||||
$this->updateJournalCurrencies();
|
||||
$this->info('Firefly III database is up to date.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate budget repetitions to new format.
|
||||
*/
|
||||
private function migrateRepetitions()
|
||||
{
|
||||
if (!Schema::hasTable('budget_limits')) {
|
||||
@@ -69,7 +85,9 @@ class UpgradeDatabase extends Command
|
||||
}
|
||||
// get all budget limits with end_date NULL
|
||||
$set = BudgetLimit::whereNull('end_date')->get();
|
||||
$this->line(sprintf('Found %d budget limit(s) to update', $set->count()));
|
||||
if ($set->count() > 0) {
|
||||
$this->line(sprintf('Found %d budget limit(s) to update', $set->count()));
|
||||
}
|
||||
/** @var BudgetLimit $budgetLimit */
|
||||
foreach ($set as $budgetLimit) {
|
||||
// get limit repetition (should be just one):
|
||||
@@ -84,6 +102,37 @@ class UpgradeDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure there are only transfers linked to piggy bank events.
|
||||
*/
|
||||
private function repairPiggyBanks()
|
||||
{
|
||||
// if table does not exist, return false
|
||||
if (!Schema::hasTable('piggy_bank_events')) {
|
||||
return;
|
||||
}
|
||||
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
|
||||
/** @var PiggyBankEvent $event */
|
||||
foreach ($set as $event) {
|
||||
|
||||
if (is_null($event->transaction_journal_id)) {
|
||||
continue;
|
||||
}
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->transactionJournal()->first();
|
||||
if (is_null($journal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = $journal->transactionType->type;
|
||||
if ($type !== TransactionType::TRANSFER) {
|
||||
$event->transaction_journal_id = null;
|
||||
$event->save();
|
||||
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird.
|
||||
*/
|
||||
@@ -112,6 +161,57 @@ class UpgradeDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateAccountCurrencies()
|
||||
{
|
||||
$accounts = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('account_types.type', [AccountType::DEFAULT, AccountType::ASSET])->get(['accounts.*']);
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
// get users preference, fall back to system pref.
|
||||
$defaultCurrencyCode = Preferences::getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
|
||||
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
|
||||
$accountCurrency = intval($account->getMeta('currency_id'));
|
||||
$openingBalance = $account->getOpeningBalance();
|
||||
$openingBalanceCurrency = intval($openingBalance->transaction_currency_id);
|
||||
|
||||
// both 0? set to default currency:
|
||||
if ($accountCurrency === 0 && $openingBalanceCurrency === 0) {
|
||||
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $defaultCurrency->id]);
|
||||
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
|
||||
continue;
|
||||
}
|
||||
|
||||
// opening balance 0, account not zero? just continue:
|
||||
if ($accountCurrency > 0 && $openingBalanceCurrency === 0) {
|
||||
continue;
|
||||
}
|
||||
// account is set to 0, opening balance is not?
|
||||
if ($accountCurrency === 0 && $openingBalanceCurrency > 0) {
|
||||
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $openingBalanceCurrency]);
|
||||
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
|
||||
continue;
|
||||
}
|
||||
|
||||
// both are equal, just continue:
|
||||
if ($accountCurrency === $openingBalanceCurrency) {
|
||||
continue;
|
||||
}
|
||||
// do not match:
|
||||
if ($accountCurrency !== $openingBalanceCurrency) {
|
||||
// update opening balance:
|
||||
$openingBalance->transaction_currency_id = $accountCurrency;
|
||||
$openingBalance->save();
|
||||
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -151,9 +251,87 @@ class UpgradeDatabase extends Command
|
||||
$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++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that withdrawals, deposits and transfers have
|
||||
* a currency setting matching their respective accounts
|
||||
*/
|
||||
private function updateJournalCurrencies()
|
||||
{
|
||||
$types = [
|
||||
TransactionType::WITHDRAWAL => '<',
|
||||
TransactionType::DEPOSIT => '>',
|
||||
];
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$notification = '%s #%d uses %s but should use %s. It has been updated. Please verify this in Firefly III.';
|
||||
$transfer = 'Transfer #%d has been updated to use the correct currencies. Please verify this in Firefly III.';
|
||||
|
||||
foreach ($types as $type => $operator) {
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')->leftJoin(
|
||||
'transactions', function (JoinClause $join) use ($operator) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', $operator, '0');
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
||||
->where('transaction_types.type', $type)
|
||||
->where('account_meta.name', 'currency_id')
|
||||
->where('transaction_journals.transaction_currency_id', '!=', DB::raw('account_meta.data'))
|
||||
->get(['transaction_journals.*', 'account_meta.data as expected_currency_id', 'transactions.amount as transaction_amount']);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($set as $journal) {
|
||||
$expectedCurrency = $repository->find(intval($journal->expected_currency_id));
|
||||
$line = sprintf($notification, $type, $journal->id, $journal->transactionCurrency->code, $expectedCurrency->code);
|
||||
|
||||
$journal->setMeta('foreign_amount', $journal->transaction_amount);
|
||||
$journal->setMeta('foreign_currency_id', $journal->transaction_currency_id);
|
||||
$journal->transaction_currency_id = $expectedCurrency->id;
|
||||
$journal->save();
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* For transfers it's slightly different. Both source and destination
|
||||
* must match the respective currency preference. So we must verify ALL
|
||||
* transactions.
|
||||
*/
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where('transaction_types.type', TransactionType::TRANSFER)
|
||||
->get(['transaction_journals.*']);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($set as $journal) {
|
||||
$updated = false;
|
||||
/** @var Transaction $sourceTransaction */
|
||||
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
$sourceCurrency = $repository->find(intval($sourceTransaction->account->getMeta('currency_id')));
|
||||
|
||||
if ($sourceCurrency->id !== $journal->transaction_currency_id) {
|
||||
$updated = true;
|
||||
$journal->transaction_currency_id = $sourceCurrency->id;
|
||||
$journal->save();
|
||||
}
|
||||
|
||||
// destination
|
||||
$destinationTransaction = $journal->transactions()->where('amount', '>', 0)->first();
|
||||
$destinationCurrency = $repository->find(intval($destinationTransaction->account->getMeta('currency_id')));
|
||||
|
||||
if ($destinationCurrency->id !== $journal->transaction_currency_id) {
|
||||
$updated = true;
|
||||
$journal->deleteMeta('foreign_amount');
|
||||
$journal->deleteMeta('foreign_currency_id');
|
||||
$journal->setMeta('foreign_amount', $destinationTransaction->amount);
|
||||
$journal->setMeta('foreign_currency_id', $destinationCurrency->id);
|
||||
}
|
||||
if ($updated) {
|
||||
$line = sprintf($transfer, $journal->id);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
@@ -93,6 +93,7 @@ class VerifyDatabase extends Command
|
||||
|
||||
// report on journals with the wrong types of accounts.
|
||||
$this->reportIncorrectJournals();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +132,7 @@ class VerifyDatabase extends Command
|
||||
/** @var Budget $entry */
|
||||
foreach ($set as $entry) {
|
||||
$line = sprintf(
|
||||
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
||||
'User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
||||
$entry->user_id, $entry->email, $entry->id, $entry->name
|
||||
);
|
||||
$this->line($line);
|
||||
@@ -277,7 +278,7 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
|
||||
$line = sprintf(
|
||||
'Notice: User #%d (%s) has %s #%d ("%s") which has no transactions.',
|
||||
'User #%d (%s) has %s #%d ("%s") which has no transactions.',
|
||||
$entry->user_id, $entry->email, $name, $entry->id, $objName
|
||||
);
|
||||
$this->line($line);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
@@ -41,7 +41,6 @@ class Kernel extends ConsoleKernel
|
||||
= [
|
||||
'Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables',
|
||||
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
|
||||
//'FireflyIII\Bootstrap\ConfigureLogging',
|
||||
'Illuminate\Foundation\Bootstrap\HandleExceptions',
|
||||
'Illuminate\Foundation\Bootstrap\RegisterFacades',
|
||||
'Illuminate\Foundation\Bootstrap\SetRequestForConsole',
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
/**
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use ErrorException;
|
||||
@@ -97,6 +98,7 @@ class Handler extends ExceptionHandler
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'code' => $exception->getCode(),
|
||||
'version' => config('firefly.version'),
|
||||
];
|
||||
|
||||
// create job that will mail.
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
/**
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Entry;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Basic;
|
||||
|
||||
@@ -81,6 +81,9 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
if (isset($set['fill'])) {
|
||||
$currentSet['fill'] = $set['fill'];
|
||||
}
|
||||
if (isset($set['currency_symbol'])) {
|
||||
$currentSet['currency_symbol'] = $set['currency_symbol'];
|
||||
}
|
||||
|
||||
$chartData['datasets'][] = $currentSet;
|
||||
}
|
||||
@@ -105,6 +108,10 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
],
|
||||
'labels' => [],
|
||||
];
|
||||
|
||||
// sort by value, keep keys.
|
||||
asort($data);
|
||||
|
||||
$index = 0;
|
||||
foreach ($data as $key => $value) {
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Basic;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Audit;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Audit;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Audit;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Budget;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Budget;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Budget;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Category;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Category;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Category;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Standard;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Standard;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Standard;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Tag;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Tag;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Tag;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
@@ -20,6 +20,7 @@ use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\Support\Events\BillScanner;
|
||||
use Log;
|
||||
@@ -45,6 +46,16 @@ class StoredJournalEventHandler
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
Log::debug(sprintf('Trying to connect journal %d to piggy bank %d.', $journal->id, $piggyBankId));
|
||||
|
||||
/*
|
||||
* Will only continue when journal is a transfer.
|
||||
*/
|
||||
Log::debug(sprintf('Journal transaction type is %s', $journal->transactionType->type));
|
||||
if ($journal->transactionType->type !== TransactionType::TRANSFER) {
|
||||
Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify existence of piggy bank:
|
||||
*/
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use Crypt;
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
@@ -42,7 +43,7 @@ interface AttachmentHelperInterface
|
||||
public function getMessages(): MessageBag;
|
||||
|
||||
/**
|
||||
* @param Model $model
|
||||
* @param Model $model
|
||||
*
|
||||
* @param null|array $files
|
||||
*
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Chart;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Chart;
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use FireflyIII\Models\Account as AccountModel;
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use FireflyIII\Models\Account as AccountModel;
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use FireflyIII\Models\Category as CategoryModel;
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers;
|
||||
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Help;
|
||||
|
||||
use Cache;
|
||||
@@ -43,12 +44,12 @@ class Help implements HelpInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language
|
||||
* @param string $route
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFromGithub(string $language, string $route): string
|
||||
public function getFromGithub(string $route, string $language): string
|
||||
{
|
||||
|
||||
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
|
||||
@@ -123,6 +124,7 @@ class Help implements HelpInterface
|
||||
if (strlen($content) > 0) {
|
||||
Log::debug(sprintf('Will store entry in cache: %s', $key));
|
||||
Cache::put($key, $content, 10080); // a week.
|
||||
|
||||
return;
|
||||
}
|
||||
Log::info(sprintf('Will not cache %s because content is empty.', $key));
|
||||
|
@@ -9,7 +9,8 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Help;
|
||||
|
||||
/**
|
||||
@@ -29,12 +30,12 @@ interface HelpInterface
|
||||
public function getFromCache(string $route, string $language): string;
|
||||
|
||||
/**
|
||||
* @param string $language
|
||||
* @param string $route
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFromGithub(string $language, string $route): string;
|
||||
public function getFromGithub(string $route, string $language): string;
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
|
199
app/Helpers/Report/PopupReport.php
Normal file
199
app/Helpers/Report/PopupReport.php
Normal file
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/**
|
||||
* PopupReport.php
|
||||
* Copyright (c) 2017 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\Helpers\Report;
|
||||
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class PopupReport
|
||||
*
|
||||
* @package FireflyIII\Helpers\Report
|
||||
*/
|
||||
class PopupReport implements PopupReportInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param $account
|
||||
* @param $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balanceDifference($account, $attributes): Collection
|
||||
{
|
||||
// row that displays difference
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector
|
||||
->setAccounts(new Collection([$account]))
|
||||
->setTypes([TransactionType::WITHDRAWAL])
|
||||
->setRange($attributes['startDate'], $attributes['endDate'])
|
||||
->withoutBudget();
|
||||
$journals = $collector->getJournals();
|
||||
|
||||
|
||||
return $journals->filter(
|
||||
function (Transaction $transaction) {
|
||||
$tags = $transaction->transactionJournal->tags()->where('tagMode', 'balancingAct')->count();
|
||||
if ($tags === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balanceForBudget(Budget $budget, Account $account, array $attributes): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setBudget($budget);
|
||||
$journals = $collector->getJournals();
|
||||
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balanceForNoBudget(Account $account, array $attributes): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector
|
||||
->setAccounts(new Collection([$account]))
|
||||
->setTypes([TransactionType::WITHDRAWAL])
|
||||
->setRange($attributes['startDate'], $attributes['endDate'])
|
||||
->withoutBudget();
|
||||
|
||||
return $collector->getJournals();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byBudget(Budget $budget, array $attributes): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
|
||||
$collector->setAccounts($attributes['accounts'])->setRange($attributes['startDate'], $attributes['endDate']);
|
||||
|
||||
if (is_null($budget->id)) {
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL])->withoutBudget();
|
||||
}
|
||||
if (!is_null($budget->id)) {
|
||||
$collector->setBudget($budget);
|
||||
}
|
||||
$journals = $collector->getJournals();
|
||||
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byCategory(Category $category, array $attributes): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($attributes['accounts'])->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->setRange($attributes['startDate'], $attributes['endDate'])
|
||||
->setCategory($category);
|
||||
$journals = $collector->getJournals();
|
||||
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byExpenses(Account $account, array $attributes): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])
|
||||
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]);
|
||||
$journals = $collector->getJournals();
|
||||
|
||||
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
|
||||
|
||||
// filter for transfers and withdrawals TO the given $account
|
||||
$journals = $journals->filter(
|
||||
function (Transaction $transaction) use ($report) {
|
||||
// get the destinations:
|
||||
$sources = $transaction->transactionJournal->sourceAccountList()->pluck('id')->toArray();
|
||||
|
||||
// do these intersect with the current list?
|
||||
return !empty(array_intersect($report, $sources));
|
||||
}
|
||||
);
|
||||
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byIncome(Account $account, array $attributes): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])
|
||||
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]);
|
||||
$journals = $collector->getJournals();
|
||||
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
|
||||
|
||||
// filter the set so the destinations outside of $attributes['accounts'] are not included.
|
||||
$journals = $journals->filter(
|
||||
function (Transaction $transaction) use ($report) {
|
||||
// get the destinations:
|
||||
$destinations = $transaction->destinationAccountList($transaction->transactionJournal)->pluck('id')->toArray();
|
||||
|
||||
// do these intersect with the current list?
|
||||
return !empty(array_intersect($report, $destinations));
|
||||
}
|
||||
);
|
||||
|
||||
return $journals;
|
||||
}
|
||||
}
|
83
app/Helpers/Report/PopupReportInterface.php
Normal file
83
app/Helpers/Report/PopupReportInterface.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* PopupReportInterface.php
|
||||
* Copyright (c) 2017 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\Helpers\Report;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface PopupReportInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Report
|
||||
*/
|
||||
interface PopupReportInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $account
|
||||
* @param $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balanceDifference($account, $attributes): Collection;
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balanceForBudget(Budget $budget, Account $account, array $attributes): Collection;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balanceForNoBudget(Account $account, array $attributes): Collection;
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byBudget(Budget $budget, array $attributes): Collection;
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byCategory(Category $category, array $attributes): Collection;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byExpenses(Account $account, array $attributes): Collection;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function byIncome(Account $account, array $attributes): Collection;
|
||||
}
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
@@ -22,9 +22,10 @@ use FireflyIII\Http\Requests\AccountFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -68,12 +69,13 @@ class AccountController extends Controller
|
||||
public function create(Request $request, string $what = 'asset')
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$currencies = ExpandedForm::makeSelectList($repository->get());
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$subTitle = trans('firefly.make_new_' . $what . '_account');
|
||||
$roles = [];
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$allCurrencies = $repository->get();
|
||||
$currencySelectList = ExpandedForm::makeSelectList($allCurrencies);
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$subTitle = trans('firefly.make_new_' . $what . '_account');
|
||||
$roles = [];
|
||||
foreach (config('firefly.accountRoles') as $role) {
|
||||
$roles[$role] = strval(trans('firefly.account_role_' . $role));
|
||||
}
|
||||
@@ -90,7 +92,7 @@ class AccountController extends Controller
|
||||
$request->session()->flash('gaEventCategory', 'accounts');
|
||||
$request->session()->flash('gaEventAction', 'create-' . $what);
|
||||
|
||||
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle', 'currencies', 'roles'));
|
||||
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle', 'currencySelectList', 'allCurrencies', 'roles'));
|
||||
|
||||
}
|
||||
|
||||
@@ -146,14 +148,14 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function edit(Request $request, Account $account)
|
||||
{
|
||||
|
||||
$what = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$currencies = ExpandedForm::makeSelectList($repository->get());
|
||||
$roles = [];
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$what = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$allCurrencies = $repository->get();
|
||||
$currencySelectList = ExpandedForm::makeSelectList($allCurrencies);
|
||||
$roles = [];
|
||||
foreach (config('firefly.accountRoles') as $role) {
|
||||
$roles[$role] = strval(trans('firefly.account_role_' . $role));
|
||||
}
|
||||
@@ -172,6 +174,7 @@ class AccountController extends Controller
|
||||
$openingBalanceAmount = $account->getOpeningBalanceAmount() === '0' ? '' : $openingBalanceAmount;
|
||||
$openingBalanceDate = $account->getOpeningBalanceDate();
|
||||
$openingBalanceDate = $openingBalanceDate->year === 1900 ? null : $openingBalanceDate->format('Y-m-d');
|
||||
$currency = $repository->find(intval($account->getMeta('currency_id')));
|
||||
|
||||
$preFilled = [
|
||||
'accountNumber' => $account->getMeta('accountNumber'),
|
||||
@@ -182,13 +185,18 @@ class AccountController extends Controller
|
||||
'openingBalanceDate' => $openingBalanceDate,
|
||||
'openingBalance' => $openingBalanceAmount,
|
||||
'virtualBalance' => $account->virtual_balance,
|
||||
'currency_id' => $account->getMeta('currency_id'),
|
||||
'currency_id' => $currency->id,
|
||||
|
||||
];
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
$request->session()->flash('gaEventCategory', 'accounts');
|
||||
$request->session()->flash('gaEventAction', 'edit-' . $what);
|
||||
|
||||
return view('accounts.edit', compact('currencies', 'account', 'subTitle', 'subTitleIcon', 'openingBalance', 'what', 'roles'));
|
||||
return view(
|
||||
'accounts.edit', compact(
|
||||
'allCurrencies', 'currencySelectList', 'account', 'currency', 'subTitle', 'subTitleIcon', 'openingBalance', 'what', 'roles'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,53 +237,62 @@ class AccountController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
* @param string $moment
|
||||
* @param Request $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param Account $account
|
||||
* @param string $moment
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||
*/
|
||||
public function show(Request $request, Account $account, string $moment = '')
|
||||
public function show(Request $request, JournalRepositoryInterface $repository, Account $account, string $moment = '')
|
||||
{
|
||||
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
||||
return $this->redirectToOriginalAccount($account);
|
||||
}
|
||||
$subTitle = $account->name;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$chartUri = route('chart.account.single', [$account->id]);
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$chartUri = route('chart.account.single', [$account->id]);
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
$currency = $currencyRepos->find(intval($account->getMeta('currency_id')));
|
||||
|
||||
// prep for "all" view.
|
||||
if ($moment === 'all') {
|
||||
$subTitle = $account->name . ' (' . strtolower(strval(trans('firefly.everything'))) . ')';
|
||||
$subTitle = trans('firefly.all_journals_for_account', ['name' => $account->name]);
|
||||
$chartUri = route('chart.account.all', [$account->id]);
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$end = new Carbon;
|
||||
}
|
||||
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && $moment !== 'all') {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$subTitle = $account->name . ' (' . strval(
|
||||
trans(
|
||||
'firefly.from_to_breadcrumb',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
)
|
||||
) . ')';
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
$chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d')]);
|
||||
$periods = $this->periodEntries($account);
|
||||
$periods = $this->getPeriodOverview($account);
|
||||
}
|
||||
|
||||
// prep for current period
|
||||
if (strlen($moment) === 0) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->periodEntries($account);
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
$periods = $this->getPeriodOverview($account);
|
||||
}
|
||||
|
||||
$accountType = $account->accountType->type;
|
||||
$count = 0;
|
||||
$loop = 0;
|
||||
// grab journals, but be prepared to jump a period back to get the right ones:
|
||||
@@ -289,7 +306,7 @@ class AccountController extends Controller
|
||||
$collector->setRange($start, $end);
|
||||
}
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('accounts/show/' . $account->id);
|
||||
$journals->setPath('accounts/show/' . $account->id . '/' . $moment);
|
||||
$count = $journals->getCollection()->count();
|
||||
if ($count === 0) {
|
||||
$start->subDay();
|
||||
@@ -299,8 +316,18 @@ class AccountController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ($moment != 'all' && $loop > 1) {
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
|
||||
return view('accounts.show', compact('account', 'accountType', 'periods', 'subTitleIcon', 'journals', 'subTitle', 'start', 'end', 'chartUri'));
|
||||
|
||||
return view(
|
||||
'accounts.show',
|
||||
compact('account', 'currency', 'moment', 'periods', 'subTitleIcon', 'journals', 'subTitle', 'start', 'end', 'chartUri')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +341,6 @@ class AccountController extends Controller
|
||||
{
|
||||
$data = $request->getAccountData();
|
||||
$account = $repository->store($data);
|
||||
|
||||
$request->session()->flash('success', strval(trans('firefly.stored_new_account', ['name' => $account->name])));
|
||||
Preferences::mark();
|
||||
|
||||
@@ -388,18 +414,15 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function periodEntries(Account $account): Collection
|
||||
private function getPeriodOverview(Account $account): Collection
|
||||
{
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
/** @var AccountTaskerInterface $tasker */
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
|
||||
$start = $repository->oldestJournalDate($account);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range);
|
||||
$entries = new Collection;
|
||||
$start = $repository->oldestJournalDate($account);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range);
|
||||
$entries = new Collection;
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties;
|
||||
@@ -412,20 +435,36 @@ class AccountController extends Controller
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// only include asset accounts when this account is an asset:
|
||||
$assets = new Collection;
|
||||
if (in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEFAULT])) {
|
||||
$assets = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
||||
}
|
||||
Log::debug('Going to get period expenses and incomes.');
|
||||
while ($end >= $start) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$spent = $tasker->amountOutInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$earned = $tasker->amountInInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push([$dateStr, $dateName, $spent, $earned, clone $end]);
|
||||
|
||||
// try a collector for income:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)
|
||||
->setTypes([TransactionType::DEPOSIT])
|
||||
->withOpposingAccount();
|
||||
$earned = strval($collector->getJournals()->sum('transaction_amount'));
|
||||
|
||||
// try a collector for expenses:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)
|
||||
->setTypes([TransactionType::WITHDRAWAL])
|
||||
->withOpposingAccount();
|
||||
$spent = strval($collector->getJournals()->sum('transaction_amount'));
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push(
|
||||
[
|
||||
'string' => $dateStr,
|
||||
'name' => $dateName,
|
||||
'spent' => $spent,
|
||||
'earned' => $earned,
|
||||
'date' => clone $end]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
|
||||
}
|
||||
@@ -453,7 +492,7 @@ class AccountController extends Controller
|
||||
$opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first();
|
||||
|
||||
if (is_null($opposingTransaction)) {
|
||||
throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.');
|
||||
throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return redirect(route('accounts.show', [$opposingTransaction->account_id]));
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
@@ -18,6 +18,7 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\UserFormRequest;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use View;
|
||||
@@ -124,34 +125,34 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserFormRequest $request
|
||||
* @param User $user
|
||||
* @param UserFormRequest $request
|
||||
* @param User $user
|
||||
*
|
||||
* @param UserRepositoryInterface $repository
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(UserFormRequest $request, User $user)
|
||||
public function update(UserFormRequest $request, User $user, UserRepositoryInterface $repository)
|
||||
{
|
||||
Log::debug('Actually here');
|
||||
$data = $request->getUserData();
|
||||
|
||||
// update password
|
||||
if (strlen($data['password']) > 0) {
|
||||
$user->password = bcrypt($data['password']);
|
||||
$user->save();
|
||||
$repository->changePassword($user, $data['password']);
|
||||
}
|
||||
|
||||
// change blocked status and code:
|
||||
$user->blocked = $data['blocked'];
|
||||
$user->blocked_code = $data['blocked_code'];
|
||||
$user->save();
|
||||
$repository->changeStatus($user, $data['blocked'], $data['blocked_code']);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.updated_user', ['email' => $user->email])));
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
// @codeCoverageIgnoreStart
|
||||
Session::put('users.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('admin.users.edit', [$user->id]))->withInput(['return_to_edit' => 1]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
@@ -176,10 +176,11 @@ class AttachmentController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('attachments.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('attachments.edit', [$attachment->id]))->withInput(['return_to_edit' => 1]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
|
@@ -8,11 +8,12 @@
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -40,25 +41,24 @@ class ForgotPasswordController extends Controller
|
||||
/**
|
||||
* Send a reset link to the given user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
*
|
||||
* @param UserRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository)
|
||||
{
|
||||
$this->validate($request, ['email' => 'required|email']);
|
||||
|
||||
// verify if the user is not a demo user. If so, we give him back an error.
|
||||
$user = User::where('email', $request->get('email'))->first();
|
||||
if (!is_null($user) && $user->hasRole('demo')) {
|
||||
return back()->withErrors(
|
||||
['email' => trans('firefly.cannot_reset_demo_user')]
|
||||
);
|
||||
|
||||
if (!is_null($user) && $repository->hasRole($user, 'demo')) {
|
||||
return back()->withErrors(['email' => trans('firefly.cannot_reset_demo_user')]);
|
||||
}
|
||||
|
||||
$response = $this->broker()->sendResetLink(
|
||||
$request->only('email')
|
||||
);
|
||||
$response = $this->broker()->sendResetLink($request->only('email'));
|
||||
|
||||
if ($response === Password::RESET_LINK_SENT) {
|
||||
return back()->with('status', trans($response));
|
||||
@@ -67,8 +67,6 @@ class ForgotPasswordController extends Controller
|
||||
// If an error was returned by the password broker, we will get this message
|
||||
// translated so we can notify a user of the problem. We'll redirect back
|
||||
// to where the users came from so they can attempt this process again.
|
||||
return back()->withErrors(
|
||||
['email' => trans($response)]
|
||||
);
|
||||
return back()->withErrors(['email' => trans($response)]); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
@@ -22,6 +22,8 @@ use Illuminate\Http\Request;
|
||||
use Lang;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class LoginController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
@@ -108,12 +110,16 @@ class LoginController extends Controller
|
||||
/**
|
||||
* Show the application login form.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
*
|
||||
* @param CookieJar $cookieJar
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showLoginForm(Request $request)
|
||||
public function showLoginForm(Request $request, CookieJar $cookieJar)
|
||||
{
|
||||
// forget 2fa cookie:
|
||||
$cookie = $cookieJar->forever('twoFactorAuthenticated', 'false');
|
||||
// is allowed to?
|
||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||
$userCount = User::count();
|
||||
@@ -125,7 +131,7 @@ class LoginController extends Controller
|
||||
$email = $request->old('email');
|
||||
$remember = $request->old('remember');
|
||||
|
||||
return view('auth.login', compact('allowRegistration', 'email', 'remember'));
|
||||
return view('auth.login', compact('allowRegistration', 'email', 'remember'))->withCookie($cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
@@ -22,6 +22,8 @@ use Illuminate\Support\Facades\Password;
|
||||
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class PasswordController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
@@ -24,6 +24,8 @@ use Session;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class RegisterController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
@@ -16,6 +16,8 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class ResetPasswordController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
@@ -41,11 +41,12 @@ class TwoFactorController extends Controller
|
||||
$user = auth()->user();
|
||||
|
||||
// to make sure the validator in the next step gets the secret, we push it in session
|
||||
$secret = Preferences::get('twoFactorAuthSecret', null)->data;
|
||||
$title = strval(trans('firefly.two_factor_title'));
|
||||
$secretPreference = Preferences::get('twoFactorAuthSecret', null);
|
||||
$secret = is_null($secretPreference) ? null : $secretPreference->data;
|
||||
$title = strval(trans('firefly.two_factor_title'));
|
||||
|
||||
// make sure the user has two factor configured:
|
||||
$has2FA = Preferences::get('twoFactorAuthEnabled', null)->data;
|
||||
$has2FA = Preferences::get('twoFactorAuthEnabled', false)->data;
|
||||
if (is_null($has2FA) || $has2FA === false) {
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
@@ -240,10 +240,11 @@ class BillController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('bills.create.fromStore', true);
|
||||
|
||||
return redirect(route('bills.create'))->withInput();
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
@@ -267,10 +268,11 @@ class BillController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('bills.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return redirect($this->getPreviousUri('bills.edit.uri'));
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
@@ -22,11 +22,15 @@ use FireflyIII\Http\Requests\BudgetIncomeRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use View;
|
||||
@@ -187,31 +191,83 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param string $moment
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function noBudget(Request $request)
|
||||
public function noBudget(Request $request, JournalRepositoryInterface $repository, string $moment = '')
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Carbon::now()->endOfMonth());
|
||||
// default values:
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
|
||||
// prep for "all" view.
|
||||
if ($moment === 'all') {
|
||||
$subTitle = trans('firefly.all_journals_without_budget');
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$end = new Carbon;
|
||||
}
|
||||
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && $moment !== 'all') {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
$periods = $this->getPeriodOverview();
|
||||
}
|
||||
|
||||
// prep for current period
|
||||
if (strlen($moment) === 0) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->getPeriodOverview();
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
|
||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
|
||||
// collector
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutBudget();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('/budgets/list/noBudget');
|
||||
$count = 0;
|
||||
$loop = 0;
|
||||
// grab journals, but be prepared to jump a period back to get the right ones:
|
||||
Log::info('Now at no-budget loop start.');
|
||||
while ($count === 0 && $loop < 3) {
|
||||
$loop++;
|
||||
Log::info('Count is zero, search for journals.');
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setLimit($pageSize)->setPage($page)
|
||||
->withoutBudget()->withOpposingAccount();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('/budgets/list/no-budget');
|
||||
$count = $journals->getCollection()->count();
|
||||
if ($count === 0) {
|
||||
$start->subDay();
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
}
|
||||
}
|
||||
|
||||
return view('budgets.no-budget', compact('journals', 'subTitle'));
|
||||
if ($moment != 'all' && $loop > 1) {
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
|
||||
return view('budgets.no-budget', compact('journals', 'subTitle', 'moment', 'periods', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,7 +311,7 @@ class BudgetController extends Controller
|
||||
$journals->setPath('/budgets/show/' . $budget->id);
|
||||
|
||||
|
||||
$subTitle = e($budget->name);
|
||||
$subTitle = trans('firefly.all_journals_for_budget', ['name' => $budget->name]);
|
||||
|
||||
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
|
||||
}
|
||||
@@ -315,10 +371,11 @@ class BudgetController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('budgets.create.fromStore', true);
|
||||
|
||||
return redirect(route('budgets.create'))->withInput();
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return redirect($this->getPreviousUri('budgets.create.uri'));
|
||||
@@ -339,10 +396,11 @@ class BudgetController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('budgets.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return redirect($this->getPreviousUri('budgets.edit.uri'));
|
||||
@@ -405,7 +463,6 @@ class BudgetController extends Controller
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
@@ -442,4 +499,57 @@ class BudgetController extends Controller
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getPeriodOverview(): Collection
|
||||
{
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range);
|
||||
$entries = new Collection;
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('no-budget-period-entries');
|
||||
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
Log::debug('Going to get period expenses and incomes.');
|
||||
while ($end >= $start) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
|
||||
// count journals without budget in this period:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutBudget()->withOpposingAccount()->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$set = $collector->getJournals();
|
||||
$sum = $set->sum('transaction_amount');
|
||||
$journals = $set->count();
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push(
|
||||
[
|
||||
'string' => $dateStr,
|
||||
'name' => $dateName,
|
||||
'count' => $journals,
|
||||
'sum' => $sum,
|
||||
'date' => clone $end,
|
||||
]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
@@ -18,13 +18,17 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Requests\CategoryFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Steam;
|
||||
use View;
|
||||
|
||||
/**
|
||||
@@ -150,118 +154,170 @@ class CategoryController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return View
|
||||
*/
|
||||
public function noCategory()
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Carbon::now()->startOfMonth());
|
||||
|
||||
// new collector:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end)->withoutCategory();//->groupJournals();
|
||||
$journals = $collector->getJournals();
|
||||
$subTitle = trans(
|
||||
'firefly.without_category_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
|
||||
return view('categories.no-category', compact('journals', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param JournalCollectorInterface $collector
|
||||
* @param Category $category
|
||||
* @param Request $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param string $moment
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function show(Request $request, JournalCollectorInterface $collector, Category $category)
|
||||
public function noCategory(Request $request, JournalRepositoryInterface $repository, string $moment = '')
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$hideCategory = true; // used in list.
|
||||
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$subTitle = $category->name;
|
||||
$subTitleIcon = 'fa-bar-chart';
|
||||
$entries = $this->getGroupedEntries($category);
|
||||
$method = 'default';
|
||||
// default values:
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
|
||||
// get journals
|
||||
$collector->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category)->withBudgetInformation();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('categories/show/' . $category->id);
|
||||
// prep for "all" view.
|
||||
if ($moment === 'all') {
|
||||
$subTitle = trans('firefly.all_journals_without_category');
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$end = new Carbon;
|
||||
}
|
||||
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && $moment !== 'all') {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
'firefly.without_category_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
$periods = $this->getNoCategoryPeriodOverview();
|
||||
}
|
||||
|
||||
return view('categories.show', compact('category', 'method', 'journals', 'entries', 'hideCategory', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||
// prep for current period
|
||||
if (strlen($moment) === 0) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->getNoCategoryPeriodOverview();
|
||||
$subTitle = trans(
|
||||
'firefly.without_category_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
|
||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
|
||||
$count = 0;
|
||||
$loop = 0;
|
||||
// grab journals, but be prepared to jump a period back to get the right ones:
|
||||
Log::info('Now at no-cat loop start.');
|
||||
while ($count === 0 && $loop < 3) {
|
||||
$loop++;
|
||||
Log::info('Count is zero, search for journals.');
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutCategory()->withOpposingAccount();
|
||||
$collector->disableInternalFilter();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('/categories/list/no-category');
|
||||
$count = $journals->getCollection()->count();
|
||||
if ($count === 0) {
|
||||
$start->subDay();
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
}
|
||||
}
|
||||
|
||||
if ($moment != 'all' && $loop > 1) {
|
||||
$subTitle = trans(
|
||||
'firefly.without_category_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
|
||||
return view('categories.no-category', compact('journals', 'subTitle', 'moment', 'periods', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param Category $category
|
||||
* @param string $moment
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function showAll(Request $request, CategoryRepositoryInterface $repository, Category $category)
|
||||
public function show(Request $request, CategoryRepositoryInterface $repository, Category $category, string $moment = '')
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = $repository->firstUseDate($category);
|
||||
if ($start->year == 1900) {
|
||||
$start = new Carbon;
|
||||
}
|
||||
$end = Navigation::endOfPeriod(new Carbon, $range);
|
||||
// default values:
|
||||
$subTitle = $category->name;
|
||||
$subTitleIcon = 'fa-bar-chart';
|
||||
$hideCategory = true; // used in list.
|
||||
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$method = 'all';
|
||||
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->setCategory($category)->withBudgetInformation();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('categories/show/' . $category->id . '/all');
|
||||
|
||||
return view('categories.show', compact('category', 'method', 'journals', 'hideCategory', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Category $category
|
||||
* @param string $date
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function showByDate(Request $request, Category $category, string $date)
|
||||
{
|
||||
$carbon = new Carbon($date);
|
||||
$count = 0;
|
||||
$loop = 0;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($carbon, $range);
|
||||
$end = Navigation::endOfPeriod($carbon, $range);
|
||||
$subTitle = $category->name;
|
||||
$subTitleIcon = 'fa-bar-chart';
|
||||
$hideCategory = true; // used in list.
|
||||
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$entries = $this->getGroupedEntries($category);
|
||||
$method = 'date';
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category)->withBudgetInformation();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('categories/show/' . $category->id . '/' . $date);
|
||||
|
||||
return view('categories.show', compact('category', 'method', 'entries', 'journals', 'hideCategory', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||
// prep for "all" view.
|
||||
if ($moment === 'all') {
|
||||
$subTitle = trans('firefly.all_journals_for_category', ['name' => $category->name]);
|
||||
$start = $repository->firstUseDate($category);
|
||||
$end = new Carbon;
|
||||
}
|
||||
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && $moment !== 'all') {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_category',
|
||||
['name' => $category->name,
|
||||
'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
$periods = $this->getPeriodOverview($category);
|
||||
}
|
||||
|
||||
// prep for current period
|
||||
if (strlen($moment) === 0) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->getPeriodOverview($category);
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_category',
|
||||
['name' => $category->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
// grab journals, but be prepared to jump a period back to get the right ones:
|
||||
Log::info('Now at category loop start.');
|
||||
while ($count === 0 && $loop < 3) {
|
||||
$loop++;
|
||||
Log::info('Count is zero, search for journals.');
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withOpposingAccount()
|
||||
->setCategory($category)->withBudgetInformation()->withCategoryInformation()->disableInternalFilter();
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('categories/show/' . $category->id);
|
||||
$count = $journals->getCollection()->count();
|
||||
if ($count === 0) {
|
||||
$start->subDay();
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
}
|
||||
}
|
||||
|
||||
if ($moment != 'all' && $loop > 1) {
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_category',
|
||||
['name' => $category->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
}
|
||||
|
||||
return view('categories.show', compact('category', 'moment', 'journals', 'periods', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param CategoryFormRequest $request
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
@@ -277,9 +333,11 @@ class CategoryController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('create_another')) === 1) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('categories.create.fromStore', true);
|
||||
|
||||
return redirect(route('categories.create'))->withInput();
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return redirect(route('categories.index'));
|
||||
@@ -302,20 +360,97 @@ class CategoryController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
if (intval($request->get('return_to_edit')) === 1) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('categories.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('categories.edit', [$category->id]));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return redirect($this->getPreviousUri('categories.edit.uri'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getNoCategoryPeriodOverview(): Collection
|
||||
{
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range);
|
||||
$entries = new Collection;
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('no-budget-period-entries');
|
||||
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Going to get period expenses and incomes between %s and %s.', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
while ($end >= $start) {
|
||||
Log::debug('Loop!');
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
|
||||
// count journals without budget in this period:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutCategory()->withOpposingAccount()->disableInternalFilter();
|
||||
$count = $collector->getJournals()->count();
|
||||
|
||||
// amount transferred
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutCategory()
|
||||
->withOpposingAccount()->setTypes([TransactionType::TRANSFER])->disableInternalFilter();
|
||||
$transferred = Steam::positive($collector->getJournals()->sum('transaction_amount'));
|
||||
|
||||
// amount spent
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutCategory()->withOpposingAccount()->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$spent = $collector->getJournals()->sum('transaction_amount');
|
||||
|
||||
// amount earned
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutCategory()->withOpposingAccount()->setTypes([TransactionType::DEPOSIT]);
|
||||
$earned = $collector->getJournals()->sum('transaction_amount');
|
||||
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push(
|
||||
[
|
||||
'string' => $dateStr,
|
||||
'name' => $dateName,
|
||||
'count' => $count,
|
||||
'spent' => $spent,
|
||||
'earned' => $earned,
|
||||
'transferred' => $transferred,
|
||||
'date' => clone $end,
|
||||
]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
}
|
||||
Log::debug('End of loops');
|
||||
$cache->store($entries);
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getGroupedEntries(Category $category): Collection
|
||||
private function getPeriodOverview(Category $category): Collection
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
@@ -348,7 +483,25 @@ class CategoryController extends Controller
|
||||
$earned = $repository->earnedInPeriod(new Collection([$category]), $accounts, $end, $currentEnd);
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push([$dateStr, $dateName, $spent, $earned, clone $end]);
|
||||
|
||||
// amount transferred
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->setCategory($category)
|
||||
->withOpposingAccount()->setTypes([TransactionType::TRANSFER])->disableInternalFilter();
|
||||
$transferred = Steam::positive($collector->getJournals()->sum('transaction_amount'));
|
||||
|
||||
$entries->push(
|
||||
[
|
||||
'string' => $dateStr,
|
||||
'name' => $dateName,
|
||||
'spent' => $spent,
|
||||
'earned' => $earned,
|
||||
'sum' => bcadd($earned, $spent),
|
||||
'transferred' => $transferred,
|
||||
'date' => clone $end,
|
||||
]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
@@ -26,6 +26,7 @@ use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@@ -61,15 +62,12 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function all(Account $account)
|
||||
{
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('chart.account.all');
|
||||
$cache->addProperty($account->id);
|
||||
if ($cache->has()) {
|
||||
Log::debug('Return chart.account.all from cache.');
|
||||
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
Log::debug('Regenerate chart.account.all from scratch.');
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
@@ -338,19 +336,13 @@ class AccountController extends Controller
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $date
|
||||
* @param Carbon $start
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function period(Account $account, string $date)
|
||||
public function period(Account $account, Carbon $start)
|
||||
{
|
||||
try {
|
||||
$start = new Carbon($date);
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
throw new FireflyException('"' . e($date) . '" does not seem to be a valid date. Should be in the format YYYY-MM-DD');
|
||||
}
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$cache = new CacheProperties();
|
||||
@@ -500,17 +492,20 @@ class AccountController extends Controller
|
||||
$cache->addProperty('chart.account.account-balance-chart');
|
||||
$cache->addProperty($accounts);
|
||||
if ($cache->has()) {
|
||||
Log::debug('Return chart.account.account-balance-chart from cache.');
|
||||
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
Log::debug('Regenerate chart.account.account-balance-chart from scratch.');
|
||||
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
$chartData = [];
|
||||
foreach ($accounts as $account) {
|
||||
$currency = $repository->find(intval($account->getMeta('currency_id')));
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
'entries' => [],
|
||||
'label' => $account->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'entries' => [],
|
||||
];
|
||||
$currentStart = clone $start;
|
||||
$range = Steam::balanceInRange($account, $start, clone $end);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user