mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-22 05:09:43 +00:00
Compare commits
284 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7edd1bff40 | ||
|
3bfcb1f3ab | ||
|
7b6c63e6a8 | ||
|
5500e5b0aa | ||
|
e4d249e73c | ||
|
091f6e918b | ||
|
5d9b68c3e7 | ||
|
12a6a61100 | ||
|
7ce3b8d4ef | ||
|
3d9b855849 | ||
|
2346d2ec05 | ||
|
a4c081c8a5 | ||
|
316980efbd | ||
|
a05bc0eed0 | ||
|
4d1c271da6 | ||
|
0dd7ecbfbe | ||
|
0dc188b083 | ||
|
6a553f77f3 | ||
|
a74cef439b | ||
|
9a3cd27700 | ||
|
801c7c0ab6 | ||
|
a95a4e783a | ||
|
af1ee9db93 | ||
|
fcdb6fd2a7 | ||
|
97c0fb389d | ||
|
a9c3992331 | ||
|
a38e057fa7 | ||
|
f83aaf77f1 | ||
|
d92768ecbf | ||
|
b9308cd74a | ||
|
78b577bc9d | ||
|
7d247897ed | ||
|
5dcbdec491 | ||
|
9bf980431e | ||
|
da60bfbcff | ||
|
92553cbc7e | ||
|
8e48e53f17 | ||
|
2f9a4bb79a | ||
|
ac968dd6cd | ||
|
6e4f2c0c8a | ||
|
d662c18ed7 | ||
|
e4ea234707 | ||
|
0b526c0168 | ||
|
2acde5c72a | ||
|
ec8cf2c459 | ||
|
3598780d54 | ||
|
35dd8ac6e6 | ||
|
5ff7c7ffab | ||
|
399db47826 | ||
|
148956a60d | ||
|
3670053a58 | ||
|
e8e2b9704f | ||
|
fcdeebcc06 | ||
|
586ed82e88 | ||
|
cc400d1e2e | ||
|
6edbfb27aa | ||
|
8fc9251b93 | ||
|
10af888a97 | ||
|
89f2328846 | ||
|
48e8cd20b4 | ||
|
394ef23eda | ||
|
62aa1eb487 | ||
|
1500018ccc | ||
|
23fad62d46 | ||
|
3cbf00734f | ||
|
1dc17dd59d | ||
|
f8935c92ea | ||
|
de6f838413 | ||
|
e8a095e543 | ||
|
717c1d080e | ||
|
0ae9afd325 | ||
|
d1b56c2afa | ||
|
8ef7c5ac33 | ||
|
7180a40cd8 | ||
|
71804af624 | ||
|
85dc7f3643 | ||
|
a866d13b75 | ||
|
fcb5e4eabc | ||
|
ade1cf9c19 | ||
|
0f1ec7d003 | ||
|
7e038afece | ||
|
9bb8e182fa | ||
|
e94ae126fd | ||
|
5bb8c6a366 | ||
|
30844df5d4 | ||
|
63e4a410a7 | ||
|
ee9a5d91e2 | ||
|
171ab8a4c3 | ||
|
96740aaac4 | ||
|
2017720096 | ||
|
b77ea6d316 | ||
|
f5adb4047f | ||
|
b082858866 | ||
|
a8a014189d | ||
|
39ea9e85a7 | ||
|
a4d2ed74fc | ||
|
90f2e27f1f | ||
|
a3359ba47a | ||
|
1d2d3523d6 | ||
|
3f40751a1a | ||
|
b5b55e862c | ||
|
c64771b76b | ||
|
ea7ee7ee9a | ||
|
a1f797c4d1 | ||
|
d0c92a2244 | ||
|
6e90c033b1 | ||
|
24f62b8fce | ||
|
d43936155c | ||
|
39dab4fdd9 | ||
|
c0fdf44ad2 | ||
|
4d91f7d23a | ||
|
49af6522a8 | ||
|
3c5f9487a8 | ||
|
f5cb87f5c3 | ||
|
cf543613c9 | ||
|
5c239c91db | ||
|
9920504232 | ||
|
5540697dbd | ||
|
b355c18e0c | ||
|
1e90485c5f | ||
|
dc784c53b5 | ||
|
5a47391a64 | ||
|
8a106bd16a | ||
|
a31ac79173 | ||
|
0d0a604254 | ||
|
724d25f2c2 | ||
|
8ed22d452d | ||
|
d7fef45a56 | ||
|
dc22802dec | ||
|
ce5af7b1d9 | ||
|
0a147e5c9c | ||
|
7d21255f7f | ||
|
13f952f182 | ||
|
b494be228b | ||
|
0fdaac53d0 | ||
|
e1b3a08878 | ||
|
dc893588b0 | ||
|
b9fcc443ec | ||
|
d8586c8043 | ||
|
4252a3e53b | ||
|
dbb5cdb9cf | ||
|
9bdfecbfdc | ||
|
3ec8a8c375 | ||
|
f85e4a24e5 | ||
|
0dda87c78e | ||
|
2fc09ff9d7 | ||
|
e4e0e21293 | ||
|
15089f0d7e | ||
|
7232c1d7bb | ||
|
9a53d8c21c | ||
|
0d198193db | ||
|
45bc23b8af | ||
|
3323c31765 | ||
|
bb7c26b77c | ||
|
9101d6a2c0 | ||
|
ad2b254be0 | ||
|
abc4f856ce | ||
|
b3b66a8f92 | ||
|
2f7cf9b916 | ||
|
b822e0c6e7 | ||
|
6fef9ee72b | ||
|
ab6dd0a1ec | ||
|
9deef5ac92 | ||
|
577187babe | ||
|
577290e813 | ||
|
f3b9798216 | ||
|
4dcaa96d16 | ||
|
0dcbf451d6 | ||
|
e87f6ca40e | ||
|
1f34e33d8c | ||
|
258e87e127 | ||
|
3ec8efcfc1 | ||
|
70ea227bd0 | ||
|
27c832ed58 | ||
|
a31b4ccf01 | ||
|
d221ea68d0 | ||
|
dc9fe58536 | ||
|
f871e29bdb | ||
|
1357352276 | ||
|
e169754693 | ||
|
1cfe4f40ba | ||
|
5545d1c1ba | ||
|
e5f7228fa9 | ||
|
11385494eb | ||
|
ae328de469 | ||
|
0574a706c8 | ||
|
70bb85a75b | ||
|
8cd901b57b | ||
|
8b9818c48e | ||
|
a95099fa46 | ||
|
221e4b7fc0 | ||
|
6cff3eb61e | ||
|
e4fd97ae77 | ||
|
5ca9099654 | ||
|
6e33e26ddf | ||
|
04461a4ab8 | ||
|
a4b9bbff54 | ||
|
4ad4252a77 | ||
|
aac0c9ab98 | ||
|
c123e1044a | ||
|
d25d0454fc | ||
|
f38984398d | ||
|
a07799cfa4 | ||
|
7c52f297ee | ||
|
50a3279b30 | ||
|
0ea14eb987 | ||
|
cf1b98e569 | ||
|
63fb435002 | ||
|
2f8263f53a | ||
|
fb649779d6 | ||
|
bb58f605f7 | ||
|
fccdf56c5d | ||
|
bd53410c71 | ||
|
7d63f124c4 | ||
|
9ffc5d857c | ||
|
2f93784acd | ||
|
d00fbe4eb3 | ||
|
51d9f041ae | ||
|
b872ab8b86 | ||
|
3d25fd79ca | ||
|
3aad78e6ef | ||
|
7d5bb72b0c | ||
|
46e5aae8bb | ||
|
b9e2ee7af3 | ||
|
c1a2892788 | ||
|
2078183e0d | ||
|
fab1d53714 | ||
|
3fe831c7d8 | ||
|
6958f71cfd | ||
|
a7351f348d | ||
|
5379e03447 | ||
|
539058e32d | ||
|
11b6b5a63c | ||
|
1155096226 | ||
|
2920dd356e | ||
|
9c3dac8170 | ||
|
49f9909b15 | ||
|
e4fef6dfc3 | ||
|
2da087401e | ||
|
629baf9de5 | ||
|
29a930dae5 | ||
|
d920537dd2 | ||
|
106b04a5da | ||
|
176752e219 | ||
|
8d19f60091 | ||
|
e937aa2f74 | ||
|
c3ccc4ccdf | ||
|
6c5cd705c0 | ||
|
ce003f217b | ||
|
8c7ef49eb6 | ||
|
29af4bd1b9 | ||
|
2ce5142b06 | ||
|
f3a8a25872 | ||
|
598e97d028 | ||
|
fa110279de | ||
|
8fdeaf73cc | ||
|
a7ffdf062a | ||
|
3bad92dd6d | ||
|
2e88024bca | ||
|
ca2301959c | ||
|
3285fae7f0 | ||
|
312079657b | ||
|
18c183afd6 | ||
|
f424d9cf20 | ||
|
5c3da9fd9e | ||
|
1f321fadd4 | ||
|
65f5d27b12 | ||
|
cdb591de7f | ||
|
a0ea3882e1 | ||
|
a9444ac702 | ||
|
d0c6afc3a9 | ||
|
e7a0a5937c | ||
|
08992b5298 | ||
|
6490a4240d | ||
|
43a7544dd7 | ||
|
0fe70dae17 | ||
|
7079e76886 | ||
|
0ec021c375 | ||
|
ff3396e286 | ||
|
78912903ce | ||
|
4c015e2d12 | ||
|
172634a55a | ||
|
58ca7d551a | ||
|
fd8ed4c9aa |
21
.env.example
21
.env.example
@@ -1,15 +1,19 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_FORCE_SSL=false
|
||||
APP_FORCE_ROOT=
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
LOG_LEVEL=warning
|
||||
APP_LOG_LEVEL=warning
|
||||
APP_URL=http://localhost
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
@@ -18,17 +22,14 @@ COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
COOKIE_SECURE=false
|
||||
|
||||
DEFAULT_CURRENCY=EUR
|
||||
DEFAULT_LANGUAGE=en_US
|
||||
|
||||
REDIS_HOST=localhost
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_FROM=enter_your_email_here
|
||||
MAIL_FROM=changeme@example.com
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
@@ -37,8 +38,10 @@ SEND_REGISTRATION_MAIL=true
|
||||
MUST_CONFIRM_ACCOUNT=false
|
||||
|
||||
SHOW_INCOMPLETE_TRANSLATIONS=false
|
||||
SHOW_DEMO_WARNING=false
|
||||
|
||||
ANALYTICS_ID=
|
||||
RUNCLEANUP=true
|
||||
SITE_OWNER=mail@example.com
|
||||
|
||||
PUSHER_KEY=
|
||||
PUSHER_SECRET=
|
||||
PUSHER_APP_ID=
|
||||
|
38
.env.testing
38
.env.testing
@@ -1,38 +0,0 @@
|
||||
APP_ENV=testing
|
||||
APP_DEBUG=true
|
||||
APP_FORCE_SSL=false
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
CACHE_DRIVER=array
|
||||
SESSION_DRIVER=array
|
||||
QUEUE_DRIVER=array
|
||||
|
||||
DEFAULT_CURRENCY=EUR
|
||||
DEFAULT_LANGUAGE=en_US
|
||||
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=log
|
||||
MAIL_HOST=mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_FROM=your_address_here@example.com
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
SHOW_INCOMPLETE_TRANSLATIONS=false
|
||||
|
||||
ANALYTICS_ID=abcde
|
||||
RUNCLEANUP=false
|
||||
SITE_OWNER=your_address_here@example.com
|
||||
|
||||
BLOCKED_DOMAINS=
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,3 +1,3 @@
|
||||
* text=auto
|
||||
*.css linguist-vendored
|
||||
*.less linguist-vendored
|
||||
*.scss linguist-vendored
|
||||
|
7
.gitignore
vendored
Normal file → Executable file
7
.gitignore
vendored
Normal file → Executable file
@@ -1,8 +1,13 @@
|
||||
/vendor
|
||||
/node_modules
|
||||
/public/storage
|
||||
/vendor
|
||||
/.idea
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
.env
|
||||
_development
|
||||
.env.local
|
||||
result.html
|
||||
test-import.sh
|
||||
test-import-report.txt
|
||||
public/google*.html
|
||||
|
@@ -5,3 +5,4 @@ filter:
|
||||
excluded_paths:
|
||||
- app/Support/Migration/*
|
||||
- app/database/migrations/*
|
||||
- database/migrations/*
|
||||
|
139
CHANGELOG.md
139
CHANGELOG.md
@@ -2,8 +2,132 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
- No unreleased changes yet.
|
||||
## [4.1] - 2016-10-22
|
||||
### Added
|
||||
- Option to show deposit accounts on the front page.
|
||||
- Script to upgrade split transactions
|
||||
- Can now save notes on piggy banks.
|
||||
- Extend user admin options.
|
||||
- Run import jobs from the command line
|
||||
|
||||
|
||||
### Changed
|
||||
- New preferences screen layout.
|
||||
|
||||
### Deprecated
|
||||
- ``firefly:import`` is now ``firefly:start-import``
|
||||
|
||||
### Removed
|
||||
- Lots of old code
|
||||
|
||||
### Fixed
|
||||
- #357, where non utf-8 files would break Firefly.
|
||||
- Tab delimiter is not properly loaded from import configuration (@roberthorlings)
|
||||
- System response to yearly bills
|
||||
|
||||
## [4.0.2] - 2016-10-14
|
||||
### Added
|
||||
- Added ``intl`` dependency to composer file to ease installation (thanks @telyn)
|
||||
- Added support for Croatian.
|
||||
|
||||
### Changed
|
||||
- Updated all copyright notices to refer to the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
- Fixed #344
|
||||
- Fixed #346, thanks to @SanderKleykens
|
||||
- #351
|
||||
- Did some internal remodelling.
|
||||
|
||||
### Fixed
|
||||
- PostgreSQL compatibility thanks to @SanderKleykens
|
||||
- @RobertHorlings fixed a bug in the ABN Amro import specific.
|
||||
|
||||
|
||||
## [4.0.1] - 2016-10-04
|
||||
### Added
|
||||
- New ING import specific by @tomwerf
|
||||
- New Presidents Choice specific to fix #307
|
||||
- Added some trimming (#335)
|
||||
|
||||
### Changed
|
||||
- Initial release.
|
||||
|
||||
### Deprecated
|
||||
- Initial release.
|
||||
|
||||
### Removed
|
||||
- Initial release.
|
||||
|
||||
### Fixed
|
||||
- Fixed a bug where incoming transactions would not be properly filtered in several reports.
|
||||
- #334 by @cyberkov
|
||||
- #337
|
||||
- #336
|
||||
- #338 found by @roberthorlings
|
||||
|
||||
### Security
|
||||
- Initial release.
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.0.0] - 2015-09-26
|
||||
### Added
|
||||
- Upgraded to Laravel 5.3, most other libraries upgraded as well.
|
||||
- Added GBP as currency, thanks to @Mortalife
|
||||
|
||||
### Changed
|
||||
- Jump to version 4.0.0.
|
||||
- Firefly III is now subject to a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/) license. Previous versions of this software are still MIT licensed.
|
||||
|
||||
### Fixed
|
||||
- Support for specific decimal places, thanks to @Mortalife
|
||||
- Various CSS fixes
|
||||
- Various bugs, thanks to @fuf, @sandermulders and @vissert
|
||||
- Various queries optimized for MySQL 5.7
|
||||
|
||||
## [3.10.4] - 2015-09-14
|
||||
### Fixed
|
||||
- Migration fix by @sandermulders
|
||||
- Tricky import bug fix thanks to @vissert
|
||||
- Currency preference will be correctly pulled from user settings, thanks to @fuf
|
||||
- Simplified code for upgrade instructions.
|
||||
|
||||
|
||||
## [3.10.3] - 2016-08-29
|
||||
### Added
|
||||
- More fields for mass-edit, thanks to @Vissert (#282)
|
||||
- First start of German translation
|
||||
|
||||
### Changed
|
||||
- More optional fields for transactions and the ability to filter them.
|
||||
|
||||
### Removed
|
||||
- Preference for budget maximum.
|
||||
|
||||
### Fixed
|
||||
- A bug in the translation routine broke the import.
|
||||
- It was possible to destroy your Firefly installation by removing all currencies. Thanks @mondjef
|
||||
- Translation bugs.
|
||||
- Import bug.
|
||||
|
||||
### Security
|
||||
- Firefly will not accept registrations beyond the first one, by default.
|
||||
|
||||
|
||||
## [3.10.2] - 2016-08-29
|
||||
### Added
|
||||
- New Chinese translations. Set Firefly III to show incomplete translations to follow the progress. Want to translate Firefly III in Chinese, or in any other language? Then check out [the Crowdin project](https://crowdin.com/project/firefly-iii).
|
||||
- Added more admin pages. They do nothing yet.
|
||||
|
||||
### Changed
|
||||
- Import routine will now also apply user rules.
|
||||
- Various code cleanup.
|
||||
- Some small HTML changes.
|
||||
|
||||
### Fixed
|
||||
- Bug in the mass edit routines.
|
||||
- Firefly III over a proxy will now work (see [issue #290](https://github.com/JC5/firefly-iii/issues/290)), thanks @dfiel for reporting.
|
||||
- Sneaky bug in the import routine, fixed by @Bonno
|
||||
|
||||
## [3.10.1] - 2016-08-25
|
||||
### Added
|
||||
@@ -38,13 +162,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- The date picker now supports more ranges and periods.
|
||||
- Rewrote all migrations. #272
|
||||
|
||||
|
||||
### Deprecated
|
||||
- Initial release.
|
||||
|
||||
### Removed
|
||||
- Initial release.
|
||||
|
||||
### Fixed
|
||||
- Issue #264
|
||||
- Issue #265
|
||||
@@ -59,10 +176,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Bulk update problems, #280, thanks @stickgrinder
|
||||
- Fixed various problems with amount reporting of split transactions.
|
||||
|
||||
### Security
|
||||
- Initial release.
|
||||
|
||||
|
||||
[3.9.1]
|
||||
### Fixed
|
||||
- Fixed a bug where removing money from a piggy bank would not work. See issue #265 and #269
|
||||
|
4
LICENSE
4
LICENSE
@@ -1,7 +1,7 @@
|
||||
Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ConfigureLogging.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -22,24 +24,40 @@ use Illuminate\Log\Writer;
|
||||
*/
|
||||
class ConfigureLogging extends IlluminateConfigureLogging
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @param Writer $log
|
||||
* 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',
|
||||
$app->make('config')->get('app.log_max_files', 5)
|
||||
$app->storagePath() . '/logs/firefly-iii.log', is_null($maxFiles) ? 5 : $maxFiles,
|
||||
$config->get('app.log_level', 'debug')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @param Writer $log
|
||||
* 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');
|
||||
$log->useFiles(
|
||||
$app->storagePath() . '/logs/firefly-iii.log',
|
||||
$app->make('config')->get('app.log_level', 'debug')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
152
app/Console/Commands/CreateImport.php
Normal file
152
app/Console/Commands/CreateImport.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* CreateImport.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Artisan;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Console\Command;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class CreateImport
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class CreateImport extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Use this command to create a new import. Your user ID can be found on the /profile page.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:create-import {file} {configuration} {--user=1} {--type=csv} {--start}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// find the file
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
$configuration = $this->argument('configuration');
|
||||
$user = $userRepository->find(intval($this->option('user')));
|
||||
$cwd = getcwd();
|
||||
$type = strtolower($this->option('type'));
|
||||
|
||||
if (!$this->validArguments()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// try to parse configuration data:
|
||||
$configurationData = json_decode(file_get_contents($configuration));
|
||||
if (is_null($configurationData)) {
|
||||
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->info(sprintf('Going to create a job to import file: %s', $file));
|
||||
$this->info(sprintf('Using configuration file: %s', $configuration));
|
||||
$this->info(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
||||
$this->info(sprintf('Type of import: %s', $type));
|
||||
|
||||
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
|
||||
|
||||
$job = $jobRepository->create($type);
|
||||
$this->line(sprintf('Created job "%s"...', $job->key));
|
||||
|
||||
// put the file in the proper place:
|
||||
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
|
||||
$this->line('Stored import data...');
|
||||
|
||||
// store the configuration in the job:
|
||||
$job->configuration = $configurationData;
|
||||
$job->status = 'settings_complete';
|
||||
$job->save();
|
||||
$this->line('Stored configuration...');
|
||||
|
||||
// if user wants to run it, do!
|
||||
if ($this->option('start') === true) {
|
||||
$this->line('The import will start in a moment. This process is not visible...');
|
||||
Log::debug('Go for import!');
|
||||
Artisan::call('firefly:start-import', ['key' => $job->key]);
|
||||
$this->line('Done!');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function validArguments(): bool
|
||||
{
|
||||
// find the file
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
$configuration = $this->argument('configuration');
|
||||
$user = $userRepository->find(intval($this->option('user')));
|
||||
$cwd = getcwd();
|
||||
$validTypes = array_keys(config('firefly.import_formats'));
|
||||
$type = strtolower($this->option('type'));
|
||||
|
||||
if (is_null($user->id)) {
|
||||
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!in_array($type, $validTypes)) {
|
||||
$this->error(sprintf('Cannot import file of type "%s"', $type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($file)) {
|
||||
$this->error(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($configuration)) {
|
||||
$this->error(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
* EncryptFile.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -46,8 +48,6 @@ class EncryptFile extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -64,6 +64,5 @@ class EncryptFile extends Command
|
||||
$path = storage_path('upload') . '/' . $newName;
|
||||
file_put_contents($path, $content);
|
||||
$this->line(sprintf('Encrypted "%s" and put it in "%s"', $file, $path));
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Import.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -12,9 +14,9 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Import\ImportProcedure;
|
||||
use FireflyIII\Import\ImportResult;
|
||||
use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Log;
|
||||
|
||||
@@ -30,14 +32,14 @@ class Import extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Import stuff into Firefly III.';
|
||||
protected $description = 'This will start a new import.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:import {key}';
|
||||
protected $signature = 'firefly:start-import {key}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
@@ -55,9 +57,12 @@ class Import extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Log::debug('Start start-import command');
|
||||
$jobKey = $this->argument('key');
|
||||
$job = ImportJob::whereKey($jobKey)->first();
|
||||
if (!$this->isValid($job)) {
|
||||
Log::error('Job is not valid for some reason. Exit.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,24 +72,33 @@ class Import extends Command
|
||||
$handler = new CommandHandler($this);
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
$result = ImportProcedure::run($job);
|
||||
$result = ImportProcedure::runImport($job);
|
||||
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var ImportResult $entry
|
||||
* @var int $index
|
||||
* @var TransactionJournal $journal
|
||||
*/
|
||||
foreach ($result as $index => $entry) {
|
||||
if ($entry->isSuccess()) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $entry->journal->id));
|
||||
foreach ($result as $index => $journal) {
|
||||
if (!is_null($journal->id)) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
|
||||
continue;
|
||||
}
|
||||
$errors = join(', ', $entry->errors->all());
|
||||
$this->error(sprintf('Could not store line #%d, because: %s', $index, $errors));
|
||||
$this->error(sprintf('Could not store line #%d', $index));
|
||||
}
|
||||
|
||||
|
||||
$this->line('The import has completed.');
|
||||
|
||||
// get any errors from the importer:
|
||||
$extendedStatus = $job->extended_status;
|
||||
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
|
||||
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
|
||||
foreach ($extendedStatus['errors'] as $error) {
|
||||
$this->error($error);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
101
app/Console/Commands/ScanAttachments.php
Normal file
101
app/Console/Commands/ScanAttachments.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* ScanAttachments.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class ScanAttachments
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class ScanAttachments extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rescan all attachments and re-set the MD5 hash and mime.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:scan-attachments';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$attachments = Attachment::get();
|
||||
$disk = Storage::disk('upload');
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($attachments as $attachment) {
|
||||
$fileName = $attachment->fileName();
|
||||
|
||||
// try to grab file content:
|
||||
try {
|
||||
$content = $disk->get($fileName);
|
||||
} catch (FileNotFoundException $e) {
|
||||
$this->error(sprintf('Could not find data for attachment #%d', $attachment->id));
|
||||
continue;
|
||||
}
|
||||
// try to decrypt content.
|
||||
try {
|
||||
$decrypted = Crypt::decrypt($content);
|
||||
} catch (DecryptException $e) {
|
||||
$this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id));
|
||||
continue;
|
||||
}
|
||||
|
||||
// make temp file:
|
||||
$tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII');
|
||||
|
||||
// store content in temp file:
|
||||
file_put_contents($tmpfname, $decrypted);
|
||||
|
||||
// get md5 and mime
|
||||
$md5 = md5_file($tmpfname);
|
||||
$mime = mime_content_type($tmpfname);
|
||||
|
||||
// update attachment:
|
||||
$attachment->md5 = $md5;
|
||||
$attachment->mime = $mime;
|
||||
$attachment->save();
|
||||
|
||||
|
||||
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
|
||||
|
||||
// find file:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
121
app/Console/Commands/UpgradeDatabase.php
Normal file
121
app/Console/Commands/UpgradeDatabase.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
* UpgradeDatabase.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class UpgradeDatabase
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class UpgradeDatabase extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Will run various commands to update database records.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:upgrade-database';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->setTransactionIdentifier();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird.
|
||||
*/
|
||||
private function setTransactionIdentifier()
|
||||
{
|
||||
$subQuery = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->groupBy(['transaction_journals.id'])
|
||||
->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]);
|
||||
|
||||
$result = DB::table(DB::raw('(' . $subQuery->toSql() . ') AS derived'))
|
||||
->mergeBindings($subQuery->getQuery())
|
||||
->where('t_count', '>', 2)
|
||||
->select(['id', 't_count']);
|
||||
$journalIds = array_unique($result->pluck('id')->toArray());
|
||||
|
||||
foreach ($journalIds as $journalId) {
|
||||
// grab all positive transactiosn from this journal that are not deleted.
|
||||
// for each one, grab the negative opposing one which has 0 as an identifier and give it the same identifier.
|
||||
$identifier = 0;
|
||||
$processed = [];
|
||||
$transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get();
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
// find opposing:
|
||||
$amount = bcmul(strval($transaction->amount), '-1');
|
||||
|
||||
try {
|
||||
/** @var Transaction $opposing */
|
||||
$opposing = Transaction
|
||||
::where('transaction_journal_id', $journalId)
|
||||
->where('amount', $amount)->where('identifier', '=', 0)
|
||||
->whereNotIn('id', $processed)
|
||||
->first();
|
||||
} catch (QueryException $e) {
|
||||
Log::error($e->getMessage());
|
||||
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
|
||||
$this->error('This field is required for Firefly III version ' . config('firefly.version') . ' to run.');
|
||||
$this->error('Please run "php artisan migrate" to add this field to the table.');
|
||||
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
|
||||
break 2;
|
||||
}
|
||||
if (!is_null($opposing)) {
|
||||
// give both a new identifier:
|
||||
$transaction->identifier = $identifier;
|
||||
$transaction->save();
|
||||
$opposing->identifier = $identifier;
|
||||
$opposing->save();
|
||||
$processed[] = $transaction->id;
|
||||
$processed[] = $opposing->id;
|
||||
$this->line(sprintf('Database upgrade for journal #%d, transactions #%d and #%d', $journalId, $transaction->id, $opposing->id));
|
||||
}
|
||||
$identifier++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
* UpgradeFireflyInstructions.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -44,8 +46,6 @@ class UpgradeFireflyInstructions extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -53,15 +53,22 @@ class UpgradeFireflyInstructions extends Command
|
||||
/** @var string $version */
|
||||
$version = config('firefly.version');
|
||||
$config = config('upgrade.text');
|
||||
$text = $config[$version] ?? null;
|
||||
$text = null;
|
||||
foreach (array_keys($config) as $compare) {
|
||||
// if string starts with:
|
||||
$len = strlen($compare);
|
||||
if (substr($version, 0, $len) === $compare) {
|
||||
$text = $config[$compare];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->line('+------------------------------------------------------------------------------+');
|
||||
$this->line('');
|
||||
|
||||
if (is_null($text)) {
|
||||
$this->line('Thank you for installing Firefly III, v' . $version);
|
||||
$this->line('If you are upgrading from a previous version,');
|
||||
$this->info('there are no extra upgrade instructions.');
|
||||
$this->info('There are no extra upgrade instructions.');
|
||||
$this->line('Firefly III should be ready for use.');
|
||||
} else {
|
||||
$this->line('Thank you for installing Firefly III, v' . $version);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* VerifyDatabase.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -12,13 +14,13 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
@@ -55,8 +57,6 @@ class VerifyDatabase extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -81,6 +81,9 @@ class VerifyDatabase extends Command
|
||||
|
||||
// report on journals with no transactions at all.
|
||||
$this->reportNoTransactions();
|
||||
|
||||
// transfers with budgets.
|
||||
$this->reportTransfersBudgets();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,11 +94,10 @@ class VerifyDatabase extends Command
|
||||
$set = Account
|
||||
::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
|
||||
->groupBy('accounts.id')
|
||||
->having('transaction_count', '=', 0)
|
||||
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
|
||||
->whereNull('transactions.account_id')
|
||||
->get(
|
||||
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email',
|
||||
DB::raw('COUNT(`transactions`.`id`) AS `transaction_count`')]
|
||||
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email']
|
||||
);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
@@ -115,9 +117,9 @@ class VerifyDatabase extends Command
|
||||
$set = Budget
|
||||
::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->groupBy('budgets.id')
|
||||
->having('budget_limit_count', '=', 0)
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email', DB::raw('COUNT(`budget_limits`.`id`) AS `budget_limit_count`')]);
|
||||
->groupBy(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email'])
|
||||
->whereNull('budget_limits.id')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
@@ -195,7 +197,7 @@ class VerifyDatabase extends Command
|
||||
$date = is_null($entry->transaction_deleted_at) ? $entry->journal_deleted_at : $entry->transaction_deleted_at;
|
||||
$this->error(
|
||||
'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called `accounts` and change the `deleted_at` field to: "' . $date . '"'
|
||||
' Find it in the table called "accounts" and change the "deleted_at" field to: "' . $date . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -222,28 +224,25 @@ class VerifyDatabase extends Command
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called `transactions` and change the `deleted_at` field to: "' . $entry->journal_deleted . '"'
|
||||
' Find it in the table called "transactions" and change the "deleted_at" field to: "' . $entry->journal_deleted . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function reportNoTransactions()
|
||||
{
|
||||
/*
|
||||
* select transaction_journals.id, count(transactions.id) as transaction_count from transaction_journals
|
||||
left join transactions ON transaction_journals.id = transactions.transaction_journal_id
|
||||
group by transaction_journals.id
|
||||
having transaction_count = 0
|
||||
*/
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->groupBy('transaction_journals.id')
|
||||
->having('transaction_count', '=', 0)
|
||||
->get(['transaction_journals.id', DB::raw('COUNT(`transactions`.`id`) as `transaction_count`')]);
|
||||
->whereNull('transactions.transaction_journal_id')
|
||||
->get(['transaction_journals.id']);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table `transaction_journals` and delete the entry with id #' . $entry->id
|
||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table "transaction_journals" and delete the entry with id #' . $entry->id
|
||||
);
|
||||
}
|
||||
|
||||
@@ -304,8 +303,33 @@ having transaction_count = 0
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Transaction journal #' . $entry->journal_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called `transaction_journals` and change the `deleted_at` field to: "' . $entry->transaction_deleted . '"'
|
||||
' Find it in the table called "transaction_journals" and change the "deleted_at" field to: "' . $entry->transaction_deleted . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function reportTransfersBudgets()
|
||||
{
|
||||
$set = TransactionJournal
|
||||
::distinct()
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||
->where('transaction_types.type', TransactionType::TRANSFER)
|
||||
->whereNotNull('budget_transaction_journal.budget_id')->get(['transaction_journals.id']);
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Error: Transaction journal #%d is a transfer, but has a budget. Edit it without changing anything, so the budget will be removed.',
|
||||
$entry->id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
38
app/Console/Kernel.php
Normal file → Executable file
38
app/Console/Kernel.php
Normal file → Executable file
@@ -3,18 +3,24 @@
|
||||
* Kernel.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use FireflyIII\Console\Commands\CreateImport;
|
||||
use FireflyIII\Console\Commands\EncryptFile;
|
||||
use FireflyIII\Console\Commands\Import;
|
||||
use FireflyIII\Console\Commands\ScanAttachments;
|
||||
use FireflyIII\Console\Commands\UpgradeDatabase;
|
||||
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
||||
use FireflyIII\Console\Commands\VerifyDatabase;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
/**
|
||||
@@ -24,11 +30,10 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
*/
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
|
||||
/**
|
||||
* The bootstrap classes for the application.
|
||||
*
|
||||
* This needs to be for with the next upgrade.
|
||||
* Next upgrade verify these are the same.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@@ -54,6 +59,31 @@ class Kernel extends ConsoleKernel
|
||||
UpgradeFireflyInstructions::class,
|
||||
VerifyDatabase::class,
|
||||
Import::class,
|
||||
CreateImport::class,
|
||||
EncryptFile::class,
|
||||
ScanAttachments::class,
|
||||
UpgradeDatabase::class,
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the Closure based commands for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@@ -1,530 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AccountCrud.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Crud\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class AccountCrud
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
*
|
||||
* @package FireflyIII\Crud\Account
|
||||
*/
|
||||
class AccountCrud implements AccountCrudInterface
|
||||
{
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
/** @var array */
|
||||
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber'];
|
||||
|
||||
/**
|
||||
* AccountCrud constructor.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account $moveTo
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(Account $account, Account $moveTo): bool
|
||||
{
|
||||
if (!is_null($moveTo->id)) {
|
||||
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
|
||||
}
|
||||
if (!is_null($account)) {
|
||||
$account->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $accountId
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function find(int $accountId): Account
|
||||
{
|
||||
$account = $this->user->accounts()->find($accountId);
|
||||
if (is_null($account)) {
|
||||
return new Account;
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByAccountNumber(string $number, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts()
|
||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
||||
->where('account_meta.name', 'accountNumber')
|
||||
->where('account_meta.data', json_encode($number));
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
/** @var Collection $accounts */
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
if ($accounts->count() > 0) {
|
||||
return $accounts->first();
|
||||
}
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $iban
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByIban(string $iban, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts()->where('iban', '!=', '');
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->iban === $iban) {
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByName(string $name, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts();
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->name === $name) {
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $accountIds
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAccountsById(array $accountIds): Collection
|
||||
{
|
||||
/** @var Collection $result */
|
||||
$query = $this->user->accounts()->with(
|
||||
['accountmeta' => function (HasMany $query) {
|
||||
$query->where('name', 'accountRole');
|
||||
}]
|
||||
);
|
||||
|
||||
if (count($accountIds) > 0) {
|
||||
$query->whereIn('accounts.id', $accountIds);
|
||||
}
|
||||
|
||||
$result = $query->get(['accounts.*']);
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
}
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAccountsByType(array $types): Collection
|
||||
{
|
||||
/** @var Collection $result */
|
||||
$query = $this->user->accounts()->with(
|
||||
['accountmeta' => function (HasMany $query) {
|
||||
$query->where('name', 'accountRole');
|
||||
}]
|
||||
);
|
||||
if (count($types) > 0) {
|
||||
$query->accountTypeIn($types);
|
||||
}
|
||||
|
||||
$result = $query->get(['accounts.*']);
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
}
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function store(array $data): Account
|
||||
{
|
||||
$newAccount = $this->storeAccount($data);
|
||||
if (!is_null($newAccount->id)) {
|
||||
$this->storeMetadata($newAccount, $data);
|
||||
}
|
||||
|
||||
if ($data['openingBalance'] != 0) {
|
||||
$this->storeInitialBalance($newAccount, $data);
|
||||
}
|
||||
|
||||
return $newAccount;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $account
|
||||
* @param $name
|
||||
* @param $value
|
||||
*
|
||||
* @return AccountMeta
|
||||
*/
|
||||
public function storeMeta(Account $account, string $name, $value): AccountMeta
|
||||
{
|
||||
return AccountMeta::create(['name' => $name, 'data' => $value, 'account_id' => $account->id,]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function update(Account $account, array $data): Account
|
||||
{
|
||||
// update the account:
|
||||
$account->name = $data['name'];
|
||||
$account->active = $data['active'] == '1' ? true : false;
|
||||
$account->virtual_balance = $data['virtualBalance'];
|
||||
$account->iban = $data['iban'];
|
||||
$account->save();
|
||||
|
||||
$this->updateMetadata($account, $data);
|
||||
$this->updateInitialBalance($account, $data);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $type
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function updateAccountType(Account $account, string $type): Account
|
||||
{
|
||||
$type = AccountType::whereType($type)->first();
|
||||
if (!is_null($type)) {
|
||||
$account->accountType()->associate($type);
|
||||
$account->save();
|
||||
}
|
||||
|
||||
return $this->find($account->id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
protected function storeAccount(array $data): Account
|
||||
{
|
||||
$type = config('firefly.accountTypeByIdentifier.' . $data['accountType']);
|
||||
$accountType = AccountType::whereType($type)->first();
|
||||
$newAccount = new Account(
|
||||
[
|
||||
'user_id' => $data['user'],
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $data['name'],
|
||||
'virtual_balance' => $data['virtualBalance'],
|
||||
'active' => $data['active'] === true ? true : false,
|
||||
'iban' => $data['iban'],
|
||||
]
|
||||
);
|
||||
|
||||
if (!$newAccount->isValid()) {
|
||||
// does the account already exist?
|
||||
$searchData = [
|
||||
'user_id' => $data['user'],
|
||||
'account_type_id' => $accountType->id,
|
||||
'virtual_balance' => $data['virtualBalance'],
|
||||
'name' => $data['name'],
|
||||
'iban' => $data['iban'],
|
||||
];
|
||||
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
||||
if (!$existingAccount) {
|
||||
Log::error('Account create error', $newAccount->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
$newAccount = $existingAccount;
|
||||
|
||||
}
|
||||
$newAccount->save();
|
||||
|
||||
return $newAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
protected function storeInitialBalance(Account $account, array $data): TransactionJournal
|
||||
{
|
||||
$amount = $data['openingBalance'];
|
||||
$user = $data['user'];
|
||||
$name = $data['name'];
|
||||
$opposing = $this->storeOpposingAccount($amount, $user, $name);
|
||||
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => $data['user'],
|
||||
'transaction_type_id' => $transactionType->id,
|
||||
'transaction_currency_id' => $data['openingBalanceCurrency'],
|
||||
'description' => 'Initial balance for "' . $account->name . '"',
|
||||
'completed' => true,
|
||||
'date' => $data['openingBalanceDate'],
|
||||
'encrypted' => true,
|
||||
]
|
||||
);
|
||||
|
||||
$firstAccount = $account;
|
||||
$secondAccount = $opposing;
|
||||
$firstAmount = $amount;
|
||||
$secondAmount = $amount * -1;
|
||||
|
||||
if ($data['openingBalance'] < 0) {
|
||||
$firstAccount = $opposing;
|
||||
$secondAccount = $account;
|
||||
$firstAmount = $amount * -1;
|
||||
$secondAmount = $amount;
|
||||
}
|
||||
|
||||
$one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
|
||||
$one->save();// first transaction: from
|
||||
$two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]);
|
||||
$two->save(); // second transaction: to
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
protected function storeMetadata(Account $account, array $data)
|
||||
{
|
||||
foreach ($this->validFields as $field) {
|
||||
if (isset($data[$field])) {
|
||||
$metaData = new AccountMeta(
|
||||
[
|
||||
'account_id' => $account->id,
|
||||
'name' => $field,
|
||||
'data' => $data[$field],
|
||||
]
|
||||
);
|
||||
$metaData->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function updateInitialBalance(Account $account, array $data): bool
|
||||
{
|
||||
$openingBalance = $this->openingBalanceTransaction($account);
|
||||
if ($data['openingBalance'] != 0) {
|
||||
if (!is_null($openingBalance->id)) {
|
||||
$date = $data['openingBalanceDate'];
|
||||
$amount = $data['openingBalance'];
|
||||
|
||||
return $this->updateJournal($account, $openingBalance, $date, $amount);
|
||||
}
|
||||
|
||||
$this->storeInitialBalance($account, $data);
|
||||
|
||||
return true;
|
||||
}
|
||||
// else, delete it:
|
||||
if ($openingBalance) { // opening balance is zero, should we delete it?
|
||||
$openingBalance->delete(); // delete existing opening balance.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
*/
|
||||
protected function updateMetadata(Account $account, array $data)
|
||||
{
|
||||
foreach ($this->validFields as $field) {
|
||||
$entry = $account->accountMeta()->where('name', $field)->first();
|
||||
|
||||
if (isset($data[$field])) {
|
||||
// update if new data is present:
|
||||
if (!is_null($entry)) {
|
||||
$entry->data = $data[$field];
|
||||
$entry->save();
|
||||
|
||||
continue;
|
||||
}
|
||||
$metaData = new AccountMeta(
|
||||
[
|
||||
'account_id' => $account->id,
|
||||
'name' => $field,
|
||||
'data' => $data[$field],
|
||||
]
|
||||
);
|
||||
$metaData->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return TransactionJournal|null
|
||||
*/
|
||||
private function openingBalanceTransaction(Account $account): TransactionJournal
|
||||
{
|
||||
$journal = TransactionJournal
|
||||
::sortCorrectly()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->transactionTypes([TransactionType::OPENING_BALANCE])
|
||||
->first(['transaction_journals.*']);
|
||||
if (is_null($journal)) {
|
||||
return new TransactionJournal;
|
||||
}
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $amount
|
||||
* @param int $user
|
||||
* @param string $name
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function storeOpposingAccount(float $amount, int $user, string $name):Account
|
||||
{
|
||||
$type = $amount < 0 ? 'expense' : 'revenue';
|
||||
$opposingData = [
|
||||
'user' => $user,
|
||||
'accountType' => $type,
|
||||
'name' => $name . ' initial balance',
|
||||
'active' => false,
|
||||
'iban' => '',
|
||||
'virtualBalance' => 0,
|
||||
];
|
||||
|
||||
return $this->storeAccount($opposingData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param TransactionJournal $journal
|
||||
* @param Carbon $date
|
||||
* @param float $amount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function updateJournal(Account $account, TransactionJournal $journal, Carbon $date, float $amount): bool
|
||||
{
|
||||
// update date:
|
||||
$journal->date = $date;
|
||||
$journal->save();
|
||||
// update transactions:
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions()->get() as $transaction) {
|
||||
if ($account->id == $transaction->account_id) {
|
||||
$transaction->amount = $amount;
|
||||
$transaction->save();
|
||||
}
|
||||
if ($account->id != $transaction->account_id) {
|
||||
$transaction->amount = $amount * -1;
|
||||
$transaction->save();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AccountCrudInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Crud\Account;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface AccountCrudInterface
|
||||
*
|
||||
* @package FireflyIII\Crud\Account
|
||||
*/
|
||||
interface AccountCrudInterface
|
||||
{
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account $moveTo
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(Account $account, Account $moveTo): bool;
|
||||
|
||||
/**
|
||||
* @param int $accountId
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function find(int $accountId): Account;
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByAccountNumber(string $number, array $types): Account;
|
||||
|
||||
/**
|
||||
* @param string $iban
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByIban(string $iban, array $types): Account;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByName(string $name, array $types): Account;
|
||||
|
||||
/**
|
||||
* @param array $accountIds
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAccountsById(array $accountIds): Collection;
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAccountsByType(array $types): Collection;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function store(array $data) : Account;
|
||||
|
||||
/**
|
||||
* @param $account
|
||||
* @param $name
|
||||
* @param $value
|
||||
*
|
||||
* @return AccountMeta
|
||||
*/
|
||||
public function storeMeta(Account $account, string $name, $value): AccountMeta;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function update(Account $account, array $data): Account;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $type
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function updateAccountType(Account $account, string $type): Account;
|
||||
}
|
@@ -1,216 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Journal.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Crud\Split;
|
||||
|
||||
use FireflyIII\Events\TransactionStored;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class Journal
|
||||
*
|
||||
* @package FireflyIII\Crud\Split
|
||||
*/
|
||||
class Journal implements JournalInterface
|
||||
{
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* AttachmentRepository constructor.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $journal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function markAsComplete(TransactionJournal $journal)
|
||||
{
|
||||
$journal->completed = 1;
|
||||
$journal->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $transaction
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function storeTransaction(TransactionJournal $journal, array $transaction): Collection
|
||||
{
|
||||
// store accounts (depends on type)
|
||||
list($sourceAccount, $destinationAccount) = $this->storeAccounts($journal->transactionType->type, $transaction);
|
||||
|
||||
// store transaction one way:
|
||||
/** @var Transaction $one */
|
||||
$one = Transaction::create(
|
||||
['account_id' => $sourceAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $transaction['amount'] * -1,
|
||||
'description' => $transaction['description']]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
['account_id' => $destinationAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $transaction['amount'],
|
||||
'description' => $transaction['description']]
|
||||
);
|
||||
|
||||
if (strlen($transaction['category']) > 0) {
|
||||
$category = Category::firstOrCreateEncrypted(['name' => $transaction['category'], 'user_id' => $journal->user_id]);
|
||||
$one->categories()->save($category);
|
||||
$two->categories()->save($category);
|
||||
}
|
||||
if (intval($transaction['budget_id']) > 0) {
|
||||
$budget = Budget::find($transaction['budget_id']);
|
||||
$one->budgets()->save($budget);
|
||||
$two->budgets()->save($budget);
|
||||
}
|
||||
|
||||
if ($transaction['piggy_bank_id'] > 0) {
|
||||
$transaction['date'] = $journal->date->format('Y-m-d');
|
||||
event(new TransactionStored($transaction));
|
||||
}
|
||||
|
||||
return new Collection([$one, $two]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal
|
||||
{
|
||||
$journal->description = $data['journal_description'];
|
||||
$journal->transaction_currency_id = $data['journal_currency_id'];
|
||||
$journal->date = $data['date'];
|
||||
$journal->interest_date = $data['interest_date'];
|
||||
$journal->book_date = $data['book_date'];
|
||||
$journal->process_date = $data['process_date'];
|
||||
$journal->save();
|
||||
|
||||
// delete original transactions, and recreate them.
|
||||
$journal->transactions()->delete();
|
||||
|
||||
foreach ($data['transactions'] as $transaction) {
|
||||
$this->storeTransaction($journal, $transaction);
|
||||
}
|
||||
|
||||
$journal->completed = true;
|
||||
$journal->save();
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param array $transaction
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function storeAccounts(string $type, array $transaction): array
|
||||
{
|
||||
$sourceAccount = null;
|
||||
$destinationAccount = null;
|
||||
switch ($type) {
|
||||
case TransactionType::WITHDRAWAL:
|
||||
list($sourceAccount, $destinationAccount) = $this->storeWithdrawalAccounts($transaction);
|
||||
break;
|
||||
case TransactionType::DEPOSIT:
|
||||
list($sourceAccount, $destinationAccount) = $this->storeDepositAccounts($transaction);
|
||||
break;
|
||||
case TransactionType::TRANSFER:
|
||||
$sourceAccount = Account::where('user_id', $this->user->id)->where('id', $transaction['source_account_id'])->first();
|
||||
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $transaction['destination_account_id'])->first();
|
||||
break;
|
||||
default:
|
||||
throw new FireflyException('Cannot handle ' . e($type));
|
||||
}
|
||||
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function storeDepositAccounts(array $data): array
|
||||
{
|
||||
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']);
|
||||
|
||||
|
||||
if (isset($data['source_account_name']) && strlen($data['source_account_name']) > 0) {
|
||||
$sourceType = AccountType::where('type', 'Revenue account')->first();
|
||||
$sourceAccount = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1]
|
||||
);
|
||||
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
|
||||
$sourceType = AccountType::where('type', 'Cash account')->first();
|
||||
$sourceAccount = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1]
|
||||
);
|
||||
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function storeWithdrawalAccounts(array $data): array
|
||||
{
|
||||
$sourceAccount = Account::where('user_id', $this->user->id)->where('id', $data['source_account_id'])->first(['accounts.*']);
|
||||
|
||||
if (strlen($data['destination_account_name']) > 0) {
|
||||
$destinationType = AccountType::where('type', 'Expense account')->first();
|
||||
$destinationAccount = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
'account_type_id' => $destinationType->id,
|
||||
'name' => $data['destination_account_name'],
|
||||
'active' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
$destinationType = AccountType::where('type', 'Cash account')->first();
|
||||
$destinationAccount = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $this->user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1]
|
||||
);
|
||||
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* JournalInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Crud\Split;
|
||||
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface JournalInterface
|
||||
*
|
||||
* @package FireflyIII\Crud\Split
|
||||
*/
|
||||
interface JournalInterface
|
||||
{
|
||||
/**
|
||||
* @param $journal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function markAsComplete(TransactionJournal $journal);
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $transaction
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function storeTransaction(TransactionJournal $journal, array $transaction): Collection;
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal;
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* ResendConfirmation.php
|
||||
* ConfirmedUser.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class ResendConfirmation
|
||||
* Class ConfirmedUser
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class ResendConfirmation extends Event
|
||||
class ConfirmedUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Event.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* UserIsConfirmed.php
|
||||
* RegisteredUser.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserIsConfirmed
|
||||
* Class RegisteredUser
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserIsConfirmed extends Event
|
||||
class RegisteredUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* UserIsDeleted.php
|
||||
* ResentConfirmation.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserIsDeleted
|
||||
* Class ResentConfirmation
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserIsDeleted extends Event
|
||||
class ResentConfirmation extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitStored.php
|
||||
* StoredBudgetLimit.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitStored
|
||||
* Class StoredBudgetLimit
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class BudgetLimitStored extends Event
|
||||
class StoredBudgetLimit extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionJournalStored.php
|
||||
* StoredTransactionJournal.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalStored
|
||||
* Class StoredTransactionJournal
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionJournalStored extends Event
|
||||
class StoredTransactionJournal extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionStored.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalStored
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionStored extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $transaction = [];
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param array $transaction
|
||||
*/
|
||||
public function __construct(array $transaction)
|
||||
{
|
||||
//
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitUpdated.php
|
||||
* UpdatedBudgetLimit.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitUpdated
|
||||
* Class UpdatedBudgetLimit
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class BudgetLimitUpdated extends Event
|
||||
class UpdatedBudgetLimit extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionJournalUpdated.php
|
||||
* UpdatedTransactionJournal.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalUpdated
|
||||
* Class UpdatedTransactionJournal
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionJournalUpdated extends Event
|
||||
class UpdatedTransactionJournal extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* UserRegistration.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserRegistration
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserRegistration extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $ipAddress;
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
public function __construct(User $user, string $ipAddress)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->ipAddress = $ipAddress;
|
||||
}
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
* FireflyException.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
40
app/Exceptions/Handler.php
Normal file → Executable file
40
app/Exceptions/Handler.php
Normal file → Executable file
@@ -3,21 +3,24 @@
|
||||
* Handler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use Auth;
|
||||
use ErrorException;
|
||||
use Exception;
|
||||
use FireflyIII\Jobs\MailError;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Request;
|
||||
use Illuminate\Session\TokenMismatchException;
|
||||
use Illuminate\Validation\ValidationException as ValException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
/**
|
||||
@@ -34,9 +37,12 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
protected $dontReport
|
||||
= [
|
||||
AuthenticationException::class,
|
||||
AuthorizationException::class,
|
||||
HttpException::class,
|
||||
ModelNotFoundException::class,
|
||||
TokenMismatchException::class,
|
||||
ValException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -71,15 +77,14 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
public function report(Exception $exception)
|
||||
{
|
||||
|
||||
if ($exception instanceof FireflyException || $exception instanceof ErrorException) {
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
];
|
||||
if (Auth::check()) {
|
||||
$userData['id'] = Auth::user()->id;
|
||||
$userData['email'] = Auth::user()->email;
|
||||
if (auth()->check()) {
|
||||
$userData['id'] = auth()->user()->id;
|
||||
$userData['email'] = auth()->user()->email;
|
||||
}
|
||||
$data = [
|
||||
'class' => get_class($exception),
|
||||
@@ -92,10 +97,27 @@ class Handler extends ExceptionHandler
|
||||
];
|
||||
|
||||
// create job that will mail.
|
||||
$job = new MailError($userData, env('SITE_OWNER'), Request::ip(), $data);
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
||||
$job = new MailError($userData, env('SITE_OWNER', ''), $ip, $data);
|
||||
dispatch($job);
|
||||
}
|
||||
|
||||
parent::report($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an authentication exception into an unauthenticated response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function unauthenticated($request)
|
||||
{
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json(['error' => 'Unauthenticated.'], 401);
|
||||
}
|
||||
|
||||
return redirect()->guest('login');
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* NotImplementedException.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ValidationException.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* AttachmentCollector.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -92,6 +94,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
'amount' => Amount::formatJournal($journal, false),
|
||||
];
|
||||
$string = trans('firefly.attachment_explanation', $args) . "\n";
|
||||
Log::debug('Appended explanation string', ['string' => $string]);
|
||||
$this->explanationString .= $string;
|
||||
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BasicCollector.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* CollectorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,15 +3,16 @@
|
||||
* UploadCollector.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
@@ -29,6 +30,7 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
private $expected;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $exportDisk;
|
||||
private $importKeys = [];
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $uploadDisk;
|
||||
|
||||
@@ -42,10 +44,17 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
parent::__construct($job);
|
||||
|
||||
Log::debug('Going to collect attachments', ['key' => $job->key]);
|
||||
|
||||
// make storage:
|
||||
$this->uploadDisk = Storage::disk('upload');
|
||||
$this->exportDisk = Storage::disk('export');
|
||||
$this->expected = 'csv-upload-' . Auth::user()->id . '-';
|
||||
|
||||
// file names associated with the old import routine.
|
||||
$this->expected = 'csv-upload-' . auth()->user()->id . '-';
|
||||
|
||||
// for the new import routine:
|
||||
$this->getImportKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,12 +66,26 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
$files = $this->uploadDisk->files();
|
||||
|
||||
foreach ($files as $entry) {
|
||||
$this->processOldUpload($entry);
|
||||
$this->processUpload($entry);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function getImportKeys()
|
||||
{
|
||||
$set = auth()->user()->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
||||
if ($set->count() > 0) {
|
||||
$keys = $set->pluck('key')->toArray();
|
||||
$this->importKeys = $keys;
|
||||
|
||||
}
|
||||
Log::debug('Valid import keys are ', $this->importKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*
|
||||
@@ -83,9 +106,28 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isValidFile(string $entry): bool
|
||||
private function isImportFile(string $entry): bool
|
||||
{
|
||||
$name = str_replace('.upload', '', $entry);
|
||||
if (in_array($name, $this->importKeys)) {
|
||||
Log::debug(sprintf('Import file "%s" is in array', $name), $this->importKeys);
|
||||
|
||||
return true;
|
||||
}
|
||||
Log::debug(sprintf('Import file "%s" is NOT in array', $name), $this->importKeys);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isOldImport(string $entry): bool
|
||||
{
|
||||
$len = strlen($this->expected);
|
||||
// file is part of the old import routine:
|
||||
if (substr($entry, 0, $len) === $this->expected) {
|
||||
|
||||
return true;
|
||||
@@ -97,23 +139,63 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
/**
|
||||
* @param $entry
|
||||
*/
|
||||
private function processOldUpload(string $entry)
|
||||
private function processUpload(string $entry)
|
||||
{
|
||||
$content = '';
|
||||
|
||||
if ($this->isValidFile($entry)) {
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old CSV import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
}
|
||||
// file is old import:
|
||||
if ($this->isOldImport($entry)) {
|
||||
$this->saveOldImportFile($entry);
|
||||
}
|
||||
if (strlen($content) > 0) {
|
||||
// continue with file:
|
||||
$date = $this->getOriginalUploadDate($entry);
|
||||
$file = $this->job->key . '-Old CSV import dated ' . $date . '.csv';
|
||||
|
||||
// file is current import.
|
||||
if ($this->isImportFile($entry)) {
|
||||
$this->saveImportFile($entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*/
|
||||
private function saveImportFile(string $entry)
|
||||
{
|
||||
// find job associated with import file:
|
||||
$name = str_replace('.upload', '', $entry);
|
||||
$job = auth()->user()->importJobs()->where('key', $name)->first();
|
||||
$content = '';
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
}
|
||||
|
||||
if (!is_null($job) && strlen($content) > 0) {
|
||||
// add to export disk.
|
||||
$date = $job->created_at->format('Y-m-d');
|
||||
$file = sprintf('%s-Old %s import dated %s.%s', $this->job->key, strtoupper($job->file_type), $date, $job->file_type);
|
||||
$this->exportDisk->put($file, $content);
|
||||
$this->getFiles()->push($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*/
|
||||
private function saveOldImportFile(string $entry)
|
||||
{
|
||||
$content = '';
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old CSV import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
}
|
||||
|
||||
if (strlen($content) > 0) {
|
||||
// add to export disk.
|
||||
$date = $this->getOriginalUploadDate($entry);
|
||||
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
||||
$this->exportDisk->put($file, $content);
|
||||
$this->getFiles()->push($file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ConfigurationFile.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Entry.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* EntryAccount.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* EntryBill.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* EntryBudget.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* EntryCategory.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BasicExporter.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* CsvExporter.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ExporterInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Processor.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -17,7 +19,7 @@ use FireflyIII\Export\Collector\UploadCollector;
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
|
||||
use Illuminate\Filesystem\FilesystemAdapter;
|
||||
use Illuminate\Support\Collection;
|
||||
use Storage;
|
||||
@@ -93,9 +95,9 @@ class Processor
|
||||
*/
|
||||
public function collectJournals(): bool
|
||||
{
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$this->journals = $repository->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
|
||||
/** @var JournalTaskerInterface $tasker */
|
||||
$tasker = app(JournalTaskerInterface::class);
|
||||
$this->journals = $tasker->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* AccountChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
@@ -22,7 +24,6 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface AccountChartGeneratorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
@@ -41,6 +42,15 @@ interface AccountChartGeneratorInterface
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function revenueAccounts(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $labels
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsAccountChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
@@ -81,6 +83,30 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function revenueAccounts(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [], 'datasets' => [[
|
||||
'label' => trans('firefly.earned'),
|
||||
'data' => []]]];
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->difference > 0) {
|
||||
$data['labels'][] = $account->name;
|
||||
$data['datasets'][0]['data'][] = $account->difference;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $labels
|
||||
@@ -103,5 +129,4 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BillChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsBillChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsBudgetChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* CategoryChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsCategoryChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsPiggyBankChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* PiggyBankChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsReportChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ReportChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AttachUserRole.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class AttachUserRole
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class AttachUserRole
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*/
|
||||
public function handle(UserRegistration $event)
|
||||
{
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
|
||||
// first user ever?
|
||||
if ($repository->count() == 1) {
|
||||
$repository->attachRole($event->user, 'owner');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,46 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitEventHandler.php
|
||||
* BudgetEventHandler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\BudgetLimitStored;
|
||||
use FireflyIII\Events\BudgetLimitUpdated;
|
||||
|
||||
use FireflyIII\Events\StoredBudgetLimit;
|
||||
use FireflyIII\Events\UpdatedBudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitEventHandler
|
||||
* Handles budget related events.
|
||||
*
|
||||
* Class BudgetEventHandler
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class BudgetLimitEventHandler
|
||||
class BudgetEventHandler
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
* This method creates a new budget limit repetition when a new budget limit has been created.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In a perfect world, the store() routine should be different from the update()
|
||||
* routine. It would not have to check count() == 0 because there could be NO
|
||||
* limit repetitions at this point. However, the database can be wrong so we check.
|
||||
* @param StoredBudgetLimit $event
|
||||
*
|
||||
* @param BudgetLimitStored $event
|
||||
* @return bool
|
||||
*/
|
||||
public function store(BudgetLimitStored $event)
|
||||
public function storeRepetition(StoredBudgetLimit $event):bool
|
||||
{
|
||||
$budgetLimit = $event->budgetLimit;
|
||||
$end = $event->end;
|
||||
@@ -69,12 +65,18 @@ class BudgetLimitEventHandler
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param BudgetLimitUpdated $event
|
||||
* Updates, if present the budget limit repetition part of a budget limit.
|
||||
*
|
||||
* @param UpdatedBudgetLimit $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update(BudgetLimitUpdated $event)
|
||||
public function update(UpdatedBudgetLimit $event): bool
|
||||
{
|
||||
$budgetLimit = $event->budgetLimit;
|
||||
$end = $event->end;
|
||||
@@ -102,6 +104,7 @@ class BudgetLimitEventHandler
|
||||
$repetition->save();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ConnectJournalToPiggyBank.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
||||
/**
|
||||
* Class ConnectJournalToPiggyBank
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class ConnectJournalToPiggyBank
|
||||
{
|
||||
|
||||
/**
|
||||
* Connect a new transaction journal to any related piggy banks.
|
||||
*
|
||||
* @param TransactionJournalStored $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionJournalStored $event): bool
|
||||
{
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->journal;
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
|
||||
if (is_null($piggyBank)) {
|
||||
return true;
|
||||
}
|
||||
// update piggy bank rep for date of transaction journal.
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
if (is_null($repetition)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$amount = TransactionJournal::amountPositive($journal);
|
||||
// if piggy account matches source account, the amount is positive
|
||||
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
|
||||
if (in_array($piggyBank->account_id, $sources)) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ConnectTransactionToPiggyBank.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\TransactionStored;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class ConnectTransactionToPiggyBank
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class ConnectTransactionToPiggyBank
|
||||
{
|
||||
|
||||
/**
|
||||
* Connect a new transaction journal to any related piggy banks.
|
||||
*
|
||||
* @param TransactionStored $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionStored $event): bool
|
||||
{
|
||||
|
||||
/** @var PiggyBankRepositoryInterface $repository */
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$transaction = $event->transaction;
|
||||
|
||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
||||
|
||||
// valid piggy:
|
||||
if (is_null($piggyBank->id)) {
|
||||
return true;
|
||||
}
|
||||
$amount = strval($transaction['amount']);
|
||||
// piggy bank account something with amount:
|
||||
if ($transaction['source_account_id'] == $piggyBank->account_id) {
|
||||
// if the source of this transaction is the same as the piggy bank,
|
||||
// the money is being removed from the piggy bank. So the
|
||||
// amount must be negative:
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
// add or remove the money from the piggy bank:
|
||||
$newAmount = bcadd(strval($repetition->currentamount), $amount);
|
||||
$repetition->currentamount = $newAmount;
|
||||
$repetition->save();
|
||||
|
||||
// now generate a piggy bank event:
|
||||
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'date' => $transaction['date'], 'amount' => $newAmount]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* FireRulesForStore.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class FireRulesForStore
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class FireRulesForStore
|
||||
{
|
||||
|
||||
/**
|
||||
* Connect a new transaction journal to any related piggy banks.
|
||||
*
|
||||
* @param TransactionJournalStored $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionJournalStored $event): bool
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
$rules = $group->rules()
|
||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||
->where('rule_triggers.trigger_type', 'user_action')
|
||||
->where('rule_triggers.trigger_value', 'store-journal')
|
||||
->where('rules.active', 1)
|
||||
->get(['rules.*']);
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
|
||||
$processor = Processor::make($rule);
|
||||
$processor->handleTransactionJournal($event->journal);
|
||||
|
||||
if ($rule->stop_processing) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* FireRulesForUpdate.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\TransactionJournalUpdated;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\User;
|
||||
|
||||
/**
|
||||
* Class FireRulesForUpdate
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class FireRulesForUpdate
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param TransactionJournalUpdated $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionJournalUpdated $event): bool
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
$rules = $group->rules()
|
||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||
->where('rule_triggers.trigger_type', 'user_action')
|
||||
->where('rule_triggers.trigger_value', 'update-journal')
|
||||
->where('rules.active', 1)
|
||||
->get(['rules.*']);
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$processor = Processor::make($rule);
|
||||
$processor->handleTransactionJournal($event->journal);
|
||||
|
||||
if ($rule->stop_processing) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ScanForBillsAfterStore.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Support\Events\BillScanner;
|
||||
|
||||
/**
|
||||
* Class RescanJournal
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class ScanForBillsAfterStore
|
||||
{
|
||||
|
||||
/**
|
||||
* Scan a transaction journal for possible links to bills, right after storing.
|
||||
*
|
||||
* @param TransactionJournalStored $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionJournalStored $event): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
BillScanner::scan($journal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ScanForBillsAfterUpdate.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\TransactionJournalUpdated;
|
||||
use FireflyIII\Support\Events\BillScanner;
|
||||
|
||||
/**
|
||||
* Class RescanJournal
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class ScanForBillsAfterUpdate
|
||||
{
|
||||
/**
|
||||
* Scan a transaction journal for possibly related bills after it has been updated.
|
||||
*
|
||||
* @param TransactionJournalUpdated $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionJournalUpdated $event): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
BillScanner::scan($journal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* SendRegistrationMail.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use Illuminate\Mail\Message;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Swift_TransportException;
|
||||
|
||||
/**
|
||||
* Class SendRegistrationMail
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class SendRegistrationMail
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(UserRegistration $event): bool
|
||||
{
|
||||
$sendMail = env('SEND_REGISTRATION_MAIL', true);
|
||||
if (!$sendMail) {
|
||||
return true;
|
||||
}
|
||||
// get the email address
|
||||
$email = $event->user->email;
|
||||
$address = route('index');
|
||||
$ipAddress = $event->ipAddress;
|
||||
// send email.
|
||||
try {
|
||||
Mail::send(
|
||||
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
|
||||
$message->to($email, $email)->subject('Welcome to Firefly III! ');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
124
app/Handlers/Events/StoredJournalEventHandler.php
Normal file
124
app/Handlers/Events/StoredJournalEventHandler.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* StoredJournalEventHandler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\StoredTransactionJournal;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\Support\Events\BillScanner;
|
||||
|
||||
/**
|
||||
* Class StoredJournalEventHandler
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class StoredJournalEventHandler
|
||||
{
|
||||
/**
|
||||
* This method connects a new transfer to a piggy bank.
|
||||
*
|
||||
* @param StoredTransactionJournal $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connectToPiggyBank(StoredTransactionJournal $event): bool
|
||||
{
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->journal;
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = $journal->user()->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
|
||||
if (is_null($piggyBank)) {
|
||||
return true;
|
||||
}
|
||||
// update piggy bank rep for date of transaction journal.
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
if (is_null($repetition)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$amount = TransactionJournal::amountPositive($journal);
|
||||
// if piggy account matches source account, the amount is positive
|
||||
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
|
||||
if (in_array($piggyBank->account_id, $sources)) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method grabs all the users rules and processes them.
|
||||
*
|
||||
* @param StoredTransactionJournal $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function processRules(StoredTransactionJournal $event): bool
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
$journal = $event->journal;
|
||||
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
$rules = $group->rules()
|
||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||
->where('rule_triggers.trigger_type', 'user_action')
|
||||
->where('rule_triggers.trigger_value', 'store-journal')
|
||||
->where('rules.active', 1)
|
||||
->get(['rules.*']);
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
|
||||
$processor = Processor::make($rule);
|
||||
$processor->handleTransactionJournal($journal);
|
||||
|
||||
if ($rule->stop_processing) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls a special bill scanner that will check if the stored journal is part of a bill.
|
||||
*
|
||||
* @param StoredTransactionJournal $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function scanBills(StoredTransactionJournal $event): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
BillScanner::scan($journal);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* UpdateJournalConnection.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\TransactionJournalUpdated;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
||||
/**
|
||||
* Class UpdateJournalConnection
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UpdateJournalConnection
|
||||
{
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param TransactionJournalUpdated $event
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionJournalUpdated $event):bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
|
||||
if (!$journal->isTransfer()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the event connected to this journal:
|
||||
/** @var PiggyBankEvent $event */
|
||||
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
|
||||
if (is_null($event)) {
|
||||
return false;
|
||||
}
|
||||
$piggyBank = $event->piggyBank()->first();
|
||||
$repetition = null;
|
||||
if (!is_null($piggyBank)) {
|
||||
/** @var PiggyBankRepetition $repetition */
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
}
|
||||
|
||||
if (is_null($repetition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$amount = TransactionJournal::amount($journal);
|
||||
$diff = bcsub($amount, $event->amount); // update current repetition
|
||||
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
|
||||
$repetition->save();
|
||||
|
||||
|
||||
$event->amount = $amount;
|
||||
$event->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
128
app/Handlers/Events/UpdatedJournalEventHandler.php
Normal file
128
app/Handlers/Events/UpdatedJournalEventHandler.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* UpdatedJournalEventHandler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use FireflyIII\Events\UpdatedTransactionJournal;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\Support\Events\BillScanner;
|
||||
|
||||
/**
|
||||
* Class UpdatedJournalEventHandler
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UpdatedJournalEventHandler
|
||||
{
|
||||
/**
|
||||
* This method will try to reconnect a journal to a piggy bank, updating the piggy bank repetition.
|
||||
*
|
||||
* @param UpdatedTransactionJournal $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connectToPiggyBank(UpdatedTransactionJournal $event): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
|
||||
if (!$journal->isTransfer()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the event connected to this journal:
|
||||
/** @var PiggyBankEvent $event */
|
||||
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
|
||||
if (is_null($event)) {
|
||||
return false;
|
||||
}
|
||||
$piggyBank = $event->piggyBank()->first();
|
||||
$repetition = null;
|
||||
if (!is_null($piggyBank)) {
|
||||
/** @var PiggyBankRepetition $repetition */
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
}
|
||||
|
||||
if (is_null($repetition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$amount = TransactionJournal::amount($journal);
|
||||
$diff = bcsub($amount, $event->amount); // update current repetition
|
||||
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
|
||||
$repetition->save();
|
||||
|
||||
|
||||
$event->amount = $amount;
|
||||
$event->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will check all the rules when a journal is updated.
|
||||
*
|
||||
* @param UpdatedTransactionJournal $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function processRules(UpdatedTransactionJournal $event):bool
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
$journal = $event->journal;
|
||||
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
$rules = $group->rules()
|
||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||
->where('rule_triggers.trigger_type', 'user_action')
|
||||
->where('rule_triggers.trigger_value', 'update-journal')
|
||||
->where('rules.active', 1)
|
||||
->get(['rules.*']);
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$processor = Processor::make($rule);
|
||||
$processor->handleTransactionJournal($journal);
|
||||
|
||||
if ($rule->stop_processing) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls a special bill scanner that will check if the updated journal is part of a bill.
|
||||
*
|
||||
* @param UpdatedTransactionJournal $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function scanBills(UpdatedTransactionJournal $event): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
BillScanner::scan($journal);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* UserConfirmation.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\ResendConfirmation;
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Mail\Message;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Preferences;
|
||||
use Swift_TransportException;
|
||||
|
||||
/**
|
||||
* Class UserConfirmation
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UserConfirmation
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ResendConfirmation $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function resendConfirmation(ResendConfirmation $event): bool
|
||||
{
|
||||
$user = $event->user;
|
||||
$ipAddress = $event->ipAddress;
|
||||
$this->doConfirm($user, $ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sendConfirmation(UserRegistration $event): bool
|
||||
{
|
||||
$user = $event->user;
|
||||
$ipAddress = $event->ipAddress;
|
||||
$this->doConfirm($user, $ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
private function doConfirm(User $user, string $ipAddress)
|
||||
{
|
||||
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
||||
if ($confirmAccount === false) {
|
||||
Preferences::setForUser($user, 'user_confirmed', true);
|
||||
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
|
||||
Preferences::mark();
|
||||
|
||||
return;
|
||||
}
|
||||
$email = $user->email;
|
||||
$code = str_random(16);
|
||||
$route = route('do_confirm_account', [$code]);
|
||||
Preferences::setForUser($user, 'user_confirmed', false);
|
||||
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
|
||||
Preferences::setForUser($user, 'user_confirmed_code', $code);
|
||||
try {
|
||||
Mail::send(
|
||||
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
|
||||
function (Message $message) use ($email) {
|
||||
$message->to($email, $email)->subject('Please confirm your Firefly III account');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
225
app/Handlers/Events/UserEventHandler.php
Normal file
225
app/Handlers/Events/UserEventHandler.php
Normal file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
/**
|
||||
* UserEventHandler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\ConfirmedUser;
|
||||
use FireflyIII\Events\RegisteredUser;
|
||||
use FireflyIII\Events\ResentConfirmation;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Mail\Message;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use Swift_TransportException;
|
||||
|
||||
/**
|
||||
* Class UserEventHandler
|
||||
*
|
||||
* This class responds to any events that have anything to do with the User object.
|
||||
*
|
||||
* The method name reflects what is being done. This is in the present tense.
|
||||
*
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UserEventHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* This method will bestow upon a user the "owner" role if he is the first user in the system.
|
||||
*
|
||||
* @param RegisteredUser $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function attachUserRole(RegisteredUser $event): bool
|
||||
{
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
|
||||
// first user ever?
|
||||
if ($repository->count() === 1) {
|
||||
$repository->attachRole($event->user, 'owner');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle user logout events.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onUserLogout(): bool
|
||||
{
|
||||
// dump stuff from the session:
|
||||
Session::forget('twofactor-authenticated');
|
||||
Session::forget('twofactor-authenticated-date');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will send a newly registered user a confirmation message, urging him or her to activate their account.
|
||||
*
|
||||
* @param RegisteredUser $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sendConfirmationMessage(RegisteredUser $event): bool
|
||||
{
|
||||
$user = $event->user;
|
||||
$ipAddress = $event->ipAddress;
|
||||
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
||||
if ($confirmAccount === false) {
|
||||
Preferences::setForUser($user, 'user_confirmed', true);
|
||||
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
|
||||
Preferences::mark();
|
||||
|
||||
return true;
|
||||
}
|
||||
$email = $user->email;
|
||||
$code = str_random(16);
|
||||
$route = route('do_confirm_account', [$code]);
|
||||
Preferences::setForUser($user, 'user_confirmed', false);
|
||||
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
|
||||
Preferences::setForUser($user, 'user_confirmed_code', $code);
|
||||
try {
|
||||
Mail::send(
|
||||
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
|
||||
function (Message $message) use ($email) {
|
||||
$message->to($email, $email)->subject('Please confirm your Firefly III account');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user has somehow lost his or her confirmation message, this event will send it to the user again.
|
||||
*
|
||||
* At the moment, this method is exactly the same as the ::sendConfirmationMessage method, but that will change.
|
||||
*
|
||||
* @param ResentConfirmation $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function sendConfirmationMessageAgain(ResentConfirmation $event): bool
|
||||
{
|
||||
$user = $event->user;
|
||||
$ipAddress = $event->ipAddress;
|
||||
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
||||
if ($confirmAccount === false) {
|
||||
Preferences::setForUser($user, 'user_confirmed', true);
|
||||
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
|
||||
Preferences::mark();
|
||||
|
||||
return true;
|
||||
}
|
||||
$email = $user->email;
|
||||
$code = str_random(16);
|
||||
$route = route('do_confirm_account', [$code]);
|
||||
Preferences::setForUser($user, 'user_confirmed', false);
|
||||
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
|
||||
Preferences::setForUser($user, 'user_confirmed_code', $code);
|
||||
try {
|
||||
Mail::send(
|
||||
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
|
||||
function (Message $message) use ($email) {
|
||||
$message->to($email, $email)->subject('Please confirm your Firefly III account');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will send the user a registration mail, welcoming him or her to Firefly III.
|
||||
* This message is only sent when the configuration of Firefly III says so.
|
||||
*
|
||||
* @param RegisteredUser $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sendRegistrationMail(RegisteredUser $event)
|
||||
{
|
||||
|
||||
$sendMail = env('SEND_REGISTRATION_MAIL', true);
|
||||
if (!$sendMail) {
|
||||
return true;
|
||||
}
|
||||
// get the email address
|
||||
$email = $event->user->email;
|
||||
$address = route('index');
|
||||
$ipAddress = $event->ipAddress;
|
||||
// send email.
|
||||
try {
|
||||
Mail::send(
|
||||
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
|
||||
$message->to($email, $email)->subject('Welcome to Firefly III! ');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the user is confirmed, this method stores the IP address of the user
|
||||
* as a preference. Since this preference cannot be edited, it is effectively hidden
|
||||
* from the user yet stored conveniently.
|
||||
*
|
||||
* @param ConfirmedUser $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function storeConfirmationIpAddress(ConfirmedUser $event): bool
|
||||
{
|
||||
Preferences::setForUser($event->user, 'confirmation_ip_address', $event->ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This message stores the users IP address on registration, in much the same
|
||||
* fashion as the previous method.
|
||||
*
|
||||
* @param RegisteredUser $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function storeRegistrationIpAddress(RegisteredUser $event): bool
|
||||
{
|
||||
Preferences::setForUser($event->user, 'registration_ip_address', $event->ipAddress);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* UserEventListener.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class UserEventListener
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UserEventListener
|
||||
{
|
||||
/**
|
||||
* Handle user logout events.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onUserLogout(): bool
|
||||
{
|
||||
// dump stuff from the session:
|
||||
Session::forget('twofactor-authenticated');
|
||||
Session::forget('twofactor-authenticated-date');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* UserSaveIpAddress.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\UserIsConfirmed;
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\User;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class UserSaveIpAddress
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UserSaveIpAddress
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveFromRegistration(UserRegistration $event): bool
|
||||
{
|
||||
Preferences::setForUser($event->user, 'registration_ip_address', $event->ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserIsConfirmed $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveFromConfirmation(UserIsConfirmed $event): bool
|
||||
{
|
||||
Preferences::setForUser($event->user, 'confirmation_ip_address', $event->ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -3,14 +3,15 @@
|
||||
* AttachmentHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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\Attachments;
|
||||
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -60,7 +61,7 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
*/
|
||||
public function getAttachmentLocation(Attachment $attachment): string
|
||||
{
|
||||
$path = storage_path('upload') . DIRECTORY_SEPARATOR . 'at-' . $attachment->id . '.data';
|
||||
$path = sprintf('%s%sat-%d.data', storage_path('upload'), DIRECTORY_SEPARATOR, intval($attachment->id));
|
||||
|
||||
return $path;
|
||||
}
|
||||
@@ -112,7 +113,7 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
$name = $file->getClientOriginalName();
|
||||
$class = get_class($model);
|
||||
$count = Auth::user()->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count();
|
||||
$count = auth()->user()->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count();
|
||||
|
||||
if ($count > 0) {
|
||||
$msg = (string)trans('validation.file_already_attached', ['name' => $name]);
|
||||
@@ -139,7 +140,7 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
}
|
||||
|
||||
$attachment = new Attachment; // create Attachment object.
|
||||
$attachment->user()->associate(Auth::user());
|
||||
$attachment->user()->associate(auth()->user());
|
||||
$attachment->attachable()->associate($model);
|
||||
$attachment->md5 = md5_file($file->getRealPath());
|
||||
$attachment->filename = $file->getClientOriginalName();
|
||||
@@ -250,6 +251,8 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
/**
|
||||
* @param array $files
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function processFiles(array $files, Model $model): bool
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* AttachmentHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Account.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Balance.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceEntry.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceHeader.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceLine.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
@@ -32,14 +34,12 @@ class BalanceLine
|
||||
|
||||
/** @var BudgetModel */
|
||||
protected $budget;
|
||||
|
||||
/** @var Carbon */
|
||||
protected $startDate;
|
||||
/** @var Carbon */
|
||||
protected $endDate;
|
||||
|
||||
/** @var int */
|
||||
protected $role = self::ROLE_DEFAULTROLE;
|
||||
/** @var Carbon */
|
||||
protected $startDate;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -90,6 +90,22 @@ class BalanceLine
|
||||
$this->budget = $budget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getEndDate()
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $endDate
|
||||
*/
|
||||
public function setEndDate($endDate)
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@@ -106,6 +122,22 @@ class BalanceLine
|
||||
$this->role = $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getStartDate()
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $startDate
|
||||
*/
|
||||
public function setStartDate($startDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@@ -127,39 +159,6 @@ class BalanceLine
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getStartDate()
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $startDate
|
||||
*/
|
||||
public function setStartDate($startDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getEndDate()
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $endDate
|
||||
*/
|
||||
public function setEndDate($endDate)
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine
|
||||
* should have a "spent" value, which is the amount of money that has been spent
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Bill.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BillLine.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Budget.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
@@ -47,6 +49,7 @@ class Budget
|
||||
public function addBudgetLine(BudgetLine $budgetLine): Budget
|
||||
{
|
||||
$this->budgetLines->push($budgetLine);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -59,6 +62,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->budgeted = bcadd($this->budgeted, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -71,6 +75,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->left = bcadd($this->left, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -83,6 +88,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->overspent = bcadd($this->overspent, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -95,6 +101,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->spent = bcadd($this->spent, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetLine.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
@@ -51,6 +53,7 @@ class BudgetLine
|
||||
public function setBudget(BudgetModel $budget): BudgetLine
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -70,6 +73,7 @@ class BudgetLine
|
||||
public function setBudgeted(string $budgeted): BudgetLine
|
||||
{
|
||||
$this->budgeted = $budgeted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -89,6 +93,7 @@ class BudgetLine
|
||||
public function setLeft(string $left): BudgetLine
|
||||
{
|
||||
$this->left = $left;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -108,6 +113,7 @@ class BudgetLine
|
||||
public function setOverspent(string $overspent): BudgetLine
|
||||
{
|
||||
$this->overspent = $overspent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -127,6 +133,7 @@ class BudgetLine
|
||||
public function setRepetition(LimitRepetition $repetition): BudgetLine
|
||||
{
|
||||
$this->repetition = $repetition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -146,6 +153,7 @@ class BudgetLine
|
||||
public function setSpent(string $spent): BudgetLine
|
||||
{
|
||||
$this->spent = $spent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Category.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
|
@@ -3,14 +3,15 @@
|
||||
* Expense.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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\Collection;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
@@ -36,36 +37,11 @@ class Expense
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $entry
|
||||
* @param stdClass $entry
|
||||
*/
|
||||
public function addOrCreateExpense(TransactionJournal $entry)
|
||||
public function addOrCreateExpense(stdClass $entry)
|
||||
{
|
||||
// add each account individually:
|
||||
$destinations = TransactionJournal::destinationTransactionList($entry);
|
||||
|
||||
foreach ($destinations as $transaction) {
|
||||
$amount = strval($transaction->amount);
|
||||
$account = $transaction->account;
|
||||
if (bccomp('0', $amount) === -1) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
$object = new stdClass;
|
||||
$object->amount = $amount;
|
||||
$object->name = $account->name;
|
||||
$object->count = 1;
|
||||
$object->id = $account->id;
|
||||
|
||||
// overrule some properties:
|
||||
if ($this->expenses->has($account->id)) {
|
||||
$object = $this->expenses->get($account->id);
|
||||
$object->amount = bcadd($object->amount, $amount);
|
||||
$object->count++;
|
||||
}
|
||||
$this->expenses->put($account->id, $object);
|
||||
}
|
||||
|
||||
|
||||
$this->expenses->put($entry->id, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,14 +3,15 @@
|
||||
* Income.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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\Collection;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
@@ -37,32 +38,11 @@ class Income
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $entry
|
||||
* @param stdClass $entry
|
||||
*/
|
||||
public function addOrCreateIncome(TransactionJournal $entry)
|
||||
public function addOrCreateIncome(stdClass $entry)
|
||||
{
|
||||
// add each account individually:
|
||||
$sources = TransactionJournal::sourceTransactionList($entry);
|
||||
|
||||
foreach ($sources as $transaction) {
|
||||
$amount = strval($transaction->amount);
|
||||
$account = $transaction->account;
|
||||
$amount = bcmul($amount, '-1');
|
||||
|
||||
$object = new stdClass;
|
||||
$object->amount = $amount;
|
||||
$object->name = $account->name;
|
||||
$object->count = 1;
|
||||
$object->id = $account->id;
|
||||
|
||||
// overrule some properties:
|
||||
if ($this->incomes->has($account->id)) {
|
||||
$object = $this->incomes->get($account->id);
|
||||
$object->amount = bcadd($object->amount, $amount);
|
||||
$object->count++;
|
||||
}
|
||||
$this->incomes->put($account->id, $object);
|
||||
}
|
||||
$this->incomes->put($entry->id, $entry);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,385 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Importer.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Converter\ConverterInterface;
|
||||
use FireflyIII\Helpers\Csv\PostProcessing\PostProcessorInterface;
|
||||
use FireflyIII\Helpers\Csv\Specifix\SpecifixInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Importer
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Importer
|
||||
{
|
||||
|
||||
/** @var Data */
|
||||
protected $data;
|
||||
/** @var array */
|
||||
protected $errors = [];
|
||||
/** @var array */
|
||||
protected $importData;
|
||||
/** @var array */
|
||||
protected $importRow;
|
||||
/** @var int */
|
||||
protected $imported = 0;
|
||||
/** @var Collection */
|
||||
protected $journals;
|
||||
/** @var array */
|
||||
protected $map;
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
/** @var array */
|
||||
protected $roles;
|
||||
/** @var int */
|
||||
protected $rows = 0;
|
||||
/** @var array */
|
||||
protected $specifix = [];
|
||||
|
||||
/**
|
||||
* Used by CsvController.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors(): array
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by CsvController
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImported(): int
|
||||
{
|
||||
return $this->imported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals(): Collection
|
||||
{
|
||||
return $this->journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by CsvController
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRows(): int
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSpecifix(): array
|
||||
{
|
||||
return is_array($this->specifix) ? $this->specifix : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
$this->journals = new Collection;
|
||||
$this->map = $this->data->getMap();
|
||||
$this->roles = $this->data->getRoles();
|
||||
$this->mapped = $this->data->getMapped();
|
||||
$this->specifix = $this->data->getSpecifix();
|
||||
|
||||
foreach ($this->data->getReader() as $index => $row) {
|
||||
if ($this->parseRow($index)) {
|
||||
$this->rows++;
|
||||
$result = $this->importRow($row);
|
||||
if (!($result instanceof TransactionJournal)) {
|
||||
Log::error('Caught error at row #' . $index . ': ' . $result);
|
||||
$this->errors[$index] = $result;
|
||||
} else {
|
||||
$this->imported++;
|
||||
$this->journals->push($result);
|
||||
event(new TransactionJournalStored($result, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Data $data
|
||||
*/
|
||||
public function setData(Data $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TransactionJournal|string
|
||||
*/
|
||||
protected function createTransactionJournal()
|
||||
{
|
||||
$date = $this->importData['date'];
|
||||
if (is_null($this->importData['date'])) {
|
||||
$date = $this->importData['date-rent'];
|
||||
}
|
||||
|
||||
|
||||
$transactionType = $this->getTransactionType(); // defaults to deposit
|
||||
$errors = new MessageBag;
|
||||
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'transaction_type_id' => $transactionType->id,
|
||||
'transaction_currency_id' => $this->importData['currency']->id,
|
||||
'description' => $this->importData['description'],
|
||||
'completed' => 0,
|
||||
'date' => $date,
|
||||
'bill_id' => $this->importData['bill-id'],
|
||||
]
|
||||
);
|
||||
if ($journal->getErrors()->count() == 0) {
|
||||
// first transaction
|
||||
$accountId = $this->importData['asset-account-object']->id; // create first transaction:
|
||||
$amount = $this->importData['amount'];
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors();
|
||||
|
||||
// second transaction
|
||||
$accountId = $this->importData['opposing-account-object']->id; // create second transaction:
|
||||
$amount = bcmul($this->importData['amount'], '-1');
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors()->merge($errors);
|
||||
}
|
||||
if ($errors->count() == 0) {
|
||||
$journal->completed = 1;
|
||||
$journal->save();
|
||||
} else {
|
||||
$text = join(',', $errors->all());
|
||||
|
||||
return $text;
|
||||
}
|
||||
$this->saveBudget($journal);
|
||||
$this->saveCategory($journal);
|
||||
$this->saveTags($journal);
|
||||
|
||||
// some debug info:
|
||||
$journalId = $journal->id;
|
||||
$type = $journal->transaction_type_type ?? $journal->transactionType->type;
|
||||
/** @var Account $asset */
|
||||
$asset = $this->importData['asset-account-object'];
|
||||
/** @var Account $opposing */
|
||||
$opposing = $this->importData['opposing-account-object'];
|
||||
|
||||
Log::info('Created journal #' . $journalId . ' of type ' . $type . '!');
|
||||
Log::info('Asset account #' . $asset->id . ' lost/gained: ' . $this->importData['amount']);
|
||||
Log::info($opposing->accountType->type . ' #' . $opposing->id . ' lost/gained: ' . bcmul($this->importData['amount'], '-1'));
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TransactionType
|
||||
*/
|
||||
protected function getTransactionType()
|
||||
{
|
||||
$transactionType = TransactionType::where('type', TransactionType::DEPOSIT)->first();
|
||||
if ($this->importData['amount'] < 0) {
|
||||
$transactionType = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
}
|
||||
|
||||
if (in_array($this->importData['opposing-account-object']->accountType->type, ['Asset account', 'Default account'])) {
|
||||
$transactionType = TransactionType::where('type', TransactionType::TRANSFER)->first();
|
||||
}
|
||||
|
||||
return $transactionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function importRow(array $row)
|
||||
{
|
||||
|
||||
$data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional
|
||||
foreach ($row as $index => $value) {
|
||||
$role = $this->roles[$index] ?? '_ignore';
|
||||
$class = config('csv.roles.' . $role . '.converter');
|
||||
$field = config('csv.roles.' . $role . '.field');
|
||||
|
||||
|
||||
// here would be the place where preprocessors would fire.
|
||||
|
||||
/** @var ConverterInterface $converter */
|
||||
$converter = app('FireflyIII\Helpers\Csv\Converter\\' . $class);
|
||||
$converter->setData($data); // the complete array so far.
|
||||
$converter->setField($field);
|
||||
$converter->setIndex($index);
|
||||
$converter->setMapped($this->mapped);
|
||||
$converter->setValue($value);
|
||||
$data[$field] = $converter->convert();
|
||||
}
|
||||
// move to class vars.
|
||||
$this->importData = $data;
|
||||
$this->importRow = $row;
|
||||
unset($data, $row);
|
||||
// post processing and validating.
|
||||
$this->postProcess();
|
||||
$result = $this->validateData();
|
||||
|
||||
if (!($result === true)) {
|
||||
return $result; // return error.
|
||||
}
|
||||
$journal = $this->createTransactionJournal();
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseRow(int $index)
|
||||
{
|
||||
return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* Row denotes the original data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function postProcess()
|
||||
{
|
||||
// do bank specific fixes (must be enabled but now all of them.
|
||||
|
||||
foreach ($this->getSpecifix() as $className) {
|
||||
/** @var SpecifixInterface $specifix */
|
||||
$specifix = app('FireflyIII\Helpers\Csv\Specifix\\' . $className);
|
||||
if ($specifix->getProcessorType() == SpecifixInterface::POST_PROCESSOR) {
|
||||
$specifix->setData($this->importData);
|
||||
$specifix->setRow($this->importRow);
|
||||
$this->importData = $specifix->fix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$set = config('csv.post_processors');
|
||||
foreach ($set as $className) {
|
||||
/** @var PostProcessorInterface $postProcessor */
|
||||
$postProcessor = app('FireflyIII\Helpers\Csv\PostProcessing\\' . $className);
|
||||
$array = $this->importData ?? [];
|
||||
$postProcessor->setData($array);
|
||||
$this->importData = $postProcessor->process();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveBudget(TransactionJournal $journal)
|
||||
{
|
||||
// add budget:
|
||||
if (!is_null($this->importData['budget'])) {
|
||||
$journal->budgets()->save($this->importData['budget']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveCategory(TransactionJournal $journal)
|
||||
{
|
||||
// add category:
|
||||
if (!is_null($this->importData['category'])) {
|
||||
$journal->categories()->save($this->importData['category']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveTags(TransactionJournal $journal)
|
||||
{
|
||||
if (!is_null($this->importData['tags'])) {
|
||||
foreach ($this->importData['tags'] as $tag) {
|
||||
$journal->tags()->save($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function validateData()
|
||||
{
|
||||
$date = $this->importData['date'] ?? null;
|
||||
$rentDate = $this->importData['date-rent'] ?? null;
|
||||
if (is_null($date) && is_null($rentDate)) {
|
||||
return 'No date value for this row.';
|
||||
}
|
||||
if (is_null($this->importData['opposing-account-object'])) {
|
||||
return 'Opposing account is null';
|
||||
}
|
||||
|
||||
if (!($this->importData['asset-account-object'] instanceof Account)) {
|
||||
return 'No asset account to import into.';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getFiller()
|
||||
{
|
||||
$filler = [];
|
||||
foreach (config('csv.roles') as $role) {
|
||||
if (isset($role['field'])) {
|
||||
$fieldName = $role['field'];
|
||||
$filler[$fieldName] = null;
|
||||
}
|
||||
}
|
||||
// some extra's:
|
||||
$filler['bill-id'] = null;
|
||||
$filler['opposing-account-object'] = null;
|
||||
$filler['asset-account-object'] = null;
|
||||
$filler['amount-modifier'] = '1';
|
||||
|
||||
return $filler;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
* FiscalHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* FiscalHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Help.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* HelpInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -1,142 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AccountReportHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Class AccountReportHelper
|
||||
*
|
||||
* @package FireflyIII\Helpers\Report
|
||||
*/
|
||||
class AccountReportHelper implements AccountReportHelperInterface
|
||||
{
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Collection $startSet
|
||||
* @param Collection $endSet
|
||||
* @param Collection $backupSet
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public static function reportFilter(Account $account, Collection $startSet, Collection $endSet, Collection $backupSet)
|
||||
{
|
||||
// The balance for today always incorporates transactions made on today. So to get todays "start" balance, we sub one day.
|
||||
$account->startBalance = '0';
|
||||
$account->endBalance = '0';
|
||||
$currentStart = $startSet->filter(
|
||||
function (Account $entry) use ($account) {
|
||||
return $account->id == $entry->id;
|
||||
}
|
||||
);
|
||||
|
||||
$currentBackup = $backupSet->filter( // grab entry from current backup as well:
|
||||
function (Account $entry) use ($account) {
|
||||
return $account->id == $entry->id;
|
||||
}
|
||||
);
|
||||
|
||||
// first try to set from backup
|
||||
if (!is_null($currentBackup->first())) {
|
||||
$account->startBalance = $currentBackup->first()->balance;
|
||||
}
|
||||
|
||||
// overrule with data from start
|
||||
if (!is_null($currentStart->first())) {
|
||||
$account->startBalance = $currentStart->first()->balance;
|
||||
}
|
||||
|
||||
$currentEnd = $endSet->filter(
|
||||
function (Account $entry) use ($account) {
|
||||
return $account->id == $entry->id;
|
||||
}
|
||||
);
|
||||
|
||||
if (!is_null($currentEnd->first())) {
|
||||
$account->endBalance = $currentEnd->first()->balance;
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method generates a full report for the given period on all
|
||||
* given accounts.
|
||||
*
|
||||
* a special consideration for accounts that did exist on this exact day.
|
||||
* we also grab the balance from today just in case, to see if that changes things.
|
||||
* it's a fall back for users who (rightly so) start keeping score at the first of
|
||||
* the month and find the first report lacking / broken.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return AccountCollection
|
||||
*/
|
||||
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection
|
||||
{
|
||||
$startAmount = '0';
|
||||
$endAmount = '0';
|
||||
$diff = '0';
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
$yesterday = clone $start;
|
||||
$yesterday->subDay();
|
||||
$startSet = $this->getSet($ids, $yesterday); // get balances for start.
|
||||
$backupSet = $this->getSet($ids, $start);
|
||||
$endSet = $this->getSet($ids, $end);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($startSet, $endSet, $backupSet) {
|
||||
return self::reportFilter($account, $startSet, $endSet, $backupSet);
|
||||
}
|
||||
);
|
||||
|
||||
// summarize:
|
||||
foreach ($accounts as $account) {
|
||||
$startAmount = bcadd($startAmount, $account->startBalance);
|
||||
$endAmount = bcadd($endAmount, $account->endBalance);
|
||||
$diff = bcadd($diff, bcsub($account->endBalance, $account->startBalance));
|
||||
}
|
||||
|
||||
$object = new AccountCollection;
|
||||
$object->setStart($startAmount);
|
||||
$object->setEnd($endAmount);
|
||||
$object->setDifference($diff);
|
||||
$object->setAccounts($accounts);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ids
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getSet(array $ids, Carbon $date): Collection
|
||||
{
|
||||
return Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereIn('accounts.id', $ids)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
|
||||
->groupBy('accounts.id')
|
||||
->get(['accounts.id', DB::raw('SUM(`transactions`.`amount`) as `balance`')]);
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AccountReportHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Interface AccountReportHelperInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Report
|
||||
*/
|
||||
interface AccountReportHelperInterface
|
||||
{
|
||||
/**
|
||||
* This method generates a full report for the given period on all
|
||||
* given accounts
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return AccountCollection
|
||||
*/
|
||||
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection;
|
||||
|
||||
}
|
@@ -3,15 +3,16 @@
|
||||
* BalanceReportHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Helpers\Collection\Balance;
|
||||
@@ -102,34 +103,34 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
private function allCoveredByBalancingActs(Collection $accounts, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
$set = Auth::user()->tags()
|
||||
->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id')
|
||||
->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->leftJoin(
|
||||
'transactions AS t_source', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 't_source.transaction_journal_id')->where('t_source.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions AS t_destination', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 't_destination.transaction_journal_id')->where('t_destination.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->where('tags.tagMode', 'balancingAct')
|
||||
->where('transaction_types.type', TransactionType::TRANSFER)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereIn('t_source.account_id', $ids)
|
||||
->whereIn('t_destination.account_id', $ids)
|
||||
->groupBy('t_destination.account_id')
|
||||
->get(
|
||||
[
|
||||
't_destination.account_id',
|
||||
DB::raw('SUM(`t_destination`.`amount`) as `sum`'),
|
||||
]
|
||||
);
|
||||
$set = auth()->user()->tags()
|
||||
->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id')
|
||||
->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->leftJoin(
|
||||
'transactions AS t_source', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 't_source.transaction_journal_id')->where('t_source.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions AS t_destination', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 't_destination.transaction_journal_id')->where('t_destination.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->where('tags.tagMode', 'balancingAct')
|
||||
->where('transaction_types.type', TransactionType::TRANSFER)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereIn('t_source.account_id', $ids)
|
||||
->whereIn('t_destination.account_id', $ids)
|
||||
->groupBy('t_destination.account_id')
|
||||
->get(
|
||||
[
|
||||
't_destination.account_id',
|
||||
DB::raw('SUM(t_destination.amount) AS sum'),
|
||||
]
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
@@ -262,6 +263,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
/**
|
||||
* @param Balance $balance
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @return Balance
|
||||
*/
|
||||
private function removeUnusedBudgets(Balance $balance): Balance
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceReportHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetReportHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user