mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-17 11:16:39 +00:00
Compare commits
266 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9bdfecbfdc | ||
|
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 | ||
|
c03f5f5ff0 | ||
|
6775fc58c8 | ||
|
9f250fc61b | ||
|
94609f1419 | ||
|
53402aa5e2 | ||
|
5aadb29905 | ||
|
d4f8c41d80 | ||
|
a2e14f8b8d | ||
|
98c4ac955a | ||
|
70b63e1736 | ||
|
106665a468 | ||
|
da5e48d769 | ||
|
85f484e73c | ||
|
d287ae97f8 | ||
|
117bb602dc | ||
|
e440d55034 | ||
|
7f5b94fe43 | ||
|
c58eea6654 | ||
|
bbed5d0701 | ||
|
2775690fc8 | ||
|
1fd9f6e724 | ||
|
3d63903128 | ||
|
ef876a165a | ||
|
c4d6aaeef3 | ||
|
37b735c2e3 | ||
|
62d30c7b0e | ||
|
9cac7d46c0 | ||
|
99b3e24836 | ||
|
ffb699cb06 | ||
|
2947ec0002 | ||
|
5c4d010bde | ||
|
955306d877 | ||
|
015935ed55 | ||
|
48f4cceb19 | ||
|
9850220aac | ||
|
c4ac1460f0 | ||
|
b9e1e01337 | ||
|
76649cb7de | ||
|
5e310776b4 | ||
|
4d7fa11172 | ||
|
28962007c1 | ||
|
2111873bcf | ||
|
0aaf9a6fda | ||
|
186b704509 | ||
|
efe9933721 | ||
|
200366f5be | ||
|
c9bd72337d | ||
|
d4510440b8 | ||
|
5a9cf698f7 | ||
|
5826fec519 | ||
|
7035600984 | ||
|
b1dfb5811f | ||
|
51570a5d08 | ||
|
f065f3a0b8 | ||
|
47376f1f35 | ||
|
bcfe2c6410 | ||
|
09d63b584d | ||
|
5f5469a7d4 | ||
|
38800d61b0 | ||
|
1186e95c51 | ||
|
d870e0f42e | ||
|
0db9852769 | ||
|
7e3f9048fe | ||
|
1ba88f182b | ||
|
c8f5a6b7ad | ||
|
d26bbf3cdc | ||
|
0de72b6914 | ||
|
e41c89bd59 | ||
|
541d9ebdd9 | ||
|
1e724712e0 | ||
|
3682467ae3 | ||
|
7707c81b2d | ||
|
e434de72a3 | ||
|
ce191fa6d3 | ||
|
90865a5284 | ||
|
684f6e0b5c | ||
|
c287bc139c | ||
|
1392275b81 | ||
|
87c0f1d86e | ||
|
a4a723cfc6 | ||
|
921e2c06f4 | ||
|
cb9433f4b9 | ||
|
1be6af820e | ||
|
3b686b6d1c | ||
|
697566fe42 | ||
|
5130ba7ea4 | ||
|
c9e46a4dd1 | ||
|
f5b3dc36e3 | ||
|
f1e8d1cf1e | ||
|
e8e7ab01d2 | ||
|
9244994233 | ||
|
ae768a8525 | ||
|
162c762973 | ||
|
57b5981904 | ||
|
275d19e71d | ||
|
189b11befa | ||
|
a56a5fc228 | ||
|
cbe3fb73a8 | ||
|
3d58fbebec | ||
|
b947ff50ed | ||
|
18d2741814 | ||
|
93a54780ab | ||
|
3d201db6fc | ||
|
9ffc0936ee | ||
|
fbf9e00208 | ||
|
2c826451d1 | ||
|
617a5c0606 | ||
|
8331a7e34a | ||
|
8ee1676f0a | ||
|
5dc8620c43 | ||
|
d2733a4df0 | ||
|
ae649223d8 | ||
|
6267930938 | ||
|
bdee8cde77 | ||
|
e63f216905 | ||
|
ec18165698 | ||
|
307e6a2337 | ||
|
b80d8cf774 | ||
|
7a5ef6013a | ||
|
13b92c47d9 | ||
|
5a79bc0a99 | ||
|
beda6ec3a9 | ||
|
c619b8730b | ||
|
c14ec8b006 |
@@ -1,50 +0,0 @@
|
||||
---
|
||||
engines:
|
||||
csslint:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
- javascript
|
||||
- python
|
||||
- php
|
||||
eslint:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
phpmd:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "**.css"
|
||||
- "**.inc"
|
||||
- "**.js"
|
||||
- "**.jsx"
|
||||
- "**.module"
|
||||
- "**.php"
|
||||
- "**.py"
|
||||
- "**.rb"
|
||||
exclude_paths:
|
||||
- gulpfile.js
|
||||
- public/packages/maximebf/php-debugbar/debugbar.js
|
||||
- public/packages/maximebf/php-debugbar/widgets.js
|
||||
- public/packages/maximebf/php-debugbar/openhandler.js
|
||||
- public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js
|
||||
- public/js/bootstrap3-typeahead.min.js
|
||||
- public/js/bootstrap-sortable.js
|
||||
- public/js/bootstrap-tagsinput.min.js
|
||||
- public/js/bootstrap-tagsinput.min.js.map
|
||||
- public/js/daterangepicker.js
|
||||
- public/js/jquery-2.1.3.min.js
|
||||
- public/js/jquery-2.1.3.min.js.map
|
||||
- public/js/jquery-ui.min.js
|
||||
- public/js/metisMenu.js
|
||||
- public/js/moment.min.js
|
||||
- public/js/sb-admin-2.js
|
||||
- public/bootstrap/*
|
||||
- resources/lang/*
|
||||
- tests/*
|
||||
- database/*
|
||||
- storage/*
|
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,10 +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
|
||||
|
||||
BLOCKED_DOMAINS=
|
||||
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
|
||||
|
10
.gitignore
vendored
Normal file → Executable file
10
.gitignore
vendored
Normal file → Executable file
@@ -1,5 +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
|
||||
|
@@ -4,3 +4,5 @@ tools:
|
||||
filter:
|
||||
excluded_paths:
|
||||
- app/Support/Migration/*
|
||||
- app/database/migrations/*
|
||||
- database/migrations/*
|
||||
|
22
.travis.yml
22
.travis.yml
@@ -1,22 +0,0 @@
|
||||
language: php
|
||||
sudo: false
|
||||
php:
|
||||
- 7
|
||||
|
||||
install:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- composer selfupdate
|
||||
- rm composer.lock
|
||||
- composer update --no-scripts
|
||||
- php artisan clear-compiled
|
||||
- php artisan optimize
|
||||
- php artisan env
|
||||
- mv -v .env.testing .env
|
||||
- php artisan env
|
||||
- touch storage/upload/at-1.data
|
||||
- touch storage/upload/at-2.data
|
||||
- touch storage/database/testing.db
|
||||
- php artisan migrate --seed
|
||||
|
||||
script:
|
||||
- phpunit
|
111
CHANGELOG.md
111
CHANGELOG.md
@@ -2,8 +2,115 @@
|
||||
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.0.0] - 2015-05-25
|
||||
### 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
|
||||
- More feedback in the import procedure.
|
||||
- Extended model for import job.
|
||||
- Web bases import procedure.
|
||||
|
||||
|
||||
### Changed
|
||||
- Scrutinizer configuration
|
||||
- Various code clean up.
|
||||
|
||||
### Removed
|
||||
- Code climate YAML file.
|
||||
|
||||
### Fixed
|
||||
- Fixed a bug where a migration would check an empty table name.
|
||||
- Fixed various bugs in the import routine.
|
||||
- Fixed various bugs in the piggy banks pages.
|
||||
- Fixed a bug in the ``firefly:verify`` routine
|
||||
|
||||
## [3.10] - 2015-05-25
|
||||
### Added
|
||||
- New charts in year report
|
||||
- Can add / remove money from piggy bank on mobile device.
|
||||
- Bill overview shows some useful things.
|
||||
- Firefly will track registration / activation IP addresses.
|
||||
|
||||
|
||||
### Changed
|
||||
- Rewrote the import routine.
|
||||
- The date picker now supports more ranges and periods.
|
||||
- Rewrote all migrations. #272
|
||||
|
||||
### Fixed
|
||||
- Issue #264
|
||||
- Issue #265
|
||||
- Fixed amount calculation problems, #266, thanks @xzaz
|
||||
- Issue #271
|
||||
- Issue #278, #273, thanks @StevenReitsma and @rubella
|
||||
- Bug in attachment download routine would report the wrong size to the user's browser.
|
||||
- Various NULL errors fixed.
|
||||
- Various strict typing errors fixed.
|
||||
- Fixed pagination problems, #276, thanks @xzaz
|
||||
- Fixed a bug where an expense would be assigned to a piggy bank if you created a transfer first.
|
||||
- Bulk update problems, #280, thanks @stickgrinder
|
||||
- Fixed various problems with amount reporting of split transactions.
|
||||
|
||||
[3.9.1]
|
||||
### Fixed
|
||||
- Fixed a bug where removing money from a piggy bank would not work. See issue #265 and #269
|
||||
|
||||
[3.9.0]
|
||||
### Added
|
||||
|
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.
|
||||
|
@@ -22,24 +22,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')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
66
app/Console/Commands/EncryptFile.php
Normal file
66
app/Console/Commands/EncryptFile.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class EncryptFile
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class EncryptFile extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Encrypts a file and places it in the storage/upload directory.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:encrypt {file} {key}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$file = e(strval($this->argument('file')));
|
||||
if (!file_exists($file)) {
|
||||
$this->error(sprintf('File "%s" does not seem to exist.', $file));
|
||||
|
||||
return;
|
||||
}
|
||||
$content = file_get_contents($file);
|
||||
$content = Crypt::encrypt($content);
|
||||
$newName = e(strval($this->argument('key'))) . '.upload';
|
||||
|
||||
$path = storage_path('upload') . '/' . $newName;
|
||||
file_put_contents($path, $content);
|
||||
$this->line(sprintf('Encrypted "%s" and put it in "%s"', $file, $path));
|
||||
}
|
||||
}
|
120
app/Console/Commands/Import.php
Normal file
120
app/Console/Commands/Import.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Import\ImportProcedure;
|
||||
use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Import
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class Import extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Import stuff into Firefly III.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:import {key}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$jobKey = $this->argument('key');
|
||||
$job = ImportJob::whereKey($jobKey)->first();
|
||||
if (!$this->isValid($job)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->line('Going to import job with key "' . $job->key . '" of type ' . $job->file_type);
|
||||
|
||||
$monolog = Log::getMonolog();
|
||||
$handler = new CommandHandler($this);
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
$result = ImportProcedure::runImport($job);
|
||||
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var TransactionJournal $journal
|
||||
*/
|
||||
foreach ($result as $index => $journal) {
|
||||
if (!is_null($journal->id)) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
|
||||
continue;
|
||||
}
|
||||
$this->error(sprintf('Could not store line #%d', $index));
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isValid(ImportJob $job): bool
|
||||
{
|
||||
if (is_null($job)) {
|
||||
$this->error('This job does not seem to exist.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($job->status != 'settings_complete') {
|
||||
$this->error('This job is not ready to be imported.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
99
app/Console/Commands/ScanAttachments.php
Normal file
99
app/Console/Commands/ScanAttachments.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* ScanAttachments.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
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:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,7 +25,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
protected $description = 'Instructions in case of upgrade trouble.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
@@ -44,8 +44,6 @@ class UpgradeFireflyInstructions extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -53,15 +51,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);
|
||||
|
@@ -12,13 +12,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 +55,6 @@ class VerifyDatabase extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -81,6 +79,9 @@ class VerifyDatabase extends Command
|
||||
|
||||
// report on journals with no transactions at all.
|
||||
$this->reportNoTransactions();
|
||||
|
||||
// transfers with budgets.
|
||||
$this->reportTransfersBudgets();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,14 +92,17 @@ 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)
|
||||
->get(['accounts.id', 'accounts.name', 'accounts.user_id', 'users.email', DB::raw('COUNT(`transactions`.`id`) AS `transaction_count`')]);
|
||||
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
|
||||
->whereNull('transactions.account_id')
|
||||
->get(
|
||||
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email']
|
||||
);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$line = 'User #' . $entry->user_id . ' (' . $entry->email . ') has account #' . $entry->id . ' ("' . Crypt::decrypt($entry->name)
|
||||
. '") which has no transactions.';
|
||||
$name = $entry->name;
|
||||
$line = 'User #%d (%s) has account #%d ("%s") which has no transactions.';
|
||||
$line = sprintf($line, $entry->user_id, $entry->email, $entry->id, $name);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
@@ -111,9 +115,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) {
|
||||
@@ -223,19 +227,16 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function reportNoTransactions()
|
||||
{
|
||||
/*
|
||||
* select transaction_journals.id, count(transactions.id) as transaction_count from transaction_journals
|
||||
left join transactions ON transaction_journals.id = transactions.transaction_journal_id
|
||||
group by transaction_journals.id
|
||||
having transaction_count = 0
|
||||
*/
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->groupBy('transaction_journals.id')
|
||||
->having('transaction_count', '=', 0)
|
||||
->get(['transaction_journals.id', DB::raw('COUNT(`transactions`.`id`) as `transaction_count`')]);
|
||||
->whereNull('transactions.transaction_journal_id')
|
||||
->get(['transaction_journals.id']);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
@@ -304,4 +305,29 @@ having transaction_count = 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
32
app/Console/Kernel.php
Normal file → Executable file
32
app/Console/Kernel.php
Normal file → Executable file
@@ -11,8 +11,12 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use FireflyIII\Console\Commands\EncryptFile;
|
||||
use FireflyIII\Console\Commands\Import;
|
||||
use FireflyIII\Console\Commands\ScanAttachments;
|
||||
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
||||
use FireflyIII\Console\Commands\VerifyDatabase;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
/**
|
||||
@@ -22,11 +26,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
|
||||
*/
|
||||
@@ -51,5 +54,30 @@ class Kernel extends ConsoleKernel
|
||||
= [
|
||||
UpgradeFireflyInstructions::class,
|
||||
VerifyDatabase::class,
|
||||
Import::class,
|
||||
EncryptFile::class,
|
||||
ScanAttachments::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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Crud\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
@@ -26,6 +27,8 @@ use Log;
|
||||
/**
|
||||
* Class AccountCrud
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
*
|
||||
* @package FireflyIII\Crud\Account
|
||||
*/
|
||||
class AccountCrud implements AccountCrudInterface
|
||||
@@ -52,14 +55,14 @@ class AccountCrud implements AccountCrudInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(Account $account, Account $moveTo = null): bool
|
||||
public function destroy(Account $account, Account $moveTo): bool
|
||||
{
|
||||
if (!is_null($moveTo)) {
|
||||
// update all transactions:
|
||||
if (!is_null($moveTo->id)) {
|
||||
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
|
||||
}
|
||||
|
||||
$account->delete();
|
||||
if (!is_null($account)) {
|
||||
$account->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -73,12 +76,96 @@ class AccountCrud implements AccountCrudInterface
|
||||
{
|
||||
$account = $this->user->accounts()->find($accountId);
|
||||
if (is_null($account)) {
|
||||
$account = new Account;
|
||||
return new Account;
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByAccountNumber(string $number, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts()
|
||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
||||
->where('account_meta.name', 'accountNumber')
|
||||
->where('account_meta.data', json_encode($number));
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
/** @var Collection $accounts */
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
if ($accounts->count() > 0) {
|
||||
return $accounts->first();
|
||||
}
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $iban
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByIban(string $iban, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts()->where('iban', '!=', '');
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->iban === $iban) {
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array $types
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function findByName(string $name, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts();
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $types);
|
||||
|
||||
}
|
||||
Log::debug(sprintf('Searching for account named %s of the following type(s)', $name), ['types' => $types]);
|
||||
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->name === $name) {
|
||||
Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id));
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
Log::debug('Found nothing.');
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $accountIds
|
||||
*
|
||||
@@ -98,7 +185,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
}
|
||||
|
||||
$result = $query->get(['accounts.*']);
|
||||
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
@@ -126,7 +212,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
}
|
||||
|
||||
$result = $query->get(['accounts.*']);
|
||||
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
@@ -140,31 +225,16 @@ class AccountCrud implements AccountCrudInterface
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function store(array $data): Account
|
||||
{
|
||||
$newAccount = $this->storeAccount($data);
|
||||
if (!is_null($newAccount)) {
|
||||
if (!is_null($newAccount->id)) {
|
||||
$this->storeMetadata($newAccount, $data);
|
||||
}
|
||||
|
||||
// continue with the opposing account:
|
||||
if ($data['openingBalance'] != 0) {
|
||||
$opposingData = [
|
||||
'user' => $data['user'],
|
||||
'accountType' => 'initial',
|
||||
'virtualBalance' => 0,
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
'iban' => '',
|
||||
];
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
if (!is_null($opposing) && !is_null($newAccount)) {
|
||||
$this->storeInitialBalance($newAccount, $opposing, $data);
|
||||
}
|
||||
|
||||
$this->storeInitialBalance($newAccount, $data);
|
||||
}
|
||||
|
||||
return $newAccount;
|
||||
@@ -199,39 +269,29 @@ class AccountCrud implements AccountCrudInterface
|
||||
$account->save();
|
||||
|
||||
$this->updateMetadata($account, $data);
|
||||
$openingBalance = $this->openingBalanceTransaction($account);
|
||||
if ($data['openingBalance'] != 0) {
|
||||
if (!is_null($openingBalance->id)) {
|
||||
$this->updateInitialBalance($account, $openingBalance, $data);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
|
||||
$opposingData = [
|
||||
'user' => $data['user'],
|
||||
'accountType' => $type,
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
'iban' => '',
|
||||
'virtualBalance' => 0,
|
||||
];
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
if (!is_null($opposing)) {
|
||||
$this->storeInitialBalance($account, $opposing, $data);
|
||||
}
|
||||
|
||||
return $account;
|
||||
|
||||
}
|
||||
|
||||
if ($openingBalance) { // opening balance is zero, should we delete it?
|
||||
$openingBalance->delete(); // delete existing opening balance.
|
||||
}
|
||||
$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
|
||||
*
|
||||
@@ -263,8 +323,9 @@ class AccountCrud implements AccountCrudInterface
|
||||
];
|
||||
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
||||
if (!$existingAccount) {
|
||||
Log::error('Account create error: ' . $newAccount->getErrors()->toJson());
|
||||
abort(500);
|
||||
Log::error('Account create error', $newAccount->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
$newAccount = $existingAccount;
|
||||
|
||||
@@ -276,19 +337,21 @@ class AccountCrud implements AccountCrudInterface
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account $opposing
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
protected function storeInitialBalance(Account $account, Account $opposing, array $data): 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,
|
||||
'bill_id' => null,
|
||||
'transaction_currency_id' => $data['openingBalanceCurrency'],
|
||||
'description' => 'Initial balance for "' . $account->name . '"',
|
||||
'completed' => true,
|
||||
@@ -299,24 +362,22 @@ class AccountCrud implements AccountCrudInterface
|
||||
|
||||
$firstAccount = $account;
|
||||
$secondAccount = $opposing;
|
||||
$firstAmount = $data['openingBalance'];
|
||||
$secondAmount = $data['openingBalance'] * -1;
|
||||
$firstAmount = $amount;
|
||||
$secondAmount = $amount * -1;
|
||||
|
||||
if ($data['openingBalance'] < 0) {
|
||||
$firstAccount = $opposing;
|
||||
$secondAccount = $account;
|
||||
$firstAmount = $data['openingBalance'] * -1;
|
||||
$secondAmount = $data['openingBalance'];
|
||||
$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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,36 +397,36 @@ class AccountCrud implements AccountCrudInterface
|
||||
);
|
||||
$metaData->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $data
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournal
|
||||
* @return bool
|
||||
*/
|
||||
protected function updateInitialBalance(Account $account, TransactionJournal $journal, array $data): TransactionJournal
|
||||
protected function updateInitialBalance(Account $account, array $data): bool
|
||||
{
|
||||
$journal->date = $data['openingBalanceDate'];
|
||||
$journal->save();
|
||||
$openingBalance = $this->openingBalanceTransaction($account);
|
||||
if ($data['openingBalance'] != 0) {
|
||||
if (!is_null($openingBalance->id)) {
|
||||
$date = $data['openingBalanceDate'];
|
||||
$amount = $data['openingBalance'];
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions()->get() as $transaction) {
|
||||
if ($account->id == $transaction->account_id) {
|
||||
$transaction->amount = $data['openingBalance'];
|
||||
$transaction->save();
|
||||
}
|
||||
if ($account->id != $transaction->account_id) {
|
||||
$transaction->amount = $data['openingBalance'] * -1;
|
||||
$transaction->save();
|
||||
return $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 $journal;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,4 +479,56 @@ class AccountCrud implements AccountCrudInterface
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,30 @@ interface AccountCrudInterface
|
||||
*/
|
||||
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
|
||||
*
|
||||
@@ -67,7 +91,6 @@ interface AccountCrudInterface
|
||||
*/
|
||||
public function storeMeta(Account $account, string $name, $value): AccountMeta;
|
||||
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
@@ -75,4 +98,12 @@ interface AccountCrudInterface
|
||||
* @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;
|
||||
}
|
||||
|
@@ -105,9 +105,6 @@ class Journal implements JournalInterface
|
||||
*/
|
||||
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal
|
||||
{
|
||||
echo '<pre>';
|
||||
print_r($data);
|
||||
|
||||
$journal->description = $data['journal_description'];
|
||||
$journal->transaction_currency_id = $data['journal_currency_id'];
|
||||
$journal->date = $data['date'];
|
||||
@@ -167,7 +164,8 @@ class Journal implements JournalInterface
|
||||
{
|
||||
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']);
|
||||
|
||||
if (strlen($data['source_account_name']) > 0) {
|
||||
|
||||
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]
|
||||
@@ -215,4 +213,4 @@ class Journal implements JournalInterface
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -44,4 +44,4 @@ interface JournalInterface
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal;
|
||||
}
|
||||
}
|
||||
|
40
app/Events/UserIsConfirmed.php
Normal file
40
app/Events/UserIsConfirmed.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* UserIsConfirmed.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 UserIsConfirmed
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserIsConfirmed 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;
|
||||
}
|
||||
}
|
40
app/Events/UserIsDeleted.php
Normal file
40
app/Events/UserIsDeleted.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* UserIsDeleted.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 UserIsDeleted
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserIsDeleted 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;
|
||||
}
|
||||
}
|
33
app/Exceptions/Handler.php
Normal file → Executable file
33
app/Exceptions/Handler.php
Normal file → Executable file
@@ -10,14 +10,15 @@
|
||||
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 +35,12 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
protected $dontReport
|
||||
= [
|
||||
AuthenticationException::class,
|
||||
AuthorizationException::class,
|
||||
HttpException::class,
|
||||
ModelNotFoundException::class,
|
||||
TokenMismatchException::class,
|
||||
ValException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -71,15 +75,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 +95,26 @@ 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');
|
||||
}
|
||||
}
|
||||
|
@@ -83,15 +83,16 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $attachment->attachable;
|
||||
$args = [
|
||||
'attachment_name' => $attachment->filename,
|
||||
'attachment_name' => e($attachment->filename),
|
||||
'attachment_id' => $attachment->id,
|
||||
'type' => strtolower($journal->transactionType->type),
|
||||
'description' => $journal->description,
|
||||
'description' => e($journal->description),
|
||||
'journal_id' => $journal->id,
|
||||
'date' => $journal->date->formatLocalized(strval(trans('config.month_and_day'))),
|
||||
'amount' => Amount::formatJournal($journal, false),
|
||||
];
|
||||
$string = trans('firefly.attachment_explanation', $args) . "\n";
|
||||
Log::debug('Appended explanation string', ['string' => $string]);
|
||||
$this->explanationString .= $string;
|
||||
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
@@ -29,6 +28,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,12 +42,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');
|
||||
|
||||
// todo needs work for new importer (potentially collect other types as well)
|
||||
$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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,12 +64,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
|
||||
*
|
||||
@@ -85,9 +104,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;
|
||||
@@ -99,23 +137,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -44,4 +44,4 @@ class EntryAccount
|
||||
$this->type = $account->accountType->type;
|
||||
$this->number = $account->getMeta('accountNumber');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,4 +38,4 @@ class EntryBill
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -38,4 +38,4 @@ class EntryBudget
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -37,4 +37,4 @@ class EntryCategory
|
||||
$this->name = $category->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -104,4 +104,4 @@ class BudgetLimitEventHandler
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
@@ -39,7 +38,7 @@ class ConnectJournalToPiggyBank
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
$piggyBank = auth()->user()->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
|
||||
if (is_null($piggyBank)) {
|
||||
return true;
|
||||
|
@@ -37,7 +37,7 @@ class ConnectTransactionToPiggyBank
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$transaction = $event->transaction;
|
||||
|
||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
||||
|
||||
// valid piggy:
|
||||
if (is_null($piggyBank->id)) {
|
||||
|
@@ -17,7 +17,6 @@ use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class FireRulesForStore
|
||||
@@ -38,7 +37,7 @@ class FireRulesForStore
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$user = auth()->user();
|
||||
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
|
@@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\TransactionJournalUpdated;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
@@ -36,7 +35,7 @@ class FireRulesForUpdate
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$user = auth()->user();
|
||||
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
|
@@ -27,6 +27,7 @@ class UpdateJournalConnection
|
||||
* Handle the event.
|
||||
*
|
||||
* @param TransactionJournalUpdated $event
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@@ -46,7 +47,7 @@ class UpdateJournalConnection
|
||||
}
|
||||
$piggyBank = $event->piggyBank()->first();
|
||||
$repetition = null;
|
||||
if ($piggyBank) {
|
||||
if (!is_null($piggyBank)) {
|
||||
/** @var PiggyBankRepetition $repetition */
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
}
|
||||
|
61
app/Handlers/Events/UserSaveIpAddress.php
Normal file
61
app/Handlers/Events/UserSaveIpAddress.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?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 Preferences;
|
||||
|
||||
/**
|
||||
* Class UserSaveIpAddress
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UserSaveIpAddress
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@@ -10,7 +10,6 @@
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -60,7 +59,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 +111,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 +138,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 +249,8 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
/**
|
||||
* @param array $files
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function processFiles(array $files, Model $model): bool
|
||||
|
@@ -32,14 +32,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 +88,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 +120,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 +157,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
|
||||
|
@@ -41,46 +41,66 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param BudgetLine $budgetLine
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addBudgetLine(BudgetLine $budgetLine)
|
||||
public function addBudgetLine(BudgetLine $budgetLine): Budget
|
||||
{
|
||||
$this->budgetLines->push($budgetLine);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addBudgeted(string $add)
|
||||
public function addBudgeted(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->budgeted = bcadd($this->budgeted, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addLeft(string $add)
|
||||
public function addLeft(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->left = bcadd($this->left, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addOverspent(string $add)
|
||||
public function addOverspent(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->overspent = bcadd($this->overspent, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addSpent(string $add)
|
||||
public function addSpent(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->spent = bcadd($this->spent, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,10 +121,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $budgeted
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setBudgeted(string $budgeted)
|
||||
public function setBudgeted(string $budgeted): Budget
|
||||
{
|
||||
$this->budgeted = $budgeted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,10 +141,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $left
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setLeft(string $left)
|
||||
public function setLeft(string $left): Budget
|
||||
{
|
||||
$this->left = $left;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,10 +161,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $overspent
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setOverspent(string $overspent)
|
||||
public function setOverspent(string $overspent): Budget
|
||||
{
|
||||
$this->overspent = strval(round($overspent, 2));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,10 +181,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $spent
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setSpent(string $spent)
|
||||
public function setSpent(string $spent): Budget
|
||||
{
|
||||
$this->spent = strval(round($spent, 2));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -45,10 +45,14 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param BudgetModel $budget
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setBudget(BudgetModel $budget)
|
||||
public function setBudget(BudgetModel $budget): BudgetLine
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,10 +65,14 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $budgeted
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setBudgeted(string $budgeted)
|
||||
public function setBudgeted(string $budgeted): BudgetLine
|
||||
{
|
||||
$this->budgeted = $budgeted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,10 +85,14 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $left
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setLeft(string $left)
|
||||
public function setLeft(string $left): BudgetLine
|
||||
{
|
||||
$this->left = $left;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,10 +105,14 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $overspent
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setOverspent(string $overspent)
|
||||
public function setOverspent(string $overspent): BudgetLine
|
||||
{
|
||||
$this->overspent = $overspent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,10 +125,14 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param LimitRepetition $repetition
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setRepetition(LimitRepetition $repetition)
|
||||
public function setRepetition(LimitRepetition $repetition): BudgetLine
|
||||
{
|
||||
$this->repetition = $repetition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,10 +145,14 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $spent
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setSpent(string $spent)
|
||||
public function setSpent(string $spent): BudgetLine
|
||||
{
|
||||
$this->spent = $spent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AccountId.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class AccountId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AccountId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account
|
||||
*/
|
||||
public function convert(): Account
|
||||
{
|
||||
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
$var = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
|
||||
$account = $crud->find($var);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Amount.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Class Amount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class Amount extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function convert(): string
|
||||
{
|
||||
if (is_numeric($this->value)) {
|
||||
return strval($this->value);
|
||||
}
|
||||
|
||||
return '0';
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AmountComma.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Class AmountComma
|
||||
*
|
||||
* Parses the input as the amount with a comma as decimal separator
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AmountComma extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
public function convert(): string
|
||||
{
|
||||
$value = str_replace(',', '.', strval($this->value));
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return strval($value);
|
||||
}
|
||||
|
||||
return '0';
|
||||
}
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AssetAccountIban.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class AssetAccountIban
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AssetAccountIban extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account
|
||||
*/
|
||||
public function convert(): Account
|
||||
{
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
|
||||
if (strlen($this->value) > 0) {
|
||||
$account = $this->searchOrCreate($crud);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountCrudInterface $crud
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function searchOrCreate(AccountCrudInterface $crud)
|
||||
{
|
||||
// find or create new account:
|
||||
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
/** @var Account $entry */
|
||||
foreach ($set as $entry) {
|
||||
if ($entry->iban == $this->value) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create it if doesn't exist.
|
||||
$accountData = [
|
||||
'name' => $this->value,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0,
|
||||
'virtualBalanceCurrency' => 1, // hard coded.
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => $this->value,
|
||||
'accountNumber' => $this->value,
|
||||
'accountRole' => null,
|
||||
'openingBalance' => 0,
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'openingBalanceCurrency' => 1, // hard coded.
|
||||
];
|
||||
|
||||
$account = $crud->store($accountData);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AssetAccountName.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class AssetAccountName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
public function convert(): Account
|
||||
{
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
/** @var Account $entry */
|
||||
foreach ($set as $entry) {
|
||||
if ($entry->name == $this->value) {
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
$accountData = [
|
||||
'name' => $this->value,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0,
|
||||
'virtualBalanceCurrency' => 1, // hard coded.
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => null,
|
||||
'accountNumber' => $this->value,
|
||||
'accountRole' => null,
|
||||
'openingBalance' => 0,
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'openingBalanceCurrency' => 1, // hard coded.
|
||||
];
|
||||
|
||||
$account = $crud->store($accountData);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AssetAccountNumber.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class AssetAccountNumber
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AssetAccountNumber extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
public function convert(): Account
|
||||
{
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
|
||||
|
||||
return $account;
|
||||
}
|
||||
// if not, search for it (or create it):
|
||||
$value = $this->value ?? '';
|
||||
if (strlen($value) > 0) {
|
||||
// find or create new account:
|
||||
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
/** @var Account $entry */
|
||||
foreach ($set as $entry) {
|
||||
$accountNumber = $entry->getMeta('accountNumber');
|
||||
if ($accountNumber == $this->value) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
||||
$accountData = [
|
||||
'name' => $this->value,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0,
|
||||
'virtualBalanceCurrency' => 1, // hard coded.
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => null,
|
||||
'accountNumber' => $this->value,
|
||||
'accountRole' => null,
|
||||
'openingBalance' => 0,
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'openingBalanceCurrency' => 1, // hard coded.
|
||||
|
||||
];
|
||||
|
||||
$account = $crud->store($accountData);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
return null; // is this accepted?
|
||||
}
|
||||
|
||||
}
|
@@ -1,114 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BasicConverter.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Class BasicConverter
|
||||
*
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BasicConverter
|
||||
{
|
||||
/** @var array */
|
||||
protected $data;
|
||||
/** @var string */
|
||||
protected $field;
|
||||
/** @var int */
|
||||
protected $index;
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
/** @var string */
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getField(): string
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*/
|
||||
public function setField(string $field)
|
||||
{
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getIndex(): int
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*/
|
||||
public function setIndex(int $index)
|
||||
{
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMapped(): array
|
||||
{
|
||||
return $this->mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $mapped
|
||||
*/
|
||||
public function setMapped(array $mapped)
|
||||
{
|
||||
$this->mapped = $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BillId.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class BillId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BillId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Bill
|
||||
*/
|
||||
public function convert(): Bill
|
||||
{
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
|
||||
$bill = $repository->find($value);
|
||||
|
||||
return $bill;
|
||||
}
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BillName.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class BillName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BillName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Bill
|
||||
*/
|
||||
public function convert(): Bill
|
||||
{
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
return $repository->find($this->mapped[$this->index][$this->value]);
|
||||
}
|
||||
$bills = $repository->getBills();
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
if ($bill->name == $this->value) {
|
||||
return $bill;
|
||||
}
|
||||
}
|
||||
|
||||
return new Bill;
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetId.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class BudgetId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BudgetId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Budget
|
||||
*/
|
||||
public function convert(): Budget
|
||||
{
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
|
||||
$budget = $repository->find($value);
|
||||
|
||||
return $budget;
|
||||
}
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetName.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class BudgetName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BudgetName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Budget
|
||||
*/
|
||||
public function convert(): Budget
|
||||
{
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$budget = $repository->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $budget;
|
||||
}
|
||||
$budget = $repository->store(['name' => $this->value, 'user' => Auth::user()->id]);
|
||||
|
||||
|
||||
return $budget;
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CategoryId.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class CategoryId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CategoryId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Category
|
||||
*/
|
||||
public function convert(): Category
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
|
||||
$category = $repository->find($value);
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CategoryName.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class CategoryName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CategoryName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Category
|
||||
*/
|
||||
public function convert(): Category
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$category = $repository->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->value,
|
||||
'user' => Auth::user()->id,
|
||||
];
|
||||
|
||||
$category = $repository->store($data);
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ConverterInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Interface ConverterInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
interface ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function convert();
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data);
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
*/
|
||||
public function setField(string $field);
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*/
|
||||
public function setIndex(int $index);
|
||||
|
||||
/**
|
||||
* @param array $mapped
|
||||
*/
|
||||
public function setMapped(array $mapped);
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue(string $value);
|
||||
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencyCode.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class CurrencyCode
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencyCode extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function convert(): TransactionCurrency
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = $repository->find(intval($this->mapped[$this->index][$this->value]));
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
$currency = $repository->findByCode($this->value);
|
||||
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencyId.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class CurrencyId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencyId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function convert(): TransactionCurrency
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
|
||||
$currency = $repository->find($value);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencyName.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class CurrencyName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencyName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function convert(): TransactionCurrency
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = $repository->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
$currency = $repository->findByName($this->value);
|
||||
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencySymbol.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class CurrencySymbol
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencySymbol extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function convert(): TransactionCurrency
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = $repository->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
$currency = $repository->findBySymbol($this->value);
|
||||
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Date.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use InvalidArgumentException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Date
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class Date extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function convert(): Carbon
|
||||
{
|
||||
$format = session('csv-date-format');
|
||||
try {
|
||||
$date = Carbon::createFromFormat($format, $this->value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::error('Date conversion error: ' . $e->getMessage() . '. Value was "' . $this->value . '", format was "' . $format . '".');
|
||||
|
||||
$message = trans('firefly.csv_date_parse_error', ['format' => $format, 'value' => $this->value]);
|
||||
|
||||
throw new FireflyException($message);
|
||||
}
|
||||
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpposingAccountIban.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class OpposingAccountIban
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* If mapped, return account. Otherwise, only return the name itself.
|
||||
*
|
||||
* @return Account|string
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = $crud->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
return $this->findAccount($crud);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountCrudInterface $crud
|
||||
*
|
||||
* @return Account|string
|
||||
*/
|
||||
private function findAccount(AccountCrudInterface $crud)
|
||||
{
|
||||
if (strlen($this->value) > 0) {
|
||||
|
||||
$set = $crud->getAccountsByType([]);
|
||||
/** @var Account $account */
|
||||
foreach ($set as $account) {
|
||||
if ($account->iban == $this->value) {
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpposingAccountId.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class OpposingAccountId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class OpposingAccountId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return Account
|
||||
*/
|
||||
public function convert(): Account
|
||||
{
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
|
||||
$account = $crud->find($value);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpposingAccountName.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class OpposingAccountName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* If mapped, return account. Otherwise, only return the name itself.
|
||||
*
|
||||
* @return Account|string
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
|
||||
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = $crud->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
return $this->value;
|
||||
|
||||
}
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TagsComma.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class TagsComma
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class TagsComma extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function convert(): Collection
|
||||
{
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$tags = new Collection;
|
||||
|
||||
$strings = explode(',', $this->value);
|
||||
foreach ($strings as $string) {
|
||||
$data = [
|
||||
'tag' => $string,
|
||||
'date' => null,
|
||||
'description' => null,
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoomLevel' => null,
|
||||
'tagMode' => 'nothing',
|
||||
];
|
||||
if (strlen($string) > 0) {
|
||||
$tag = $repository->store($data); // should validate first?
|
||||
$tags->push($tag);
|
||||
}
|
||||
}
|
||||
$tags = $tags->merge($this->data['tags']);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TagsSpace.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class TagsSpace
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class TagsSpace extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function convert(): Collection
|
||||
{
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
|
||||
$tags = new Collection;
|
||||
|
||||
$strings = explode(' ', $this->value);
|
||||
foreach ($strings as $string) {
|
||||
$data = [
|
||||
'tag' => $string,
|
||||
'date' => null,
|
||||
'description' => null,
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoomLevel' => null,
|
||||
'tagMode' => 'nothing',
|
||||
];
|
||||
if (strlen($string) > 0) {
|
||||
$tag = $repository->store($data); // should validate first?
|
||||
$tags->push($tag);
|
||||
}
|
||||
}
|
||||
$tags = $tags->merge($this->data['tags']);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
}
|
@@ -1,336 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Data.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 Crypt;
|
||||
use League\Csv\Reader;
|
||||
use Session;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class Data
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Data
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
protected $csvFileContent = '';
|
||||
/** @var string */
|
||||
protected $csvFileLocation = '';
|
||||
/** @var string */
|
||||
protected $dateFormat = '';
|
||||
/** @var string */
|
||||
protected $delimiter = '';
|
||||
/** @var bool */
|
||||
protected $hasHeaders;
|
||||
/** @var int */
|
||||
protected $importAccount = 0;
|
||||
/** @var array */
|
||||
protected $map = [];
|
||||
/** @var array */
|
||||
protected $mapped = [];
|
||||
/** @var Reader */
|
||||
protected $reader;
|
||||
/** @var array */
|
||||
protected $roles = [];
|
||||
/** @var array */
|
||||
protected $specifix = [];
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->sessionHasHeaders();
|
||||
$this->sessionDateFormat();
|
||||
$this->sessionCsvFileLocation();
|
||||
$this->sessionMap();
|
||||
$this->sessionRoles();
|
||||
$this->sessionMapped();
|
||||
$this->sessionSpecifix();
|
||||
$this->sessionImportAccount();
|
||||
$this->sessionDelimiter();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCsvFileContent(): string
|
||||
{
|
||||
return $this->csvFileContent ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $csvFileContent
|
||||
*/
|
||||
public function setCsvFileContent(string $csvFileContent)
|
||||
{
|
||||
$this->csvFileContent = $csvFileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXxME may return null
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCsvFileLocation(): string
|
||||
{
|
||||
return $this->csvFileLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $csvFileLocation
|
||||
*/
|
||||
public function setCsvFileLocation(string $csvFileLocation)
|
||||
{
|
||||
Session::put('csv-file', $csvFileLocation);
|
||||
$this->csvFileLocation = $csvFileLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXxME may return null
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat(): string
|
||||
{
|
||||
return $this->dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $dateFormat
|
||||
*/
|
||||
public function setDateFormat(string $dateFormat)
|
||||
{
|
||||
Session::put('csv-date-format', $dateFormat);
|
||||
$this->dateFormat = $dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXxME may return null
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDelimiter(): string
|
||||
{
|
||||
return $this->delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $delimiter
|
||||
*/
|
||||
public function setDelimiter(string $delimiter)
|
||||
{
|
||||
Session::put('csv-delimiter', $delimiter);
|
||||
$this->delimiter = $delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
return $this->map;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $map
|
||||
*/
|
||||
public function setMap(array $map)
|
||||
{
|
||||
Session::put('csv-map', $map);
|
||||
$this->map = $map;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMapped(): array
|
||||
{
|
||||
return $this->mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $mapped
|
||||
*/
|
||||
public function setMapped(array $mapped)
|
||||
{
|
||||
Session::put('csv-mapped', $mapped);
|
||||
$this->mapped = $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Reader
|
||||
*/
|
||||
public function getReader(): Reader
|
||||
{
|
||||
if (!is_null($this->csvFileContent) && strlen($this->csvFileContent) === 0) {
|
||||
$this->loadCsvFile();
|
||||
}
|
||||
|
||||
if (is_null($this->reader)) {
|
||||
$this->reader = Reader::createFromString($this->getCsvFileContent());
|
||||
$this->reader->setDelimiter($this->delimiter);
|
||||
}
|
||||
|
||||
return $this->reader;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRoles(): array
|
||||
{
|
||||
return $this->roles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $roles
|
||||
*/
|
||||
public function setRoles(array $roles)
|
||||
{
|
||||
Session::put('csv-roles', $roles);
|
||||
$this->roles = $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSpecifix(): array
|
||||
{
|
||||
return is_array($this->specifix) ? $this->specifix : [];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $specifix
|
||||
*/
|
||||
public function setSpecifix(array $specifix)
|
||||
{
|
||||
Session::put('csv-specifix', $specifix);
|
||||
$this->specifix = $specifix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHeaders(): bool
|
||||
{
|
||||
return $this->hasHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param bool $hasHeaders
|
||||
*/
|
||||
public function setHasHeaders(bool $hasHeaders)
|
||||
{
|
||||
Session::put('csv-has-headers', $hasHeaders);
|
||||
$this->hasHeaders = $hasHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $importAccount
|
||||
*/
|
||||
public function setImportAccount(int $importAccount)
|
||||
{
|
||||
Session::put('csv-import-account', $importAccount);
|
||||
$this->importAccount = $importAccount;
|
||||
}
|
||||
|
||||
protected function loadCsvFile()
|
||||
{
|
||||
$file = $this->getCsvFileLocation();
|
||||
$disk = Storage::disk('upload');
|
||||
$content = $disk->get($file);
|
||||
$contentDecrypted = Crypt::decrypt($content);
|
||||
$this->setCsvFileContent($contentDecrypted);
|
||||
}
|
||||
|
||||
protected function sessionCsvFileLocation()
|
||||
{
|
||||
if (Session::has('csv-file')) {
|
||||
$this->csvFileLocation = (string)session('csv-file');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionDateFormat()
|
||||
{
|
||||
if (Session::has('csv-date-format')) {
|
||||
$this->dateFormat = (string)session('csv-date-format');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionDelimiter()
|
||||
{
|
||||
if (Session::has('csv-delimiter')) {
|
||||
$this->delimiter = session('csv-delimiter');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionHasHeaders()
|
||||
{
|
||||
if (Session::has('csv-has-headers')) {
|
||||
$this->hasHeaders = (bool)session('csv-has-headers');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionImportAccount()
|
||||
{
|
||||
if (Session::has('csv-import-account')) {
|
||||
$this->importAccount = intval(session('csv-import-account'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionMap()
|
||||
{
|
||||
if (Session::has('csv-map')) {
|
||||
$this->map = (array)session('csv-map');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionMapped()
|
||||
{
|
||||
if (Session::has('csv-mapped')) {
|
||||
$this->mapped = (array)session('csv-mapped');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionRoles()
|
||||
{
|
||||
if (Session::has('csv-roles')) {
|
||||
$this->roles = (array)session('csv-roles');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionSpecifix()
|
||||
{
|
||||
if (Session::has('csv-specifix')) {
|
||||
$this->specifix = (array)session('csv-specifix');
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,384 +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;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AnyAccount.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\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class AnyAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class AnyAccount implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
$result = Auth::user()->accounts()->with('accountType')->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
|
||||
$list = [];
|
||||
/** @var Account $account */
|
||||
foreach ($result as $account) {
|
||||
$list[$account->id] = $account->name . ' (' . $account->accountType->type . ')';
|
||||
}
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Bill.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Bill as BillModel;
|
||||
|
||||
/**
|
||||
* Class Bill
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Bill implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
$result = Auth::user()->bills()->get(['bills.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var BillModel $bill */
|
||||
foreach ($result as $bill) {
|
||||
$list[$bill->id] = $bill->name . ' [' . $bill->match . ']';
|
||||
}
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Budget.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Budget as BudgetModel;
|
||||
|
||||
/**
|
||||
* Class Budget
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Budget implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
$result = Auth::user()->budgets()->get(['budgets.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var BudgetModel $budget */
|
||||
foreach ($result as $budget) {
|
||||
$list[$budget->id] = $budget->name;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Category.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Category as CategoryModel;
|
||||
|
||||
/**
|
||||
* Class Category
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Category implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
$result = Auth::user()->categories()->get(['categories.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var CategoryModel $category */
|
||||
foreach ($result as $category) {
|
||||
$list[$category->id] = $category->name;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Tag.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\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Tag as TagModel;
|
||||
|
||||
/**
|
||||
* Class Tag
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Tag implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
$result = Auth::user()->budgets()->get(['tags.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var TagModel $tag */
|
||||
foreach ($result as $tag) {
|
||||
$list[$tag->id] = $tag->tag;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Amount.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
/**
|
||||
* Class Amount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Amount implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array
|
||||
{
|
||||
$amount = $this->data['amount'] ?? '0';
|
||||
$modifier = strval($this->data['amount-modifier']);
|
||||
$this->data['amount'] = bcmul($amount, $modifier);
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
@@ -1,274 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AssetAccount.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\PostProcessing;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* Class AssetAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class AssetAccount implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array
|
||||
{
|
||||
$result = $this->checkIdNameObject(); // has object in ID or Name?
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// no object? maybe asset-account-iban is a string and we can find the matching account.
|
||||
$result = $this->checkIbanString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// no object still? maybe we can find the account by name.
|
||||
$result = $this->checkNameString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
// still nothing? Perhaps the account number can lead us to an account:
|
||||
$result = $this->checkAccountNumberString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkAccountNumberString()
|
||||
{
|
||||
$accountNumber = $this->data['asset-account-number'] ?? null;
|
||||
if ($accountNumber instanceof Account) { // fourth: try to find account based on name, if any.
|
||||
$this->data['asset-account-object'] = $accountNumber;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if (is_string($accountNumber)) { // it's an actual account number
|
||||
$this->data['asset-account-object'] = $this->parseAccountNumberString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkIbanString()
|
||||
{
|
||||
$iban = $this->data['asset-account-iban'] ?? '';
|
||||
$rules = ['iban' => 'iban'];
|
||||
$check = ['iban' => $iban];
|
||||
$validator = Validator::make($check, $rules);
|
||||
if (!$validator->fails()) {
|
||||
$this->data['asset-account-object'] = $this->parseIbanString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function checkIdNameObject()
|
||||
{
|
||||
$accountId = $this->data['asset-account-id'] ?? null;
|
||||
$accountIban = $this->data['asset-account-iban'] ?? null;
|
||||
$accountNumber = $this->data['asset-account-number'] ?? null;
|
||||
if ($accountId instanceof Account) { // first priority. try to find the account based on ID, if any
|
||||
$this->data['asset-account-object'] = $accountId;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if ($accountIban instanceof Account) { // second: try to find the account based on IBAN, if any.
|
||||
$this->data['asset-account-object'] = $accountIban;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
if ($accountNumber instanceof Account) { // second: try to find the account based on account number, if any.
|
||||
$this->data['asset-account-object'] = $accountNumber;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkNameString()
|
||||
{
|
||||
$accountName = $this->data['asset-account-name'] ?? null;
|
||||
if ($accountName instanceof Account) { // third: try to find account based on name, if any.
|
||||
$this->data['asset-account-object'] = $accountName;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if (is_string($accountName)) {
|
||||
$this->data['asset-account-object'] = $this->parseNameString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function createAccount()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
$name = $this->data['asset-account-name'] ?? '';
|
||||
$iban = $this->data['asset-account-iban'] ?? '';
|
||||
|
||||
// create if not exists: // See issue #180
|
||||
$name = strlen($name) > 0 ? $name : $iban;
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $name,
|
||||
'iban' => $iban,
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AccountType
|
||||
*/
|
||||
protected function getAccountType()
|
||||
{
|
||||
return AccountType::where('type', 'Asset account')->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseIbanString()
|
||||
{
|
||||
// create by name and/or iban.
|
||||
$iban = $this->data['asset-account-iban'] ?? '';
|
||||
$accounts = Auth::user()->accounts()->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($iban !== '' && $entry->iban === $iban) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
$account = $this->createAccount();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseNameString()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->name == $this->data['asset-account-name']) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
// create if not exists:
|
||||
// See issue #180
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $this->data['asset-account-name'],
|
||||
'iban' => '',
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
private function parseAccountNumberString()
|
||||
{
|
||||
/** @var AccountCrudInterface $crud */
|
||||
$crud = app(AccountCrudInterface::class);
|
||||
|
||||
$accountNumber = $this->data['asset-account-number'] ?? '';
|
||||
$accountType = $this->getAccountType();
|
||||
$accounts = Auth::user()->accounts()->with(['accountmeta'])->where('account_type_id', $accountType->id)->get();
|
||||
/** @var Account $entry */
|
||||
foreach ($accounts as $entry) {
|
||||
$metaFieldValue = $entry->getMeta('accountNumber');
|
||||
if ($metaFieldValue === $accountNumber && $metaFieldValue !== '') {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
// create new if not exists and return that one:
|
||||
$accountData = [
|
||||
'name' => $accountNumber,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0,
|
||||
'virtualBalanceCurrency' => 1, // hard coded.
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => null,
|
||||
'accountNumber' => $accountNumber,
|
||||
'accountRole' => null,
|
||||
'openingBalance' => 0,
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'openingBalanceCurrency' => 1, // hard coded.
|
||||
];
|
||||
$account = $crud->store($accountData);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Bill.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
/**
|
||||
* Class Bill
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Bill implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array
|
||||
{
|
||||
|
||||
// get bill id.
|
||||
if (!is_null($this->data['bill']) && !is_null($this->data['bill']->id)) {
|
||||
$this->data['bill-id'] = $this->data['bill']->id;
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Currency.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\PostProcessing;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class Currency
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Currency implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array
|
||||
{
|
||||
|
||||
// fix currency
|
||||
if (is_null($this->data['currency'])) {
|
||||
$currencyPreference = Preferences::get('currencyPreference', env('DEFAULT_CURRENCY', 'EUR'));
|
||||
$this->data['currency'] = TransactionCurrency::whereCode($currencyPreference->data)->first();
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Description.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\PostProcessing;
|
||||
|
||||
/**
|
||||
* Class Description
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Description implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array
|
||||
{
|
||||
$description = $this->data['description'] ?? '';
|
||||
$this->data['description'] = trim($description);
|
||||
if (strlen($this->data['description']) == 0) {
|
||||
$this->data['description'] = trans('firefly.csv_empty_description');
|
||||
}
|
||||
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
@@ -1,210 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpposingAccount.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\PostProcessing;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* Class OpposingAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class OpposingAccount implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array
|
||||
{
|
||||
// three values:
|
||||
// opposing-account-id, opposing-account-iban, opposing-account-name
|
||||
|
||||
|
||||
$result = $this->checkIdNameObject();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->checkIbanString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->checkNameString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkIbanString()
|
||||
{
|
||||
$rules = ['iban' => 'iban'];
|
||||
$iban = $this->data['opposing-account-iban'];
|
||||
$check = ['iban' => $iban];
|
||||
$validator = Validator::make($check, $rules);
|
||||
if (is_string($iban) && strlen($iban) > 0 && !$validator->fails()) {
|
||||
|
||||
$this->data['opposing-account-object'] = $this->parseIbanString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function checkIdNameObject()
|
||||
{
|
||||
if ($this->data['opposing-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-id'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if ($this->data['opposing-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any.
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-iban'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkNameString()
|
||||
{
|
||||
if ($this->data['opposing-account-name'] instanceof Account) { // third: try to find account based on name, if any.
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-name'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if (is_string($this->data['opposing-account-name'])) {
|
||||
|
||||
$this->data['opposing-account-object'] = $this->parseNameString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function createAccount()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
|
||||
// create if not exists:
|
||||
$name = is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name']
|
||||
: $this->data['opposing-account-iban'];
|
||||
$account = Account::firstOrCreateEncrypted( // See issue #180
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $name,
|
||||
'iban' => $this->data['opposing-account-iban'],
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AccountType
|
||||
*/
|
||||
protected function getAccountType()
|
||||
{
|
||||
// opposing account type:
|
||||
if ($this->data['amount'] < 0) {
|
||||
// create expense account:
|
||||
|
||||
return AccountType::where('type', 'Expense account')->first();
|
||||
}
|
||||
|
||||
// create revenue account:
|
||||
|
||||
return AccountType::where('type', 'Revenue account')->first();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseIbanString()
|
||||
{
|
||||
// create by name and/or iban.
|
||||
$accounts = Auth::user()->accounts()->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->iban == $this->data['opposing-account-iban']) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
$account = $this->createAccount();
|
||||
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseNameString()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->name == $this->data['opposing-account-name']) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
// create if not exists:
|
||||
$account = Account::firstOrCreateEncrypted( // See issue #180
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $this->data['opposing-account-name'],
|
||||
'iban' => '',
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* PostProcessorInterface.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\PostProcessing;
|
||||
|
||||
|
||||
/**
|
||||
* Interface PostProcessorInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
interface PostProcessorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process(): array;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data);
|
||||
}
|
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Dummy.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\Specifix;
|
||||
|
||||
/**
|
||||
* Class Dummy
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
class Dummy extends Specifix implements SpecifixInterface
|
||||
{
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/** @var array */
|
||||
protected $row;
|
||||
|
||||
/**
|
||||
* Dummy constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->setProcessorType(self::POST_PROCESSOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function fix(): array
|
||||
{
|
||||
return $this->data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*/
|
||||
public function setRow(array $row)
|
||||
{
|
||||
$this->row = $row;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* RabobankDescription.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\Specifix;
|
||||
|
||||
/**
|
||||
* Class RabobankDescription
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
class RabobankDescription extends Specifix implements SpecifixInterface
|
||||
{
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/** @var array */
|
||||
protected $row;
|
||||
|
||||
/**
|
||||
* RabobankDescription constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->setProcessorType(self::POST_PROCESSOR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function fix(): array
|
||||
{
|
||||
$this->rabobankFixEmptyOpposing();
|
||||
|
||||
return $this->data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*/
|
||||
public function setRow(array $row)
|
||||
{
|
||||
$this->row = $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes Rabobank specific thing.
|
||||
*/
|
||||
protected function rabobankFixEmptyOpposing()
|
||||
{
|
||||
if (is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) == 0) {
|
||||
$this->data['opposing-account-name'] = $this->row[10];
|
||||
|
||||
$this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Specifix.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\Specifix;
|
||||
|
||||
/**
|
||||
* Class Specifix
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
class Specifix
|
||||
{
|
||||
|
||||
/** @var int */
|
||||
protected $processorType;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getProcessorType(): int
|
||||
{
|
||||
return $this->processorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $processorType
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setProcessorType(int $processorType)
|
||||
{
|
||||
$this->processorType = $processorType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* SpecifixInterface.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\Specifix;
|
||||
|
||||
/**
|
||||
* Interface SpecifixInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
interface SpecifixInterface
|
||||
{
|
||||
const PRE_PROCESSOR = 1;
|
||||
const POST_PROCESSOR = 2;
|
||||
|
||||
/**
|
||||
* Implement bank and locale related fixes.
|
||||
*/
|
||||
public function fix();
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getProcessorType(): int;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data);
|
||||
|
||||
/**
|
||||
* @param int $processorType
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setProcessorType(int $processorType);
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*/
|
||||
public function setRow(array $row);
|
||||
}
|
@@ -1,202 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Wizard.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 Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Mapper\MapperInterface;
|
||||
use League\Csv\Reader;
|
||||
use Log;
|
||||
use ReflectionException;
|
||||
use Session;
|
||||
use SplFileObject;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class Wizard
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Wizard implements WizardInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Reader $reader
|
||||
* @param array $map
|
||||
* @param bool $hasHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMappableValues(Reader $reader, array $map, bool $hasHeaders): array
|
||||
{
|
||||
$values = [];
|
||||
/*
|
||||
* Loop over the CSV and collect mappable data:
|
||||
*/
|
||||
$keys = array_keys($map);
|
||||
foreach ($reader as $index => $row) {
|
||||
if ($this->useRow($hasHeaders, $index)) {
|
||||
// collect all map values
|
||||
|
||||
foreach ($keys as $column) {
|
||||
$values[$column][] = $row[$column];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Make each one unique.
|
||||
*/
|
||||
$values = $this->uniqueRecursive($values);
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $roles
|
||||
* @param array $map
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedMapping(array $roles, array $map): array
|
||||
{
|
||||
$configRoles = config('csv.roles');
|
||||
$maps = [];
|
||||
$keys = array_keys($map);
|
||||
foreach ($keys as $index) {
|
||||
if (isset($roles[$index])) {
|
||||
$name = $roles[$index];
|
||||
if ($configRoles[$name]['mappable']) {
|
||||
$maps[$index] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $maps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $input
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedRoles(array $input): array
|
||||
{
|
||||
$roles = [];
|
||||
|
||||
|
||||
/*
|
||||
* Store all rows for each column:
|
||||
*/
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $index => $role) {
|
||||
if ($role != '_ignore') {
|
||||
$roles[$index] = $role;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sessionHasValues(array $fields): bool
|
||||
{
|
||||
foreach ($fields as $field) {
|
||||
if (!Session::has($field)) {
|
||||
Log::error('Session is missing field: ' . $field);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $map
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function showOptions(array $map): array
|
||||
{
|
||||
$options = [];
|
||||
foreach ($map as $index => $columnRole) {
|
||||
|
||||
$mapper = config('csv.roles.' . $columnRole . '.mapper');
|
||||
if (is_null($mapper)) {
|
||||
throw new FireflyException('Cannot map field of type "' . $columnRole . '".');
|
||||
}
|
||||
$class = 'FireflyIII\Helpers\Csv\Mapper\\' . $mapper;
|
||||
try {
|
||||
/** @var MapperInterface $mapObject */
|
||||
$mapObject = app($class);
|
||||
} catch (ReflectionException $e) {
|
||||
throw new FireflyException('Column "' . $columnRole . '" cannot be mapped because mapper class ' . $mapper . ' does not exist.');
|
||||
}
|
||||
$set = $mapObject->getMap();
|
||||
$options[$index] = $set;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function storeCsvFile(string $path): string
|
||||
{
|
||||
$time = str_replace(' ', '-', microtime());
|
||||
$fileName = 'csv-upload-' . Auth::user()->id . '-' . $time . '.csv.encrypted';
|
||||
$disk = Storage::disk('upload');
|
||||
$file = new SplFileObject($path, 'r');
|
||||
$content = $file->fread($file->getSize());
|
||||
$contentEncrypted = Crypt::encrypt($content);
|
||||
$disk->put($fileName, $contentEncrypted);
|
||||
|
||||
return $fileName;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function uniqueRecursive(array $array)
|
||||
{
|
||||
foreach ($array as $column => $found) {
|
||||
$array[$column] = array_unique($found);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $hasHeaders
|
||||
* @param int $index
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function useRow(bool $hasHeaders, int $index)
|
||||
{
|
||||
return ($hasHeaders && $index > 1) || !$hasHeaders;
|
||||
}
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WizardInterface.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 League\Csv\Reader;
|
||||
|
||||
/**
|
||||
* Interface WizardInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
interface WizardInterface
|
||||
{
|
||||
/**
|
||||
* @param Reader $reader
|
||||
* @param array $map
|
||||
* @param bool $hasHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMappableValues(Reader $reader, array $map, bool $hasHeaders): array;
|
||||
|
||||
/**
|
||||
* @param array $roles
|
||||
* @param array $map
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedMapping(array $roles, array $map): array;
|
||||
|
||||
/**
|
||||
* @param array $input
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedRoles(array $input): array;
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sessionHasValues(array $fields): bool;
|
||||
|
||||
/**
|
||||
* @param array $map
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function showOptions(array $map): array;
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function storeCsvFile(string $path): string;
|
||||
|
||||
}
|
@@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Helpers\Collection\Balance;
|
||||
@@ -58,8 +57,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
*/
|
||||
public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts): Balance
|
||||
{
|
||||
$balance = new Balance;
|
||||
// build a balance header:
|
||||
$balance = new Balance;
|
||||
$header = new BalanceHeader;
|
||||
$limitRepetitions = $this->budgetRepository->getAllBudgetLimitRepetitions($start, $end);
|
||||
foreach ($accounts as $account) {
|
||||
@@ -103,34 +101,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 +260,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
|
||||
/**
|
||||
* @param Balance $balance
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @return Balance
|
||||
*/
|
||||
|
@@ -18,6 +18,7 @@ use FireflyIII\Helpers\Collection\BudgetLine;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,60 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // at 43, its ok.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function budgetYearOverview(Carbon $start, Carbon $end, Collection $accounts): Collection
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('budget-year');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$current = clone $start;
|
||||
$return = new Collection;
|
||||
$set = $this->repository->getBudgets();
|
||||
$budgets = [];
|
||||
$spent = [];
|
||||
$headers = $this->createYearHeaders($current, $end);
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($set as $budget) {
|
||||
$id = $budget->id;
|
||||
$budgets[$id] = $budget->name;
|
||||
$current = clone $start;
|
||||
$budgetData = $this->getBudgetSpentData($current, $end, $budget, $accounts);
|
||||
$sum = $budgetData['sum'];
|
||||
$spent[$id] = $budgetData['spent'];
|
||||
|
||||
if (bccomp('0', $sum) === 0) {
|
||||
// not spent anything.
|
||||
unset($spent[$id]);
|
||||
unset($budgets[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
$return->put('headers', $headers);
|
||||
$return->put('budgets', $budgets);
|
||||
$return->put('spent', $spent);
|
||||
|
||||
$cache->store($return);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
@@ -63,10 +118,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
|
||||
if ($spent > 0) {
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setOverspent($spent);
|
||||
$object->addOverspent($spent);
|
||||
$object->addBudgetLine($budgetLine);
|
||||
$budgetLine->setBudget($budget)->setOverspent($spent);
|
||||
$object->addOverspent($spent)->addBudgetLine($budgetLine);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -76,18 +129,12 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
$data = $this->calculateExpenses($budget, $repetition, $accounts);
|
||||
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setRepetition($repetition);
|
||||
$budgetLine->setLeft($data['left']);
|
||||
$budgetLine->setSpent($data['expenses']);
|
||||
$budgetLine->setOverspent($data['overspent']);
|
||||
$budgetLine->setBudgeted($repetition->amount);
|
||||
$budgetLine->setBudget($budget)->setRepetition($repetition)
|
||||
->setLeft($data['left'])->setSpent($data['expenses'])->setOverspent($data['overspent'])
|
||||
->setBudgeted(strval($repetition->amount));
|
||||
|
||||
$object->addBudgeted($repetition->amount);
|
||||
$object->addSpent($data['spent']);
|
||||
$object->addLeft($data['left']);
|
||||
$object->addOverspent($data['overspent']);
|
||||
$object->addBudgetLine($budgetLine);
|
||||
$object->addBudgeted(strval($repetition->amount))->addSpent($data['spent'])
|
||||
->addLeft($data['left'])->addOverspent($data['overspent'])->addBudgetLine($budgetLine);
|
||||
|
||||
}
|
||||
|
||||
@@ -97,10 +144,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
|
||||
$noBudget = $this->repository->spentInPeriodWithoutBudget($accounts, $start, $end);
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setOverspent($noBudget);
|
||||
$budgetLine->setSpent($noBudget);
|
||||
$object->addOverspent($noBudget);
|
||||
$object->addBudgetLine($budgetLine);
|
||||
$budgetLine->setOverspent($noBudget)->setSpent($noBudget);
|
||||
$object->addOverspent($noBudget)->addBudgetLine($budgetLine);
|
||||
|
||||
return $object;
|
||||
}
|
||||
@@ -181,4 +226,50 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
return $array;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $current
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createYearHeaders(Carbon $current, Carbon $end): array
|
||||
{
|
||||
$headers = [];
|
||||
while ($current < $end) {
|
||||
$short = $current->format('m-Y');
|
||||
$headers[$short] = $current->formatLocalized((string)trans('config.month'));
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $current
|
||||
* @param Carbon $end
|
||||
* @param Budget $budget
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBudgetSpentData(Carbon $current, Carbon $end, Budget $budget, Collection $accounts): array
|
||||
{
|
||||
$sum = '0';
|
||||
$spent = [];
|
||||
while ($current < $end) {
|
||||
$currentEnd = clone $current;
|
||||
$currentEnd->endOfMonth();
|
||||
$format = $current->format('m-Y');
|
||||
$budgetSpent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $current, $currentEnd);
|
||||
$spent[$format] = $budgetSpent;
|
||||
$sum = bcadd($sum, $budgetSpent);
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
return [
|
||||
'spent' => $spent,
|
||||
'sum' => $sum,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,15 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface BudgetReportHelperInterface
|
||||
{
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function budgetYearOverview(Carbon $start, Carbon $end, Collection $accounts): Collection;
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
|
@@ -82,8 +82,8 @@ class ReportHelper implements ReportHelperInterface
|
||||
$billLine = new BillLine;
|
||||
$billLine->setBill($bill);
|
||||
$billLine->setActive(intval($bill->active) === 1);
|
||||
$billLine->setMin($bill->amount_min);
|
||||
$billLine->setMax($bill->amount_max);
|
||||
$billLine->setMin(strval($bill->amount_min));
|
||||
$billLine->setMax(strval($bill->amount_max));
|
||||
$billLine->setHit(false);
|
||||
// is hit in period?
|
||||
|
||||
|
@@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
@@ -50,7 +49,7 @@ class AccountController extends Controller
|
||||
/**
|
||||
* @param string $what
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create(string $what = 'asset')
|
||||
{
|
||||
@@ -116,7 +115,7 @@ class AccountController extends Controller
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(ARI $repository, Account $account)
|
||||
{
|
||||
@@ -172,8 +171,10 @@ class AccountController extends Controller
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
||||
$accounts = $crud->getAccountsByType($types);
|
||||
$start = clone session('start', Carbon::now()->startOfMonth());
|
||||
$end = clone session('end', Carbon::now()->endOfMonth());
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
$end = clone session('end', Carbon::now()->endOfMonth());
|
||||
$start->subDay();
|
||||
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
@@ -196,7 +197,7 @@ class AccountController extends Controller
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function show(ARI $repository, Account $account)
|
||||
{
|
||||
@@ -204,15 +205,17 @@ class AccountController extends Controller
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$subTitle = $account->name;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$page = intval(Input::get('page'));
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
$count = $set->count();
|
||||
$subSet = $set->splice($offset, $pageSize);
|
||||
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$page = intval(Input::get('page'));
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
$count = $set->count();
|
||||
$subSet = $set->splice($offset, $pageSize);
|
||||
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
||||
$journals->setPath('accounts/show/' . $account->id);
|
||||
|
||||
// grouped other months thing:
|
||||
@@ -251,6 +254,7 @@ class AccountController extends Controller
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
return view('accounts.show', compact('account', 'what', 'entries', 'subTitleIcon', 'journals', 'subTitle'));
|
||||
}
|
||||
@@ -270,6 +274,7 @@ class AccountController extends Controller
|
||||
$end = Navigation::endOfPeriod($carbon, $range);
|
||||
$subTitle = $account->name . ' (' . Navigation::periodShow($start, $range) . ')';
|
||||
$page = intval(Input::get('page'));
|
||||
$page = $page === 0 ? 1 : $page;
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
@@ -285,7 +290,7 @@ class AccountController extends Controller
|
||||
* @param AccountFormRequest $request
|
||||
* @param AccountCrudInterface $crud
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function store(AccountFormRequest $request, AccountCrudInterface $crud)
|
||||
{
|
||||
@@ -295,7 +300,7 @@ class AccountController extends Controller
|
||||
'virtualBalance' => round($request->input('virtualBalance'), 2),
|
||||
'virtualBalanceCurrency' => intval($request->input('amount_currency_id_virtualBalance')),
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'user' => auth()->user()->id,
|
||||
'iban' => $request->input('iban'),
|
||||
'accountNumber' => $request->input('accountNumber'),
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
@@ -333,7 +338,7 @@ class AccountController extends Controller
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param Account $account
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(AccountFormRequest $request, AccountCrudInterface $crud, Account $account)
|
||||
{
|
||||
@@ -341,7 +346,7 @@ class AccountController extends Controller
|
||||
$accountData = [
|
||||
'name' => $request->input('name'),
|
||||
'active' => $request->input('active'),
|
||||
'user' => Auth::user()->id,
|
||||
'user' => auth()->user()->id,
|
||||
'iban' => $request->input('iban'),
|
||||
'accountNumber' => $request->input('accountNumber'),
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
|
77
app/Http/Controllers/Admin/ConfigurationController.php
Normal file
77
app/Http/Controllers/Admin/ConfigurationController.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* ConfigurationController.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\Http\Controllers\Admin;
|
||||
|
||||
|
||||
use Config;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\ConfigurationRequest;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Admin
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
/**
|
||||
* ConfigurationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
View::share('title', strval(trans('firefly.administration')));
|
||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = strval(trans('firefly.instance_configuration'));
|
||||
$subTitleIcon = 'fa-wrench';
|
||||
|
||||
// all available configuration and their default value in case
|
||||
// they don't exist yet.
|
||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||
|
||||
return view('admin.configuration.index', compact('subTitle', 'subTitleIcon', 'singleUserMode'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigurationRequest $request
|
||||
*/
|
||||
public function store(ConfigurationRequest $request)
|
||||
{
|
||||
// get config values:
|
||||
$singleUserMode = intval($request->get('single_user_mode')) === 1 ? true : false;
|
||||
|
||||
// store config values
|
||||
FireflyConfig::set('single_user_mode', $singleUserMode);
|
||||
|
||||
// flash message
|
||||
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::route('admin.configuration.index');
|
||||
}
|
||||
|
||||
}
|
136
app/Http/Controllers/Admin/DomainController.php
Normal file
136
app/Http/Controllers/Admin/DomainController.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
* DomainController.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\Http\Controllers\Admin;
|
||||
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class DomainController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Admin
|
||||
*/
|
||||
class DomainController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function domains()
|
||||
{
|
||||
|
||||
$title = strval(trans('firefly.administration'));
|
||||
$mainTitleIcon = 'fa-hand-spock-o';
|
||||
$subTitle = strval(trans('firefly.blocked_domains'));
|
||||
$subTitleIcon = 'fa-exclamation-circle';
|
||||
$domains = FireflyConfig::get('blocked-domains', [])->data;
|
||||
|
||||
// known domains
|
||||
$knownDomains = $this->getKnownDomains();
|
||||
|
||||
return view('admin.domains.index', compact('title', 'mainTitleIcon', 'knownDomains', 'subTitle', 'subTitleIcon', 'domains'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function manual(Request $request)
|
||||
{
|
||||
if (strlen($request->get('domain')) === 0) {
|
||||
Session::flash('error', trans('firefly.no_domain_filled_in'));
|
||||
|
||||
return redirect(route('admin.users.domains'));
|
||||
}
|
||||
|
||||
$domain = strtolower($request->get('domain'));
|
||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
||||
|
||||
if (in_array($domain, $blocked)) {
|
||||
Session::flash('error', trans('firefly.domain_already_blocked', ['domain' => $domain]));
|
||||
|
||||
return redirect(route('admin.users.domains'));
|
||||
}
|
||||
$blocked[] = $domain;
|
||||
FireflyConfig::set('blocked-domains', $blocked);
|
||||
|
||||
Session::flash('success', trans('firefly.domain_is_now_blocked', ['domain' => $domain]));
|
||||
|
||||
return redirect(route('admin.users.domains'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $domain
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function toggleDomain(string $domain)
|
||||
{
|
||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
||||
|
||||
if (in_array($domain, $blocked)) {
|
||||
$key = array_search($domain, $blocked);
|
||||
unset($blocked[$key]);
|
||||
sort($blocked);
|
||||
|
||||
FireflyConfig::set('blocked-domains', $blocked);
|
||||
Session::flash('message', trans('firefly.domain_now_unblocked', ['domain' => $domain]));
|
||||
|
||||
|
||||
return redirect(route('admin.users.domains'));
|
||||
|
||||
}
|
||||
|
||||
$blocked[] = $domain;
|
||||
|
||||
FireflyConfig::set('blocked-domains', $blocked);
|
||||
Session::flash('message', trans('firefly.domain_now_blocked', ['domain' => $domain]));
|
||||
|
||||
return redirect(route('admin.users.domains'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getKnownDomains(): array
|
||||
{
|
||||
$users = User::get();
|
||||
$set = [];
|
||||
$filtered = [];
|
||||
/** @var User $user */
|
||||
foreach ($users as $user) {
|
||||
$email = $user->email;
|
||||
$parts = explode('@', $email);
|
||||
$domain = $parts[1];
|
||||
$set[] = $domain;
|
||||
}
|
||||
$set = array_unique($set);
|
||||
// filter for already banned domains:
|
||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
||||
|
||||
foreach ($set as $domain) {
|
||||
// in the block array? ignore it.
|
||||
if (!in_array($domain, $blocked)) {
|
||||
$filtered[] = $domain;
|
||||
}
|
||||
}
|
||||
asort($filtered);
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
}
|
@@ -24,8 +24,23 @@ use Preferences;
|
||||
*/
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function edit(User $user)
|
||||
{
|
||||
return $user->id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function index(UserRepositoryInterface $repository)
|
||||
{
|
||||
@@ -61,4 +76,5 @@ class UserController extends Controller
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ use FireflyIII\Http\Requests\AttachmentFormRequest;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use Input;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
@@ -46,7 +47,7 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Attachment $attachment)
|
||||
{
|
||||
@@ -92,10 +93,12 @@ class AttachmentController extends Controller
|
||||
|
||||
if ($disk->exists($file)) {
|
||||
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
$content = Crypt::decrypt($disk->get($file));
|
||||
|
||||
Log::debug('Send file to user', ['file' => $quoted, 'size' => strlen($content)]);
|
||||
|
||||
return response(Crypt::decrypt($disk->get($file)), 200)
|
||||
return response($content, 200)
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Content-Type', 'application/octet-stream')
|
||||
->header('Content-Disposition', 'attachment; filename=' . $quoted)
|
||||
@@ -104,7 +107,7 @@ class AttachmentController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', $disk->size($file));
|
||||
->header('Content-Length', strlen($content));
|
||||
|
||||
}
|
||||
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
|
||||
@@ -113,7 +116,7 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Attachment $attachment)
|
||||
{
|
||||
|
@@ -11,20 +11,10 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
|
||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Session;
|
||||
use Swift_TransportException;
|
||||
use Validator;
|
||||
|
||||
|
||||
@@ -54,106 +44,6 @@ class AuthController extends Controller
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a login request to the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$this->validate($request, [$this->loginUsername() => 'required', 'password' => 'required',]);
|
||||
$throttles = $this->isUsingThrottlesLoginsTrait();
|
||||
|
||||
if ($throttles && $this->hasTooManyLoginAttempts($request)) {
|
||||
return $this->sendLockoutResponse($request);
|
||||
}
|
||||
|
||||
$credentials = $this->getCredentials($request);
|
||||
$credentials['blocked'] = 0; // most not be blocked.
|
||||
|
||||
if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
|
||||
return $this->handleUserWasAuthenticated($request, $throttles);
|
||||
}
|
||||
|
||||
// check if user is blocked:
|
||||
$errorMessage = '';
|
||||
/** @var User $foundUser */
|
||||
$foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first();
|
||||
if (!is_null($foundUser)) {
|
||||
// if it exists, show message:
|
||||
$code = strlen(strval($foundUser->blocked_code)) > 0 ? $foundUser->blocked_code : 'general_blocked';
|
||||
$errorMessage = strval(trans('firefly.' . $code . '_error', ['email' => $credentials['email']]));
|
||||
$this->reportBlockedUserLoginAttempt($foundUser, $code, $request->ip());
|
||||
}
|
||||
|
||||
if ($throttles) {
|
||||
$this->incrementLoginAttempts($request);
|
||||
}
|
||||
|
||||
return $this->sendFailedLoginResponse($request, $errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a registration request for the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @throws FireflyException
|
||||
* @throws \Illuminate\Foundation\Validation\ValidationException
|
||||
*/
|
||||
public function register(Request $request)
|
||||
{
|
||||
$validator = $this->validator($request->all());
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->throwValidationException(
|
||||
$request, $validator
|
||||
);
|
||||
}
|
||||
|
||||
$data = $request->all();
|
||||
$data['password'] = bcrypt($data['password']);
|
||||
|
||||
// is user email domain blocked?
|
||||
if ($this->isBlockedDomain($data['email'])) {
|
||||
$validator->getMessageBag()->add('email', (string)trans('validation.invalid_domain'));
|
||||
|
||||
$this->reportBlockedDomainRegistrationAttempt($data['email'], $request->ip());
|
||||
|
||||
$this->throwValidationException(
|
||||
$request, $validator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$user = $this->create($request->all());
|
||||
|
||||
// trigger user registration event:
|
||||
event(new UserRegistration($user, $request->ip()));
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.registered')));
|
||||
Session::flash('gaEventCategory', 'user');
|
||||
Session::flash('gaEventAction', 'new-registration');
|
||||
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application registration form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showRegistrationForm()
|
||||
{
|
||||
$showDemoWarning = env('SHOW_DEMO_WARNING', false);
|
||||
|
||||
return view('auth.register', compact('showDemoWarning'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
@@ -172,76 +62,6 @@ class AuthController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getBlockedDomains()
|
||||
{
|
||||
$set = explode(',', env('BLOCKED_DOMAINS', ''));
|
||||
$domains = [];
|
||||
foreach ($set as $entry) {
|
||||
$domain = trim($entry);
|
||||
if (strlen($domain) > 0) {
|
||||
$domains[] = $domain;
|
||||
}
|
||||
}
|
||||
|
||||
return $domains;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failed login message.
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFailedLoginMessage(string $message)
|
||||
{
|
||||
if (strlen($message) > 0) {
|
||||
return $message;
|
||||
}
|
||||
|
||||
return Lang::has('auth.failed')
|
||||
? Lang::get('auth.failed')
|
||||
: 'These credentials do not match our records.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isBlockedDomain(string $email)
|
||||
{
|
||||
$parts = explode('@', $email);
|
||||
$blocked = $this->getBlockedDomains();
|
||||
|
||||
if (isset($parts[1]) && in_array($parts[1], $blocked)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failed login response instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $message
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request, string $message)
|
||||
{
|
||||
return redirect()->back()
|
||||
->withInput($request->only($this->loginUsername(), 'remember'))
|
||||
->withErrors(
|
||||
[
|
||||
$this->loginUsername() => $this->getFailedLoginMessage($message),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
@@ -260,61 +80,5 @@ class AuthController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message home about a blocked domain and the address attempted to register.
|
||||
*
|
||||
* @param string $registrationMail
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
private function reportBlockedDomainRegistrationAttempt(string $registrationMail, string $ipAddress)
|
||||
{
|
||||
try {
|
||||
$email = env('SITE_OWNER', false);
|
||||
$parts = explode('@', $registrationMail);
|
||||
$domain = $parts[1];
|
||||
$fields = [
|
||||
'email_address' => $registrationMail,
|
||||
'blocked_domain' => $domain,
|
||||
'ip' => $ipAddress,
|
||||
];
|
||||
|
||||
Mail::send(
|
||||
['emails.blocked-registration-html', 'emails.blocked-registration'], $fields, function (Message $message) use ($email, $domain) {
|
||||
$message->to($email, $email)->subject('Blocked a registration attempt with domain ' . $domain . '.');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message home about the blocked attempt to login.
|
||||
* Perhaps in a later stage, simply log these messages.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $code
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
private function reportBlockedUserLoginAttempt(User $user, string $code, string $ipAddress)
|
||||
{
|
||||
|
||||
try {
|
||||
$email = env('SITE_OWNER', false);
|
||||
$fields = [
|
||||
'user_id' => $user->id,
|
||||
'user_address' => $user->email,
|
||||
'code' => $code,
|
||||
'ip' => $ipAddress,
|
||||
];
|
||||
|
||||
Mail::send(
|
||||
['emails.blocked-login-html', 'emails.blocked-login'], $fields, function (Message $message) use ($email, $user) {
|
||||
$message->to($email, $email)->subject('Blocked a login attempt from ' . trim($user->email) . '.');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\ResendConfirmation;
|
||||
use FireflyIII\Events\UserIsConfirmed;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -36,12 +36,13 @@ class ConfirmationController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
* @param Request $request
|
||||
* @param string $code
|
||||
*
|
||||
* @return mixed
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function doConfirmation(string $code)
|
||||
public function doConfirmation(Request $request, string $code)
|
||||
{
|
||||
// check user_confirmed_last_mail
|
||||
|
||||
@@ -51,8 +52,12 @@ class ConfirmationController extends Controller
|
||||
$maxDiff = config('firefly.confirmation_age');
|
||||
|
||||
if ($database === $code && ($now - $time <= $maxDiff)) {
|
||||
Preferences::setForUser(Auth::user(), 'user_confirmed', true);
|
||||
Preferences::setForUser(Auth::user(), 'user_confirmed_confirmed', time());
|
||||
|
||||
// trigger user registration event:
|
||||
event(new UserIsConfirmed(auth()->user(), $request->ip()));
|
||||
|
||||
Preferences::setForUser(auth()->user(), 'user_confirmed', true);
|
||||
Preferences::setForUser(auth()->user(), 'user_confirmed_confirmed', time());
|
||||
Session::flash('success', strval(trans('firefly.account_is_confirmed')));
|
||||
|
||||
return redirect(route('home'));
|
||||
@@ -62,6 +67,8 @@ class ConfirmationController extends Controller
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function resendConfirmation(Request $request)
|
||||
{
|
||||
@@ -71,7 +78,7 @@ class ConfirmationController extends Controller
|
||||
$owner = env('SITE_OWNER', 'mail@example.com');
|
||||
$view = 'auth.confirmation.no-resent';
|
||||
if ($now - $time > $maxDiff) {
|
||||
event(new ResendConfirmation(Auth::user(), $request->ip()));
|
||||
event(new ResendConfirmation(auth()->user(), $request->ip()));
|
||||
$view = 'auth.confirmation.resent';
|
||||
}
|
||||
|
||||
|
34
app/Http/Controllers/Auth/ForgotPasswordController.php
Executable file
34
app/Http/Controllers/Auth/ForgotPasswordController.php
Executable file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* ForgotPasswordController.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\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Class ForgotPasswordController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
*/
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
use SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('guest');
|
||||
}
|
||||
}
|
195
app/Http/Controllers/Auth/LoginController.php
Executable file
195
app/Http/Controllers/Auth/LoginController.php
Executable file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/**
|
||||
* LoginController.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\Http\Controllers\Auth;
|
||||
|
||||
use Config;
|
||||
use FireflyConfig;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Lang;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Swift_TransportException;
|
||||
|
||||
/**
|
||||
* Class LoginController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
*/
|
||||
class LoginController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles authenticating users for the application and
|
||||
| redirecting them to your home screen. The controller uses a trait
|
||||
| to conveniently provide its functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesUsers;
|
||||
|
||||
/**
|
||||
* Where to redirect users after login / registration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('guest', ['except' => 'logout']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a login request to the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$this->validateLogin($request);
|
||||
|
||||
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
||||
// the login attempts for this application. We'll key this by the username and
|
||||
// the IP address of the client making these requests into this application.
|
||||
if ($lockedOut = $this->hasTooManyLoginAttempts($request)) {
|
||||
$this->fireLockoutEvent($request);
|
||||
|
||||
return $this->sendLockoutResponse($request);
|
||||
}
|
||||
|
||||
$credentials = $this->credentials($request);
|
||||
$credentials['blocked'] = 0; // most not be blocked.
|
||||
|
||||
if ($this->guard()->attempt($credentials, $request->has('remember'))) {
|
||||
return $this->sendLoginResponse($request);
|
||||
}
|
||||
|
||||
// check if user is blocked:
|
||||
$errorMessage = '';
|
||||
/** @var User $foundUser */
|
||||
$foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first();
|
||||
if (!is_null($foundUser)) {
|
||||
// if it exists, show message:
|
||||
$code = strlen(strval($foundUser->blocked_code)) > 0 ? $foundUser->blocked_code : 'general_blocked';
|
||||
$errorMessage = strval(trans('firefly.' . $code . '_error', ['email' => $credentials['email']]));
|
||||
$this->reportBlockedUserLoginAttempt($foundUser, $code, $request->ip());
|
||||
}
|
||||
|
||||
// If the login attempt was unsuccessful we will increment the number of attempts
|
||||
// to login and redirect the user back to the login form. Of course, when this
|
||||
// user surpasses their maximum number of attempts they will get locked out.
|
||||
if (!$lockedOut) {
|
||||
$this->incrementLoginAttempts($request);
|
||||
}
|
||||
|
||||
return $this->sendFailedLoginResponse($request, $errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application login form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showLoginForm(Request $request)
|
||||
{
|
||||
// is allowed to?
|
||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||
$userCount = User::count();
|
||||
$allowRegistration = true;
|
||||
if ($singleUserMode === true && $userCount > 0) {
|
||||
$allowRegistration = false;
|
||||
}
|
||||
|
||||
$email = $request->old('email');
|
||||
$remember = $request->old('remember');
|
||||
|
||||
return view('auth.login', compact('allowRegistration', 'email', 'remember'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failed login message.
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFailedLoginMessage(string $message)
|
||||
{
|
||||
if (strlen($message) > 0) {
|
||||
return $message;
|
||||
}
|
||||
|
||||
return Lang::has('auth.failed') ? Lang::get('auth.failed') : 'These credentials do not match our records.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failed login response instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $message
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request, string $message)
|
||||
{
|
||||
return redirect()->back()
|
||||
->withInput($request->only($this->username(), 'remember'))
|
||||
->withErrors(
|
||||
[
|
||||
$this->username() => $this->getFailedLoginMessage($message),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message home about the blocked attempt to login.
|
||||
* Perhaps in a later stage, simply log these messages.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $code
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
private function reportBlockedUserLoginAttempt(User $user, string $code, string $ipAddress)
|
||||
{
|
||||
|
||||
try {
|
||||
$email = env('SITE_OWNER', false);
|
||||
$fields = [
|
||||
'user_id' => $user->id,
|
||||
'user_address' => $user->email,
|
||||
'code' => $code,
|
||||
'ip' => $ipAddress,
|
||||
];
|
||||
|
||||
Mail::send(
|
||||
['emails.blocked-login-html', 'emails.blocked-login'], $fields, function (Message $message) use ($email, $user) {
|
||||
$message->to($email, $email)->subject('Blocked a login attempt from ' . trim($user->email) . '.');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -23,6 +23,7 @@ use Illuminate\Support\Facades\Password;
|
||||
* Class PasswordController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
* @method getEmailSubject
|
||||
*/
|
||||
class PasswordController extends Controller
|
||||
{
|
||||
@@ -55,7 +56,7 @@ class PasswordController extends Controller
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
|
224
app/Http/Controllers/Auth/RegisterController.php
Executable file
224
app/Http/Controllers/Auth/RegisterController.php
Executable file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* RegisterController.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\Http\Controllers\Auth;
|
||||
|
||||
use Auth;
|
||||
use Config;
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Session;
|
||||
use Swift_TransportException;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* Class RegisterController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
*/
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles the registration of new users as well as their
|
||||
| validation and creation. By default this controller uses a trait to
|
||||
| provide this functionality without requiring any additional code.
|
||||
|
|
||||
*/
|
||||
|
||||
use RegistersUsers;
|
||||
|
||||
/**
|
||||
* Where to redirect users after login / registration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*/
|
||||
public function register(Request $request)
|
||||
{
|
||||
// is allowed to?
|
||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||
$userCount = User::count();
|
||||
if ($singleUserMode === true && $userCount > 0) {
|
||||
$message = 'Registration is currently not available.';
|
||||
|
||||
return view('error', compact('message'));
|
||||
}
|
||||
|
||||
|
||||
$validator = $this->validator($request->all());
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->throwValidationException($request, $validator);
|
||||
}
|
||||
|
||||
$data = $request->all();
|
||||
$data['password'] = bcrypt($data['password']);
|
||||
|
||||
// is user email domain blocked?
|
||||
if ($this->isBlockedDomain($data['email'])) {
|
||||
$validator->getMessageBag()->add('email', (string)trans('validation.invalid_domain'));
|
||||
|
||||
$this->reportBlockedDomainRegistrationAttempt($data['email'], $request->ip());
|
||||
|
||||
$this->throwValidationException($request, $validator);
|
||||
}
|
||||
|
||||
|
||||
$user = $this->create($request->all());
|
||||
|
||||
// trigger user registration event:
|
||||
event(new UserRegistration($user, $request->ip()));
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.registered')));
|
||||
Session::flash('gaEventCategory', 'user');
|
||||
Session::flash('gaEventAction', 'new-registration');
|
||||
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* OLD
|
||||
* Show the application registration form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showRegistrationForm(Request $request)
|
||||
{
|
||||
$showDemoWarning = config('firefly.show-demo-warning', false);
|
||||
|
||||
// is allowed to?
|
||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||
$userCount = User::count();
|
||||
if ($singleUserMode === true && $userCount > 0) {
|
||||
$message = 'Registration is currently not available.';
|
||||
|
||||
return view('error', compact('message'));
|
||||
}
|
||||
|
||||
$email = $request->old('email');
|
||||
|
||||
return view('auth.register', compact('showDemoWarning', 'email'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
protected function create(array $data)
|
||||
{
|
||||
return User::create(
|
||||
[
|
||||
'email' => $data['email'],
|
||||
'password' => bcrypt($data['password']),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
protected function validator(array $data)
|
||||
{
|
||||
return Validator::make(
|
||||
$data, [
|
||||
'email' => 'required|email|max:255|unique:users',
|
||||
'password' => 'required|min:6|confirmed',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getBlockedDomains()
|
||||
{
|
||||
return FireflyConfig::get('blocked-domains', [])->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isBlockedDomain(string $email)
|
||||
{
|
||||
$parts = explode('@', $email);
|
||||
$blocked = $this->getBlockedDomains();
|
||||
|
||||
if (isset($parts[1]) && in_array($parts[1], $blocked)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message home about a blocked domain and the address attempted to register.
|
||||
*
|
||||
* @param string $registrationMail
|
||||
* @param string $ipAddress
|
||||
*/
|
||||
private function reportBlockedDomainRegistrationAttempt(string $registrationMail, string $ipAddress)
|
||||
{
|
||||
try {
|
||||
$email = env('SITE_OWNER', false);
|
||||
$parts = explode('@', $registrationMail);
|
||||
$domain = $parts[1];
|
||||
$fields = [
|
||||
'email_address' => $registrationMail,
|
||||
'blocked_domain' => $domain,
|
||||
'ip' => $ipAddress,
|
||||
];
|
||||
|
||||
Mail::send(
|
||||
['emails.blocked-registration-html', 'emails.blocked-registration'], $fields, function (Message $message) use ($email, $domain) {
|
||||
$message->to($email, $email)->subject('Blocked a registration attempt with domain ' . $domain . '.');
|
||||
}
|
||||
);
|
||||
} catch (Swift_TransportException $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
44
app/Http/Controllers/Auth/ResetPasswordController.php
Executable file
44
app/Http/Controllers/Auth/ResetPasswordController.php
Executable file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* ResetPasswordController.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\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
|
||||
/**
|
||||
* Class ResetPasswordController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Auth
|
||||
*/
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset requests
|
||||
| and uses a simple trait to include this behavior. You're free to
|
||||
| explore this trait and override any methods you wish to tweak.
|
||||
|
|
||||
*/
|
||||
|
||||
use ResetsPasswords;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user