mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-11-02 12:15:55 +00:00
Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a6f299ae6 | ||
|
|
73f87e30c2 | ||
|
|
838ece2c89 | ||
|
|
d8b88ea2c0 | ||
|
|
5908951b75 | ||
|
|
0b41f4c4d2 | ||
|
|
35439d4fbc | ||
|
|
fdce40310f | ||
|
|
6b4785ae32 | ||
|
|
f74e8e9cb7 | ||
|
|
5a4eb7e09e | ||
|
|
3bc4df03cc | ||
|
|
5d585132fb | ||
|
|
eff4905883 | ||
|
|
8923ac4fe3 | ||
|
|
073535e5ed | ||
|
|
d304b90ca6 | ||
|
|
816c26e14e | ||
|
|
b1244ffa01 | ||
|
|
fc1342bff9 | ||
|
|
d7b95194b5 | ||
|
|
b58bdeccd2 | ||
|
|
f260b9bdee | ||
|
|
fb1bdc9ec5 | ||
|
|
697eff48fc | ||
|
|
c05019339a | ||
|
|
8438efaf41 | ||
|
|
81c019cc99 | ||
|
|
c773fdc435 | ||
|
|
c1406f51f1 | ||
|
|
92affd3440 | ||
|
|
d3da0652ef | ||
|
|
e3fbbd6cf1 | ||
|
|
fcff13470c | ||
|
|
e3061ee7e7 | ||
|
|
0ee305fc4a | ||
|
|
58b93fd0c4 | ||
|
|
b30217fa2d | ||
|
|
ae48eec3a2 | ||
|
|
948233ba27 | ||
|
|
c2db9b183a | ||
|
|
6d2b88fa0b | ||
|
|
1d5da825c5 | ||
|
|
330c9b53d6 | ||
|
|
751fe7d4fb | ||
|
|
9df1fc6e5d | ||
|
|
8d660f1701 | ||
|
|
4d61d3c4aa | ||
|
|
0457088c99 | ||
|
|
8e575da74e | ||
|
|
48ed28888e | ||
|
|
4084b1124e | ||
|
|
60ba607027 | ||
|
|
3df2c11b4a | ||
|
|
c93221923a | ||
|
|
375317e932 | ||
|
|
7ce527957a | ||
|
|
6946521199 | ||
|
|
18ee20e680 | ||
|
|
c53da15219 | ||
|
|
d4995e342f | ||
|
|
c9f14da294 | ||
|
|
e9c2446cba | ||
|
|
35f179625c | ||
|
|
39749aa113 | ||
|
|
ba65e982fd | ||
|
|
b50e5d7e59 | ||
|
|
a3148dc172 | ||
|
|
73f1491d2d | ||
|
|
28eb54dc96 | ||
|
|
21fb426524 | ||
|
|
d5710ca809 | ||
|
|
0ba6cdda17 | ||
|
|
afdcfa8525 | ||
|
|
5db4f8512b | ||
|
|
dc0c1b73bc | ||
|
|
f999257095 | ||
|
|
7182909e28 | ||
|
|
fe3f015171 | ||
|
|
5bb668be63 | ||
|
|
01de147900 | ||
|
|
a7e5fcc806 | ||
|
|
e2d187d74b | ||
|
|
48b0620629 | ||
|
|
19e9f382e4 | ||
|
|
446eaf6588 | ||
|
|
78deb1420d | ||
|
|
e092515dff | ||
|
|
81f6fef978 | ||
|
|
6a2f8fa9ee | ||
|
|
a79a8c8874 | ||
|
|
c39659b064 | ||
|
|
9a30fbd05a | ||
|
|
83f48418f6 | ||
|
|
bcd7b41c91 | ||
|
|
cefb7d12bc | ||
|
|
3c0c15103e | ||
|
|
a8a8afc2be | ||
|
|
49e32abd3f | ||
|
|
7977eefaca | ||
|
|
f1fa6c3108 | ||
|
|
2fa0d55f39 | ||
|
|
5bff509346 | ||
|
|
a147e9b74a | ||
|
|
0d87f7c4ca | ||
|
|
8c675615df | ||
|
|
7edd1bff40 | ||
|
|
3bfcb1f3ab | ||
|
|
7b6c63e6a8 | ||
|
|
5500e5b0aa | ||
|
|
e4d249e73c | ||
|
|
091f6e918b | ||
|
|
5d9b68c3e7 | ||
|
|
12a6a61100 | ||
|
|
7ce3b8d4ef | ||
|
|
3d9b855849 | ||
|
|
2346d2ec05 | ||
|
|
a4c081c8a5 | ||
|
|
316980efbd | ||
|
|
a05bc0eed0 | ||
|
|
4d1c271da6 | ||
|
|
0dd7ecbfbe | ||
|
|
0dc188b083 | ||
|
|
6a553f77f3 | ||
|
|
a74cef439b | ||
|
|
9a3cd27700 | ||
|
|
801c7c0ab6 | ||
|
|
a95a4e783a | ||
|
|
af1ee9db93 | ||
|
|
fcdb6fd2a7 | ||
|
|
97c0fb389d | ||
|
|
a9c3992331 | ||
|
|
a38e057fa7 | ||
|
|
f83aaf77f1 | ||
|
|
d92768ecbf | ||
|
|
b9308cd74a | ||
|
|
78b577bc9d | ||
|
|
7d247897ed | ||
|
|
5dcbdec491 | ||
|
|
9bf980431e | ||
|
|
da60bfbcff | ||
|
|
92553cbc7e | ||
|
|
8e48e53f17 | ||
|
|
2f9a4bb79a | ||
|
|
ac968dd6cd | ||
|
|
6e4f2c0c8a | ||
|
|
d662c18ed7 | ||
|
|
e4ea234707 | ||
|
|
0b526c0168 | ||
|
|
2acde5c72a | ||
|
|
ec8cf2c459 | ||
|
|
3598780d54 | ||
|
|
35dd8ac6e6 | ||
|
|
5ff7c7ffab | ||
|
|
399db47826 | ||
|
|
148956a60d | ||
|
|
3670053a58 | ||
|
|
e8e2b9704f | ||
|
|
fcdeebcc06 | ||
|
|
586ed82e88 | ||
|
|
cc400d1e2e | ||
|
|
6edbfb27aa | ||
|
|
8fc9251b93 | ||
|
|
10af888a97 | ||
|
|
89f2328846 | ||
|
|
48e8cd20b4 | ||
|
|
394ef23eda | ||
|
|
62aa1eb487 | ||
|
|
1500018ccc | ||
|
|
23fad62d46 | ||
|
|
3cbf00734f | ||
|
|
1dc17dd59d | ||
|
|
f8935c92ea | ||
|
|
de6f838413 | ||
|
|
e8a095e543 | ||
|
|
717c1d080e | ||
|
|
0ae9afd325 | ||
|
|
d1b56c2afa | ||
|
|
8ef7c5ac33 | ||
|
|
7180a40cd8 | ||
|
|
71804af624 | ||
|
|
85dc7f3643 | ||
|
|
a866d13b75 | ||
|
|
fcb5e4eabc | ||
|
|
ade1cf9c19 | ||
|
|
0f1ec7d003 | ||
|
|
7e038afece | ||
|
|
9bb8e182fa | ||
|
|
e94ae126fd | ||
|
|
5bb8c6a366 | ||
|
|
30844df5d4 | ||
|
|
63e4a410a7 | ||
|
|
ee9a5d91e2 | ||
|
|
171ab8a4c3 | ||
|
|
96740aaac4 | ||
|
|
2017720096 | ||
|
|
b77ea6d316 | ||
|
|
f5adb4047f | ||
|
|
b082858866 | ||
|
|
a8a014189d | ||
|
|
39ea9e85a7 | ||
|
|
a4d2ed74fc | ||
|
|
90f2e27f1f | ||
|
|
a3359ba47a | ||
|
|
1d2d3523d6 | ||
|
|
3f40751a1a | ||
|
|
b5b55e862c | ||
|
|
c64771b76b | ||
|
|
ea7ee7ee9a | ||
|
|
a1f797c4d1 | ||
|
|
d0c92a2244 | ||
|
|
6e90c033b1 | ||
|
|
24f62b8fce | ||
|
|
d43936155c | ||
|
|
39dab4fdd9 | ||
|
|
c0fdf44ad2 | ||
|
|
4d91f7d23a | ||
|
|
49af6522a8 | ||
|
|
3c5f9487a8 | ||
|
|
f5cb87f5c3 | ||
|
|
cf543613c9 | ||
|
|
5c239c91db | ||
|
|
9920504232 | ||
|
|
5540697dbd | ||
|
|
b355c18e0c | ||
|
|
1e90485c5f | ||
|
|
dc784c53b5 | ||
|
|
5a47391a64 | ||
|
|
8a106bd16a | ||
|
|
a31ac79173 | ||
|
|
0d0a604254 | ||
|
|
724d25f2c2 | ||
|
|
8ed22d452d | ||
|
|
d7fef45a56 | ||
|
|
dc22802dec | ||
|
|
ce5af7b1d9 | ||
|
|
0a147e5c9c | ||
|
|
7d21255f7f | ||
|
|
13f952f182 | ||
|
|
b494be228b | ||
|
|
0fdaac53d0 | ||
|
|
e1b3a08878 | ||
|
|
dc893588b0 | ||
|
|
b9fcc443ec | ||
|
|
d8586c8043 | ||
|
|
4252a3e53b | ||
|
|
dbb5cdb9cf | ||
|
|
3ec8a8c375 |
100
CHANGELOG.md
100
CHANGELOG.md
@@ -2,7 +2,105 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [4.0.0] - 2015-05-25
|
## [4.1.4] - 2016-10-30
|
||||||
|
### Added
|
||||||
|
- New Dockerfile thanks to @schoentoon
|
||||||
|
- Added changing the destination account as rule action.
|
||||||
|
- Added changing the source account as rule action.
|
||||||
|
- Can convert transactions into different types.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changed the export routine to be more future-proof.
|
||||||
|
- Improved help routine.
|
||||||
|
- Integrated CrowdIn translations.
|
||||||
|
- Simplified reports
|
||||||
|
- Change error message to refer to solution.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- #367 thanks to @HungryFeline
|
||||||
|
- #366 thanks to @3mz3t
|
||||||
|
- #362 and #341 thanks to @bnw
|
||||||
|
- #355 thanks to @roberthorlings
|
||||||
|
|
||||||
|
## [4.1.3] - 2016-10-22
|
||||||
|
### Fixed
|
||||||
|
- Some event handlers called the wrong method.
|
||||||
|
|
||||||
|
## [4.1.2] - 2016-10-22
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- A bug is fixed in the journal event handler that prevented Firefly III from actually storing journals.
|
||||||
|
|
||||||
|
## [4.1.1] - 2016-10-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Option to show deposit accounts on the front page.
|
||||||
|
- Script to upgrade split transactions
|
||||||
|
- Can now save notes on piggy banks.
|
||||||
|
- Extend user admin options.
|
||||||
|
- Run import jobs from the command line
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- New preferences screen layout.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
- ``firefly:import`` is now ``firefly:start-import``
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Lots of old code
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- #357, where non utf-8 files would break Firefly.
|
||||||
|
- Tab delimiter is not properly loaded from import configuration (@roberthorlings)
|
||||||
|
- System response to yearly bills
|
||||||
|
|
||||||
|
## [4.0.2] - 2016-10-14
|
||||||
|
### Added
|
||||||
|
- Added ``intl`` dependency to composer file to ease installation (thanks @telyn)
|
||||||
|
- Added support for Croatian.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Updated all copyright notices to refer to the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||||
|
- Fixed #344
|
||||||
|
- Fixed #346, thanks to @SanderKleykens
|
||||||
|
- #351
|
||||||
|
- Did some internal remodelling.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- PostgreSQL compatibility thanks to @SanderKleykens
|
||||||
|
- @RobertHorlings fixed a bug in the ABN Amro import specific.
|
||||||
|
|
||||||
|
|
||||||
|
## [4.0.1] - 2016-10-04
|
||||||
|
### Added
|
||||||
|
- New ING import specific by @tomwerf
|
||||||
|
- New Presidents Choice specific to fix #307
|
||||||
|
- Added some trimming (#335)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed a bug where incoming transactions would not be properly filtered in several reports.
|
||||||
|
- #334 by @cyberkov
|
||||||
|
- #337
|
||||||
|
- #336
|
||||||
|
- #338 found by @roberthorlings
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [4.0.0] - 2015-09-26
|
||||||
### Added
|
### Added
|
||||||
- Upgraded to Laravel 5.3, most other libraries upgraded as well.
|
- Upgraded to Laravel 5.3, most other libraries upgraded as well.
|
||||||
- Added GBP as currency, thanks to @Mortalife
|
- Added GBP as currency, thanks to @Mortalife
|
||||||
|
|||||||
42
Dockerfile
Normal file
42
Dockerfile
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
FROM php:7-apache
|
||||||
|
|
||||||
|
RUN apt-get update -y && \
|
||||||
|
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
libjpeg62-turbo-dev \
|
||||||
|
libpng12-dev \
|
||||||
|
libicu-dev \
|
||||||
|
libmcrypt-dev \
|
||||||
|
libedit-dev \
|
||||||
|
libtidy-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libbz2-dev && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN docker-php-ext-install -j$(nproc) curl gd intl json mcrypt readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2
|
||||||
|
|
||||||
|
# Enable apache mod rewrite..
|
||||||
|
RUN a2enmod rewrite
|
||||||
|
|
||||||
|
# Setup the Composer installer
|
||||||
|
RUN curl -o /tmp/composer-setup.php https://getcomposer.org/installer && \
|
||||||
|
curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig && \
|
||||||
|
php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" && \
|
||||||
|
chmod +x /tmp/composer-setup.php && \
|
||||||
|
php /tmp/composer-setup.php && \
|
||||||
|
mv composer.phar /usr/local/bin/composer && \
|
||||||
|
rm -f /tmp/composer-setup.{php,sig}
|
||||||
|
|
||||||
|
ADD . /var/www/firefly-iii
|
||||||
|
RUN chown -R www-data:www-data /var/www/
|
||||||
|
ADD docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||||
|
|
||||||
|
USER www-data
|
||||||
|
|
||||||
|
WORKDIR /var/www/firefly-iii
|
||||||
|
|
||||||
|
RUN composer install --no-scripts --no-dev
|
||||||
|
|
||||||
|
USER root
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* ConfigureLogging.php
|
* ConfigureLogging.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
152
app/Console/Commands/CreateImport.php
Normal file
152
app/Console/Commands/CreateImport.php
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* CreateImport.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands;
|
||||||
|
|
||||||
|
use Artisan;
|
||||||
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CreateImport
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Console\Commands
|
||||||
|
*/
|
||||||
|
class CreateImport extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Use this command to create a new import. Your user ID can be found on the /profile page.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly:create-import {file} {configuration} {--user=1} {--type=csv} {--start}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
// find the file
|
||||||
|
/** @var UserRepositoryInterface $userRepository */
|
||||||
|
$userRepository = app(UserRepositoryInterface::class);
|
||||||
|
$file = $this->argument('file');
|
||||||
|
$configuration = $this->argument('configuration');
|
||||||
|
$user = $userRepository->find(intval($this->option('user')));
|
||||||
|
$cwd = getcwd();
|
||||||
|
$type = strtolower($this->option('type'));
|
||||||
|
|
||||||
|
if (!$this->validArguments()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to parse configuration data:
|
||||||
|
$configurationData = json_decode(file_get_contents($configuration));
|
||||||
|
if (is_null($configurationData)) {
|
||||||
|
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info(sprintf('Going to create a job to import file: %s', $file));
|
||||||
|
$this->info(sprintf('Using configuration file: %s', $configuration));
|
||||||
|
$this->info(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
||||||
|
$this->info(sprintf('Type of import: %s', $type));
|
||||||
|
|
||||||
|
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||||
|
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
|
||||||
|
|
||||||
|
$job = $jobRepository->create($type);
|
||||||
|
$this->line(sprintf('Created job "%s"...', $job->key));
|
||||||
|
|
||||||
|
// put the file in the proper place:
|
||||||
|
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
|
||||||
|
$this->line('Stored import data...');
|
||||||
|
|
||||||
|
// store the configuration in the job:
|
||||||
|
$job->configuration = $configurationData;
|
||||||
|
$job->status = 'settings_complete';
|
||||||
|
$job->save();
|
||||||
|
$this->line('Stored configuration...');
|
||||||
|
|
||||||
|
// if user wants to run it, do!
|
||||||
|
if ($this->option('start') === true) {
|
||||||
|
$this->line('The import will start in a moment. This process is not visible...');
|
||||||
|
Log::debug('Go for import!');
|
||||||
|
Artisan::call('firefly:start-import', ['key' => $job->key]);
|
||||||
|
$this->line('Done!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validArguments(): bool
|
||||||
|
{
|
||||||
|
// find the file
|
||||||
|
/** @var UserRepositoryInterface $userRepository */
|
||||||
|
$userRepository = app(UserRepositoryInterface::class);
|
||||||
|
$file = $this->argument('file');
|
||||||
|
$configuration = $this->argument('configuration');
|
||||||
|
$user = $userRepository->find(intval($this->option('user')));
|
||||||
|
$cwd = getcwd();
|
||||||
|
$validTypes = array_keys(config('firefly.import_formats'));
|
||||||
|
$type = strtolower($this->option('type'));
|
||||||
|
|
||||||
|
if (is_null($user->id)) {
|
||||||
|
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!in_array($type, $validTypes)) {
|
||||||
|
$this->error(sprintf('Cannot import file of type "%s"', $type));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
$this->error(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($configuration)) {
|
||||||
|
$this->error(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* EncryptFile.php
|
* EncryptFile.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Import.php
|
* Import.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -30,14 +32,14 @@ class Import extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Import stuff into Firefly III.';
|
protected $description = 'This will start a new import.';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'firefly:import {key}';
|
protected $signature = 'firefly:start-import {key}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
* Create a new command instance.
|
||||||
@@ -55,9 +57,12 @@ class Import extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
Log::debug('Start start-import command');
|
||||||
$jobKey = $this->argument('key');
|
$jobKey = $this->argument('key');
|
||||||
$job = ImportJob::whereKey($jobKey)->first();
|
$job = ImportJob::whereKey($jobKey)->first();
|
||||||
if (!$this->isValid($job)) {
|
if (!$this->isValid($job)) {
|
||||||
|
Log::error('Job is not valid for some reason. Exit.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ScanAttachments.php
|
* ScanAttachments.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
121
app/Console/Commands/UpgradeDatabase.php
Normal file
121
app/Console/Commands/UpgradeDatabase.php
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* UpgradeDatabase.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands;
|
||||||
|
|
||||||
|
|
||||||
|
use DB;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UpgradeDatabase
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Console\Commands
|
||||||
|
*/
|
||||||
|
class UpgradeDatabase extends Command
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Will run various commands to update database records.';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly:upgrade-database';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->setTransactionIdentifier();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird.
|
||||||
|
*/
|
||||||
|
private function setTransactionIdentifier()
|
||||||
|
{
|
||||||
|
$subQuery = TransactionJournal
|
||||||
|
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
|
->whereNull('transactions.deleted_at')
|
||||||
|
->groupBy(['transaction_journals.id'])
|
||||||
|
->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]);
|
||||||
|
|
||||||
|
$result = DB::table(DB::raw('(' . $subQuery->toSql() . ') AS derived'))
|
||||||
|
->mergeBindings($subQuery->getQuery())
|
||||||
|
->where('t_count', '>', 2)
|
||||||
|
->select(['id', 't_count']);
|
||||||
|
$journalIds = array_unique($result->pluck('id')->toArray());
|
||||||
|
|
||||||
|
foreach ($journalIds as $journalId) {
|
||||||
|
// grab all positive transactiosn from this journal that are not deleted.
|
||||||
|
// for each one, grab the negative opposing one which has 0 as an identifier and give it the same identifier.
|
||||||
|
$identifier = 0;
|
||||||
|
$processed = [];
|
||||||
|
$transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get();
|
||||||
|
/** @var Transaction $transaction */
|
||||||
|
foreach ($transactions as $transaction) {
|
||||||
|
// find opposing:
|
||||||
|
$amount = bcmul(strval($transaction->amount), '-1');
|
||||||
|
|
||||||
|
try {
|
||||||
|
/** @var Transaction $opposing */
|
||||||
|
$opposing = Transaction
|
||||||
|
::where('transaction_journal_id', $journalId)
|
||||||
|
->where('amount', $amount)->where('identifier', '=', 0)
|
||||||
|
->whereNotIn('id', $processed)
|
||||||
|
->first();
|
||||||
|
} catch (QueryException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
|
||||||
|
$this->error('This field is required for Firefly III version ' . config('firefly.version') . ' to run.');
|
||||||
|
$this->error('Please run "php artisan migrate" to add this field to the table.');
|
||||||
|
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
if (!is_null($opposing)) {
|
||||||
|
// give both a new identifier:
|
||||||
|
$transaction->identifier = $identifier;
|
||||||
|
$transaction->save();
|
||||||
|
$opposing->identifier = $identifier;
|
||||||
|
$opposing->save();
|
||||||
|
$processed[] = $transaction->id;
|
||||||
|
$processed[] = $opposing->id;
|
||||||
|
$this->line(sprintf('Database upgrade for journal #%d, transactions #%d and #%d', $journalId, $transaction->id, $opposing->id));
|
||||||
|
}
|
||||||
|
$identifier++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* UpgradeFireflyInstructions.php
|
* UpgradeFireflyInstructions.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* VerifyDatabase.php
|
* VerifyDatabase.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -13,6 +15,7 @@ namespace FireflyIII\Console\Commands;
|
|||||||
|
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
@@ -82,6 +85,9 @@ class VerifyDatabase extends Command
|
|||||||
|
|
||||||
// transfers with budgets.
|
// transfers with budgets.
|
||||||
$this->reportTransfersBudgets();
|
$this->reportTransfersBudgets();
|
||||||
|
|
||||||
|
// report on journals with the wrong types of accounts.
|
||||||
|
$this->reportIncorrectJournals();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,11 +201,50 @@ class VerifyDatabase extends Command
|
|||||||
$date = is_null($entry->transaction_deleted_at) ? $entry->journal_deleted_at : $entry->transaction_deleted_at;
|
$date = is_null($entry->transaction_deleted_at) ? $entry->journal_deleted_at : $entry->transaction_deleted_at;
|
||||||
$this->error(
|
$this->error(
|
||||||
'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' .
|
'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' .
|
||||||
' Find it in the table called `accounts` and change the `deleted_at` field to: "' . $date . '"'
|
' Find it in the table called "accounts" and change the "deleted_at" field to: "' . $date . '"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function reportIncorrectJournals()
|
||||||
|
{
|
||||||
|
$configuration = [
|
||||||
|
// a withdrawal can not have revenue account:
|
||||||
|
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
|
||||||
|
|
||||||
|
// deposit cannot have an expense account:
|
||||||
|
TransactionType::DEPOSIT => [AccountType::EXPENSE],
|
||||||
|
|
||||||
|
// transfer cannot have either:
|
||||||
|
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
||||||
|
];
|
||||||
|
foreach ($configuration as $transactionType => $accountTypes) {
|
||||||
|
$set = TransactionJournal
|
||||||
|
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||||
|
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||||
|
->leftJoin('account_types', 'account_types.id', 'accounts.account_type_id')
|
||||||
|
->leftJoin('users', 'users.id', '=', 'transaction_journals.user_id')
|
||||||
|
->where('transaction_types.type', $transactionType)
|
||||||
|
->whereIn('account_types.type', $accountTypes)
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
|
->get(['transaction_journals.id', 'transaction_journals.user_id', 'users.email', 'account_types.type as a_type', 'transaction_types.type']);
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$this->error(
|
||||||
|
sprintf(
|
||||||
|
'Transaction journal #%d (user #%d, %s) is of type "%s" but ' .
|
||||||
|
'is linked to a "%s". The transaction journal should be recreated.',
|
||||||
|
$entry->id,
|
||||||
|
$entry->user_id,
|
||||||
|
$entry->email,
|
||||||
|
$entry->type,
|
||||||
|
$entry->a_type
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any deleted transaction journals that have transactions that are NOT deleted:
|
* Any deleted transaction journals that have transactions that are NOT deleted:
|
||||||
*/
|
*/
|
||||||
@@ -222,7 +267,7 @@ class VerifyDatabase extends Command
|
|||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$this->error(
|
$this->error(
|
||||||
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
|
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
|
||||||
' Find it in the table called `transactions` and change the `deleted_at` field to: "' . $entry->journal_deleted . '"'
|
' Find it in the table called "transactions" and change the "deleted_at" field to: "' . $entry->journal_deleted . '"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +285,7 @@ class VerifyDatabase extends Command
|
|||||||
|
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$this->error(
|
$this->error(
|
||||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table `transaction_journals` and delete the entry with id #' . $entry->id
|
'Error: Journal #' . $entry->id . ' has zero transactions. Open table "transaction_journals" and delete the entry with id #' . $entry->id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +346,7 @@ class VerifyDatabase extends Command
|
|||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$this->error(
|
$this->error(
|
||||||
'Error: Transaction journal #' . $entry->journal_id . ' should have been deleted, but has not.' .
|
'Error: Transaction journal #' . $entry->journal_id . ' should have been deleted, but has not.' .
|
||||||
' Find it in the table called `transaction_journals` and change the `deleted_at` field to: "' . $entry->transaction_deleted . '"'
|
' Find it in the table called "transaction_journals" and change the "deleted_at" field to: "' . $entry->transaction_deleted . '"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,21 @@
|
|||||||
* Kernel.php
|
* Kernel.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|
||||||
namespace FireflyIII\Console;
|
namespace FireflyIII\Console;
|
||||||
|
|
||||||
|
use FireflyIII\Console\Commands\CreateImport;
|
||||||
use FireflyIII\Console\Commands\EncryptFile;
|
use FireflyIII\Console\Commands\EncryptFile;
|
||||||
use FireflyIII\Console\Commands\Import;
|
use FireflyIII\Console\Commands\Import;
|
||||||
use FireflyIII\Console\Commands\ScanAttachments;
|
use FireflyIII\Console\Commands\ScanAttachments;
|
||||||
|
use FireflyIII\Console\Commands\UpgradeDatabase;
|
||||||
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
||||||
use FireflyIII\Console\Commands\VerifyDatabase;
|
use FireflyIII\Console\Commands\VerifyDatabase;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
@@ -55,8 +59,10 @@ class Kernel extends ConsoleKernel
|
|||||||
UpgradeFireflyInstructions::class,
|
UpgradeFireflyInstructions::class,
|
||||||
VerifyDatabase::class,
|
VerifyDatabase::class,
|
||||||
Import::class,
|
Import::class,
|
||||||
|
CreateImport::class,
|
||||||
EncryptFile::class,
|
EncryptFile::class,
|
||||||
ScanAttachments::class,
|
ScanAttachments::class,
|
||||||
|
UpgradeDatabase::class,
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,534 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* AccountCrud.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Crud\Account;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use DB;
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use FireflyIII\Models\AccountMeta;
|
|
||||||
use FireflyIII\Models\AccountType;
|
|
||||||
use FireflyIII\Models\Transaction;
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class AccountCrud
|
|
||||||
*
|
|
||||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Crud\Account
|
|
||||||
*/
|
|
||||||
class AccountCrud implements AccountCrudInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/** @var User */
|
|
||||||
private $user;
|
|
||||||
/** @var array */
|
|
||||||
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AccountCrud constructor.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
*/
|
|
||||||
public function __construct(User $user)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param Account $moveTo
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function destroy(Account $account, Account $moveTo): bool
|
|
||||||
{
|
|
||||||
if (!is_null($moveTo->id)) {
|
|
||||||
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
|
|
||||||
}
|
|
||||||
if (!is_null($account)) {
|
|
||||||
$account->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $accountId
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function find(int $accountId): Account
|
|
||||||
{
|
|
||||||
$account = $this->user->accounts()->find($accountId);
|
|
||||||
if (is_null($account)) {
|
|
||||||
return new Account;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $number
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function findByAccountNumber(string $number, array $types): Account
|
|
||||||
{
|
|
||||||
$query = $this->user->accounts()
|
|
||||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
|
||||||
->where('account_meta.name', 'accountNumber')
|
|
||||||
->where('account_meta.data', json_encode($number));
|
|
||||||
|
|
||||||
if (count($types) > 0) {
|
|
||||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
|
||||||
$query->whereIn('account_types.type', $types);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var Collection $accounts */
|
|
||||||
$accounts = $query->get(['accounts.*']);
|
|
||||||
if ($accounts->count() > 0) {
|
|
||||||
return $accounts->first();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $iban
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function findByIban(string $iban, array $types): Account
|
|
||||||
{
|
|
||||||
$query = $this->user->accounts()->where('iban', '!=', '');
|
|
||||||
|
|
||||||
if (count($types) > 0) {
|
|
||||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
|
||||||
$query->whereIn('account_types.type', $types);
|
|
||||||
}
|
|
||||||
|
|
||||||
$accounts = $query->get(['accounts.*']);
|
|
||||||
/** @var Account $account */
|
|
||||||
foreach ($accounts as $account) {
|
|
||||||
if ($account->iban === $iban) {
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function findByName(string $name, array $types): Account
|
|
||||||
{
|
|
||||||
$query = $this->user->accounts();
|
|
||||||
|
|
||||||
if (count($types) > 0) {
|
|
||||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
|
||||||
$query->whereIn('account_types.type', $types);
|
|
||||||
|
|
||||||
}
|
|
||||||
Log::debug(sprintf('Searching for account named %s of the following type(s)', $name), ['types' => $types]);
|
|
||||||
|
|
||||||
$accounts = $query->get(['accounts.*']);
|
|
||||||
/** @var Account $account */
|
|
||||||
foreach ($accounts as $account) {
|
|
||||||
if ($account->name === $name) {
|
|
||||||
Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id));
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log::debug('Found nothing.');
|
|
||||||
|
|
||||||
return new Account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $accountIds
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getAccountsById(array $accountIds): Collection
|
|
||||||
{
|
|
||||||
/** @var Collection $result */
|
|
||||||
$query = $this->user->accounts()->with(
|
|
||||||
['accountmeta' => function (HasMany $query) {
|
|
||||||
$query->where('name', 'accountRole');
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (count($accountIds) > 0) {
|
|
||||||
$query->whereIn('accounts.id', $accountIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $query->get(['accounts.*']);
|
|
||||||
$result = $result->sortBy(
|
|
||||||
function (Account $account) {
|
|
||||||
return strtolower($account->name);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getAccountsByType(array $types): Collection
|
|
||||||
{
|
|
||||||
/** @var Collection $result */
|
|
||||||
$query = $this->user->accounts()->with(
|
|
||||||
['accountmeta' => function (HasMany $query) {
|
|
||||||
$query->where('name', 'accountRole');
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
if (count($types) > 0) {
|
|
||||||
$query->accountTypeIn($types);
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $query->get(['accounts.*']);
|
|
||||||
$result = $result->sortBy(
|
|
||||||
function (Account $account) {
|
|
||||||
return strtolower($account->name);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function store(array $data): Account
|
|
||||||
{
|
|
||||||
$newAccount = $this->storeAccount($data);
|
|
||||||
if (!is_null($newAccount->id)) {
|
|
||||||
$this->storeMetadata($newAccount, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($data['openingBalance'] != 0) {
|
|
||||||
$this->storeInitialBalance($newAccount, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $newAccount;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $account
|
|
||||||
* @param $name
|
|
||||||
* @param $value
|
|
||||||
*
|
|
||||||
* @return AccountMeta
|
|
||||||
*/
|
|
||||||
public function storeMeta(Account $account, string $name, $value): AccountMeta
|
|
||||||
{
|
|
||||||
return AccountMeta::create(['name' => $name, 'data' => $value, 'account_id' => $account->id,]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function update(Account $account, array $data): Account
|
|
||||||
{
|
|
||||||
// update the account:
|
|
||||||
$account->name = $data['name'];
|
|
||||||
$account->active = $data['active'] == '1' ? true : false;
|
|
||||||
$account->virtual_balance = $data['virtualBalance'];
|
|
||||||
$account->iban = $data['iban'];
|
|
||||||
$account->save();
|
|
||||||
|
|
||||||
$this->updateMetadata($account, $data);
|
|
||||||
$this->updateInitialBalance($account, $data);
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param string $type
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function updateAccountType(Account $account, string $type): Account
|
|
||||||
{
|
|
||||||
$type = AccountType::whereType($type)->first();
|
|
||||||
if (!is_null($type)) {
|
|
||||||
$account->accountType()->associate($type);
|
|
||||||
$account->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->find($account->id);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
protected function storeAccount(array $data): Account
|
|
||||||
{
|
|
||||||
$type = config('firefly.accountTypeByIdentifier.' . $data['accountType']);
|
|
||||||
$accountType = AccountType::whereType($type)->first();
|
|
||||||
$newAccount = new Account(
|
|
||||||
[
|
|
||||||
'user_id' => $data['user'],
|
|
||||||
'account_type_id' => $accountType->id,
|
|
||||||
'name' => $data['name'],
|
|
||||||
'virtual_balance' => $data['virtualBalance'],
|
|
||||||
'active' => $data['active'] === true ? true : false,
|
|
||||||
'iban' => $data['iban'],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$newAccount->isValid()) {
|
|
||||||
// does the account already exist?
|
|
||||||
$searchData = [
|
|
||||||
'user_id' => $data['user'],
|
|
||||||
'account_type_id' => $accountType->id,
|
|
||||||
'virtual_balance' => $data['virtualBalance'],
|
|
||||||
'name' => $data['name'],
|
|
||||||
'iban' => $data['iban'],
|
|
||||||
];
|
|
||||||
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
|
||||||
if (!$existingAccount) {
|
|
||||||
Log::error('Account create error', $newAccount->getErrors()->toArray());
|
|
||||||
|
|
||||||
return new Account;
|
|
||||||
}
|
|
||||||
$newAccount = $existingAccount;
|
|
||||||
|
|
||||||
}
|
|
||||||
$newAccount->save();
|
|
||||||
|
|
||||||
return $newAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return TransactionJournal
|
|
||||||
*/
|
|
||||||
protected function storeInitialBalance(Account $account, array $data): TransactionJournal
|
|
||||||
{
|
|
||||||
$amount = $data['openingBalance'];
|
|
||||||
$user = $data['user'];
|
|
||||||
$name = $data['name'];
|
|
||||||
$opposing = $this->storeOpposingAccount($amount, $user, $name);
|
|
||||||
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
|
||||||
$journal = TransactionJournal::create(
|
|
||||||
[
|
|
||||||
'user_id' => $data['user'],
|
|
||||||
'transaction_type_id' => $transactionType->id,
|
|
||||||
'transaction_currency_id' => $data['openingBalanceCurrency'],
|
|
||||||
'description' => 'Initial balance for "' . $account->name . '"',
|
|
||||||
'completed' => true,
|
|
||||||
'date' => $data['openingBalanceDate'],
|
|
||||||
'encrypted' => true,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$firstAccount = $account;
|
|
||||||
$secondAccount = $opposing;
|
|
||||||
$firstAmount = $amount;
|
|
||||||
$secondAmount = $amount * -1;
|
|
||||||
|
|
||||||
if ($data['openingBalance'] < 0) {
|
|
||||||
$firstAccount = $opposing;
|
|
||||||
$secondAccount = $account;
|
|
||||||
$firstAmount = $amount * -1;
|
|
||||||
$secondAmount = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
$one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
|
|
||||||
$one->save();// first transaction: from
|
|
||||||
$two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]);
|
|
||||||
$two->save(); // second transaction: to
|
|
||||||
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param array $data
|
|
||||||
*/
|
|
||||||
protected function storeMetadata(Account $account, array $data)
|
|
||||||
{
|
|
||||||
foreach ($this->validFields as $field) {
|
|
||||||
if (isset($data[$field])) {
|
|
||||||
$metaData = new AccountMeta(
|
|
||||||
[
|
|
||||||
'account_id' => $account->id,
|
|
||||||
'name' => $field,
|
|
||||||
'data' => $data[$field],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
$metaData->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function updateInitialBalance(Account $account, array $data): bool
|
|
||||||
{
|
|
||||||
$openingBalance = $this->openingBalanceTransaction($account);
|
|
||||||
if ($data['openingBalance'] != 0) {
|
|
||||||
if (!is_null($openingBalance->id)) {
|
|
||||||
$date = $data['openingBalanceDate'];
|
|
||||||
$amount = $data['openingBalance'];
|
|
||||||
|
|
||||||
return $this->updateJournal($account, $openingBalance, $date, $amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->storeInitialBalance($account, $data);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// else, delete it:
|
|
||||||
if ($openingBalance) { // opening balance is zero, should we delete it?
|
|
||||||
$openingBalance->delete(); // delete existing opening balance.
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function updateMetadata(Account $account, array $data)
|
|
||||||
{
|
|
||||||
foreach ($this->validFields as $field) {
|
|
||||||
$entry = $account->accountMeta()->where('name', $field)->first();
|
|
||||||
|
|
||||||
if (isset($data[$field])) {
|
|
||||||
// update if new data is present:
|
|
||||||
if (!is_null($entry)) {
|
|
||||||
$entry->data = $data[$field];
|
|
||||||
$entry->save();
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$metaData = new AccountMeta(
|
|
||||||
[
|
|
||||||
'account_id' => $account->id,
|
|
||||||
'name' => $field,
|
|
||||||
'data' => $data[$field],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
$metaData->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
*
|
|
||||||
* @return TransactionJournal|null
|
|
||||||
*/
|
|
||||||
private function openingBalanceTransaction(Account $account): TransactionJournal
|
|
||||||
{
|
|
||||||
$journal = TransactionJournal
|
|
||||||
::sortCorrectly()
|
|
||||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
|
||||||
->where('transactions.account_id', $account->id)
|
|
||||||
->transactionTypes([TransactionType::OPENING_BALANCE])
|
|
||||||
->first(['transaction_journals.*']);
|
|
||||||
if (is_null($journal)) {
|
|
||||||
return new TransactionJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param float $amount
|
|
||||||
* @param int $user
|
|
||||||
* @param string $name
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
private function storeOpposingAccount(float $amount, int $user, string $name):Account
|
|
||||||
{
|
|
||||||
$type = $amount < 0 ? 'expense' : 'revenue';
|
|
||||||
$opposingData = [
|
|
||||||
'user' => $user,
|
|
||||||
'accountType' => $type,
|
|
||||||
'name' => $name . ' initial balance',
|
|
||||||
'active' => false,
|
|
||||||
'iban' => '',
|
|
||||||
'virtualBalance' => 0,
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->storeAccount($opposingData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
* @param Carbon $date
|
|
||||||
* @param float $amount
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function updateJournal(Account $account, TransactionJournal $journal, Carbon $date, float $amount): bool
|
|
||||||
{
|
|
||||||
// update date:
|
|
||||||
$journal->date = $date;
|
|
||||||
$journal->save();
|
|
||||||
// update transactions:
|
|
||||||
/** @var Transaction $transaction */
|
|
||||||
foreach ($journal->transactions()->get() as $transaction) {
|
|
||||||
if ($account->id == $transaction->account_id) {
|
|
||||||
$transaction->amount = $amount;
|
|
||||||
$transaction->save();
|
|
||||||
}
|
|
||||||
if ($account->id != $transaction->account_id) {
|
|
||||||
$transaction->amount = $amount * -1;
|
|
||||||
$transaction->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* AccountCrudInterface.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Crud\Account;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use FireflyIII\Models\AccountMeta;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface AccountCrudInterface
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Crud\Account
|
|
||||||
*/
|
|
||||||
interface AccountCrudInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param Account $moveTo
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function destroy(Account $account, Account $moveTo): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $accountId
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function find(int $accountId): Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $number
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function findByAccountNumber(string $number, array $types): Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $iban
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function findByIban(string $iban, array $types): Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function findByName(string $name, array $types): Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $accountIds
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getAccountsById(array $accountIds): Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $types
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getAccountsByType(array $types): Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function store(array $data) : Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $account
|
|
||||||
* @param $name
|
|
||||||
* @param $value
|
|
||||||
*
|
|
||||||
* @return AccountMeta
|
|
||||||
*/
|
|
||||||
public function storeMeta(Account $account, string $name, $value): AccountMeta;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function update(Account $account, array $data): Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param string $type
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public function updateAccountType(Account $account, string $type): Account;
|
|
||||||
}
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Journal.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Crud\Split;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionStored;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use FireflyIII\Models\AccountType;
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
use FireflyIII\Models\Category;
|
|
||||||
use FireflyIII\Models\Transaction;
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Journal
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Crud\Split
|
|
||||||
*/
|
|
||||||
class Journal implements JournalInterface
|
|
||||||
{
|
|
||||||
/** @var User */
|
|
||||||
private $user;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AttachmentRepository constructor.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
*/
|
|
||||||
public function __construct(User $user)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $journal
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function markAsComplete(TransactionJournal $journal)
|
|
||||||
{
|
|
||||||
$journal->completed = 1;
|
|
||||||
$journal->save();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
* @param array $transaction
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function storeTransaction(TransactionJournal $journal, array $transaction): Collection
|
|
||||||
{
|
|
||||||
// store accounts (depends on type)
|
|
||||||
list($sourceAccount, $destinationAccount) = $this->storeAccounts($journal->transactionType->type, $transaction);
|
|
||||||
|
|
||||||
// store transaction one way:
|
|
||||||
/** @var Transaction $one */
|
|
||||||
$one = Transaction::create(
|
|
||||||
['account_id' => $sourceAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $transaction['amount'] * -1,
|
|
||||||
'description' => $transaction['description']]
|
|
||||||
);
|
|
||||||
$two = Transaction::create(
|
|
||||||
['account_id' => $destinationAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $transaction['amount'],
|
|
||||||
'description' => $transaction['description']]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (strlen($transaction['category']) > 0) {
|
|
||||||
$category = Category::firstOrCreateEncrypted(['name' => $transaction['category'], 'user_id' => $journal->user_id]);
|
|
||||||
$one->categories()->save($category);
|
|
||||||
$two->categories()->save($category);
|
|
||||||
}
|
|
||||||
if (intval($transaction['budget_id']) > 0) {
|
|
||||||
$budget = Budget::find($transaction['budget_id']);
|
|
||||||
$one->budgets()->save($budget);
|
|
||||||
$two->budgets()->save($budget);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($transaction['piggy_bank_id'] > 0) {
|
|
||||||
$transaction['date'] = $journal->date->format('Y-m-d');
|
|
||||||
event(new TransactionStored($transaction));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Collection([$one, $two]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return TransactionJournal
|
|
||||||
*/
|
|
||||||
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal
|
|
||||||
{
|
|
||||||
$journal->description = $data['journal_description'];
|
|
||||||
$journal->transaction_currency_id = $data['journal_currency_id'];
|
|
||||||
$journal->date = $data['date'];
|
|
||||||
$journal->interest_date = $data['interest_date'];
|
|
||||||
$journal->book_date = $data['book_date'];
|
|
||||||
$journal->process_date = $data['process_date'];
|
|
||||||
$journal->save();
|
|
||||||
|
|
||||||
// delete original transactions, and recreate them.
|
|
||||||
$journal->transactions()->delete();
|
|
||||||
|
|
||||||
foreach ($data['transactions'] as $transaction) {
|
|
||||||
$this->storeTransaction($journal, $transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
$journal->completed = true;
|
|
||||||
$journal->save();
|
|
||||||
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $type
|
|
||||||
* @param array $transaction
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
private function storeAccounts(string $type, array $transaction): array
|
|
||||||
{
|
|
||||||
$sourceAccount = null;
|
|
||||||
$destinationAccount = null;
|
|
||||||
switch ($type) {
|
|
||||||
case TransactionType::WITHDRAWAL:
|
|
||||||
list($sourceAccount, $destinationAccount) = $this->storeWithdrawalAccounts($transaction);
|
|
||||||
break;
|
|
||||||
case TransactionType::DEPOSIT:
|
|
||||||
list($sourceAccount, $destinationAccount) = $this->storeDepositAccounts($transaction);
|
|
||||||
break;
|
|
||||||
case TransactionType::TRANSFER:
|
|
||||||
$sourceAccount = Account::where('user_id', $this->user->id)->where('id', $transaction['source_account_id'])->first();
|
|
||||||
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $transaction['destination_account_id'])->first();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot handle ' . e($type));
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$sourceAccount, $destinationAccount];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function storeDepositAccounts(array $data): array
|
|
||||||
{
|
|
||||||
$destinationAccount = Account::where('user_id', $this->user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']);
|
|
||||||
|
|
||||||
|
|
||||||
if (isset($data['source_account_name']) && strlen($data['source_account_name']) > 0) {
|
|
||||||
$sourceType = AccountType::where('type', 'Revenue account')->first();
|
|
||||||
$sourceAccount = Account::firstOrCreateEncrypted(
|
|
||||||
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1]
|
|
||||||
);
|
|
||||||
|
|
||||||
return [$sourceAccount, $destinationAccount];
|
|
||||||
}
|
|
||||||
|
|
||||||
$sourceType = AccountType::where('type', 'Cash account')->first();
|
|
||||||
$sourceAccount = Account::firstOrCreateEncrypted(
|
|
||||||
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1]
|
|
||||||
);
|
|
||||||
|
|
||||||
return [$sourceAccount, $destinationAccount];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function storeWithdrawalAccounts(array $data): array
|
|
||||||
{
|
|
||||||
$sourceAccount = Account::where('user_id', $this->user->id)->where('id', $data['source_account_id'])->first(['accounts.*']);
|
|
||||||
|
|
||||||
if (strlen($data['destination_account_name']) > 0) {
|
|
||||||
$destinationType = AccountType::where('type', 'Expense account')->first();
|
|
||||||
$destinationAccount = Account::firstOrCreateEncrypted(
|
|
||||||
[
|
|
||||||
'user_id' => $this->user->id,
|
|
||||||
'account_type_id' => $destinationType->id,
|
|
||||||
'name' => $data['destination_account_name'],
|
|
||||||
'active' => 1,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
return [$sourceAccount, $destinationAccount];
|
|
||||||
}
|
|
||||||
$destinationType = AccountType::where('type', 'Cash account')->first();
|
|
||||||
$destinationAccount = Account::firstOrCreateEncrypted(
|
|
||||||
['user_id' => $this->user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1]
|
|
||||||
);
|
|
||||||
|
|
||||||
return [$sourceAccount, $destinationAccount];
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* JournalInterface.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Crud\Split;
|
|
||||||
|
|
||||||
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface JournalInterface
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Crud\Split
|
|
||||||
*/
|
|
||||||
interface JournalInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param $journal
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function markAsComplete(TransactionJournal $journal);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
* @param array $transaction
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function storeTransaction(TransactionJournal $journal, array $transaction): Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return TransactionJournal
|
|
||||||
*/
|
|
||||||
public function updateJournal(TransactionJournal $journal, array $data): TransactionJournal;
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* UserRegistration.php
|
* ConfirmedUser.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserRegistration
|
* Class ConfirmedUser
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class UserRegistration extends Event
|
class ConfirmedUser extends Event
|
||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ class UserRegistration extends Event
|
|||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance. This event is triggered when a user confirms their new account.
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string $ipAddress
|
* @param string $ipAddress
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* Event.php
|
* Event.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* UserIsDeleted.php
|
* RegisteredUser.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserIsDeleted
|
* Class RegisteredUser
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class UserIsDeleted extends Event
|
class RegisteredUser extends Event
|
||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ class UserIsDeleted extends Event
|
|||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance. This event is triggered when a new user registers.
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string $ipAddress
|
* @param string $ipAddress
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ResendConfirmation.php
|
|
||||||
* Copyright (C) 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 ResendConfirmation
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class ResendConfirmation 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* UserIsConfirmed.php
|
* ResentConfirmation.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserIsConfirmed
|
* Class ResentConfirmation
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class UserIsConfirmed extends Event
|
class ResentConfirmation extends Event
|
||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ class UserIsConfirmed extends Event
|
|||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance. This event is triggered when a users wants a new confirmation.
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string $ipAddress
|
* @param string $ipAddress
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* BudgetLimitStored.php
|
* StoredBudgetLimit.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimitStored
|
* Class StoredBudgetLimit
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class BudgetLimitStored extends Event
|
class StoredBudgetLimit extends Event
|
||||||
{
|
{
|
||||||
|
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* TransactionJournalStored.php
|
* StoredTransactionJournal.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TransactionJournalStored
|
* Class StoredTransactionJournal
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class TransactionJournalStored extends Event
|
class StoredTransactionJournal extends Event
|
||||||
{
|
{
|
||||||
|
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* TransactionStored.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Events;
|
|
||||||
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class TransactionJournalStored
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class TransactionStored extends Event
|
|
||||||
{
|
|
||||||
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $transaction = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance.
|
|
||||||
*
|
|
||||||
* @param array $transaction
|
|
||||||
*/
|
|
||||||
public function __construct(array $transaction)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
$this->transaction = $transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* BudgetLimitUpdated.php
|
* UpdatedBudgetLimit.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimitUpdated
|
* Class UpdatedBudgetLimit
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class BudgetLimitUpdated extends Event
|
class UpdatedBudgetLimit extends Event
|
||||||
{
|
{
|
||||||
|
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* TransactionJournalUpdated.php
|
* UpdatedTransactionJournal.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TransactionJournalUpdated
|
* Class UpdatedTransactionJournal
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Events
|
* @package FireflyIII\Events
|
||||||
*/
|
*/
|
||||||
class TransactionJournalUpdated extends Event
|
class UpdatedTransactionJournal extends Event
|
||||||
{
|
{
|
||||||
|
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* FireflyException.php
|
* FireflyException.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Handler.php
|
* Handler.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -106,7 +108,8 @@ class Handler extends ExceptionHandler
|
|||||||
/**
|
/**
|
||||||
* Convert an authentication exception into an unauthenticated response.
|
* Convert an authentication exception into an unauthenticated response.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
protected function unauthenticated($request)
|
protected function unauthenticated($request)
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* NotImplementedException.php
|
* NotImplementedException.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ValidationException.php
|
* ValidationException.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,19 +3,20 @@
|
|||||||
* AttachmentCollector.php
|
* AttachmentCollector.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|
||||||
namespace FireflyIII\Export\Collector;
|
namespace FireflyIII\Export\Collector;
|
||||||
|
|
||||||
use Amount;
|
use Carbon\Carbon;
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Models\ExportJob;
|
use FireflyIII\Models\ExportJob;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -29,12 +30,14 @@ use Storage;
|
|||||||
*/
|
*/
|
||||||
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var Carbon */
|
||||||
private $explanationString = '';
|
private $end;
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $exportDisk;
|
private $exportDisk;
|
||||||
/** @var AttachmentRepositoryInterface */
|
/** @var AttachmentRepositoryInterface */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $start;
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $uploadDisk;
|
private $uploadDisk;
|
||||||
|
|
||||||
@@ -67,34 +70,17 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
|||||||
$this->exportAttachment($attachment);
|
$this->exportAttachment($attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the explanation string in a file and attach it as well.
|
|
||||||
$file = $this->job->key . '-Source of all your attachments explained.txt';
|
|
||||||
$this->exportDisk->put($file, $this->explanationString);
|
|
||||||
$this->getFiles()->push($file);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Attachment $attachment
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
*/
|
*/
|
||||||
private function explain(Attachment $attachment)
|
public function setDates(Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
/** @var TransactionJournal $journal */
|
$this->start = $start;
|
||||||
$journal = $attachment->attachable;
|
$this->end = $end;
|
||||||
$args = [
|
|
||||||
'attachment_name' => e($attachment->filename),
|
|
||||||
'attachment_id' => $attachment->id,
|
|
||||||
'type' => strtolower($journal->transactionType->type),
|
|
||||||
'description' => e($journal->description),
|
|
||||||
'journal_id' => $journal->id,
|
|
||||||
'date' => $journal->date->formatLocalized(strval(trans('config.month_and_day'))),
|
|
||||||
'amount' => Amount::formatJournal($journal, false),
|
|
||||||
];
|
|
||||||
$string = trans('firefly.attachment_explanation', $args) . "\n";
|
|
||||||
Log::debug('Appended explanation string', ['string' => $string]);
|
|
||||||
$this->explanationString .= $string;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,10 +96,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
|||||||
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
||||||
$exportFile = $this->exportFileName($attachment);
|
$exportFile = $this->exportFileName($attachment);
|
||||||
$this->exportDisk->put($exportFile, $decrypted);
|
$this->exportDisk->put($exportFile, $decrypted);
|
||||||
$this->getFiles()->push($exportFile);
|
$this->getEntries()->push($exportFile);
|
||||||
|
|
||||||
// explain:
|
|
||||||
$this->explain($attachment);
|
|
||||||
} catch (DecryptException $e) {
|
} catch (DecryptException $e) {
|
||||||
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -141,7 +125,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
|||||||
*/
|
*/
|
||||||
private function getAttachments(): Collection
|
private function getAttachments(): Collection
|
||||||
{
|
{
|
||||||
$attachments = $this->repository->get();
|
$attachments = $this->repository->getBetween($this->start, $this->end);
|
||||||
|
|
||||||
return $attachments;
|
return $attachments;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BasicCollector.php
|
* BasicCollector.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -25,7 +27,7 @@ class BasicCollector
|
|||||||
/** @var ExportJob */
|
/** @var ExportJob */
|
||||||
protected $job;
|
protected $job;
|
||||||
/** @var Collection */
|
/** @var Collection */
|
||||||
private $files;
|
private $entries;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BasicCollector constructor.
|
* BasicCollector constructor.
|
||||||
@@ -34,24 +36,24 @@ class BasicCollector
|
|||||||
*/
|
*/
|
||||||
public function __construct(ExportJob $job)
|
public function __construct(ExportJob $job)
|
||||||
{
|
{
|
||||||
$this->files = new Collection;
|
$this->entries = new Collection;
|
||||||
$this->job = $job;
|
$this->job = $job;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getFiles(): Collection
|
public function getEntries(): Collection
|
||||||
{
|
{
|
||||||
return $this->files;
|
return $this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $files
|
* @param Collection $entries
|
||||||
*/
|
*/
|
||||||
public function setFiles(Collection $files)
|
public function setEntries(Collection $entries)
|
||||||
{
|
{
|
||||||
$this->files = $files;
|
$this->entries = $entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* CollectorInterface.php
|
* CollectorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -23,7 +25,7 @@ interface CollectorInterface
|
|||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getFiles(): Collection;
|
public function getEntries(): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
@@ -31,9 +33,9 @@ interface CollectorInterface
|
|||||||
public function run(): bool;
|
public function run(): bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $files
|
* @param Collection $entries
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setFiles(Collection $files);
|
public function setEntries(Collection $entries);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
348
app/Export/Collector/JournalCollector.php
Normal file
348
app/Export/Collector/JournalCollector.php
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* JournalCollector.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Export\Collector;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Crypt;
|
||||||
|
use DB;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use Illuminate\Database\Query\JoinClause;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JournalCollector
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Export\Collector
|
||||||
|
*/
|
||||||
|
class JournalCollector extends BasicCollector implements CollectorInterface
|
||||||
|
{
|
||||||
|
/** @var Collection */
|
||||||
|
private $accounts;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $end;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $start;
|
||||||
|
|
||||||
|
/** @var Collection */
|
||||||
|
private $workSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function run(): bool
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Instead of collecting journals we collect transactions for the given accounts.
|
||||||
|
* We left join the OPPOSING transaction AND some journal data.
|
||||||
|
* After that we complement this info with budgets, categories, etc.
|
||||||
|
*
|
||||||
|
* This is way more efficient and will also work on split journals.
|
||||||
|
*/
|
||||||
|
$this->getWorkSet();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract:
|
||||||
|
* possible budget ids for journals
|
||||||
|
* possible category ids journals
|
||||||
|
* possible budget ids for transactions
|
||||||
|
* possible category ids for transactions
|
||||||
|
*
|
||||||
|
* possible IBAN and account numbers?
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$journals = $this->extractJournalIds();
|
||||||
|
$transactions = $this->extractTransactionIds();
|
||||||
|
|
||||||
|
|
||||||
|
// extend work set with category data from journals:
|
||||||
|
$this->categoryDataForJournals($journals);
|
||||||
|
|
||||||
|
// extend work set with category cate from transactions (overrules journals):
|
||||||
|
$this->categoryDataForTransactions($transactions);
|
||||||
|
|
||||||
|
// same for budgets:
|
||||||
|
$this->budgetDataForJournals($journals);
|
||||||
|
$this->budgetDataForTransactions($transactions);
|
||||||
|
|
||||||
|
$this->setEntries($this->workSet);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
*/
|
||||||
|
public function setAccounts(Collection $accounts)
|
||||||
|
{
|
||||||
|
$this->accounts = $accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*/
|
||||||
|
public function setDates(Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$this->start = $start;
|
||||||
|
$this->end = $end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $journals
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function budgetDataForJournals(array $journals): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('budget_transaction_journal')
|
||||||
|
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||||
|
->whereIn('budget_transaction_journal.transaction_journal_id', $journals)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budget_transaction_journal.budget_id',
|
||||||
|
'budget_transaction_journal.transaction_journal_id',
|
||||||
|
'budgets.name',
|
||||||
|
'budgets.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_journal_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
if (isset($array[$obj->transaction_journal_id])) {
|
||||||
|
$obj->budget_id = $array[$obj->transaction_journal_id]['id'];
|
||||||
|
$obj->budget_name = $array[$obj->transaction_journal_id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $transactions
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function budgetDataForTransactions(array $transactions): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('budget_transaction')
|
||||||
|
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction.budget_id')
|
||||||
|
->whereIn('budget_transaction.transaction_id', $transactions)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budget_transaction.budget_id',
|
||||||
|
'budget_transaction.transaction_id',
|
||||||
|
'budgets.name',
|
||||||
|
'budgets.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
|
||||||
|
// first transaction
|
||||||
|
if (isset($array[$obj->id])) {
|
||||||
|
$obj->budget_id = $array[$obj->id]['id'];
|
||||||
|
$obj->budget_name = $array[$obj->id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $journals
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function categoryDataForJournals(array $journals): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('category_transaction_journal')
|
||||||
|
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||||
|
->whereIn('category_transaction_journal.transaction_journal_id', $journals)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'category_transaction_journal.category_id',
|
||||||
|
'category_transaction_journal.transaction_journal_id',
|
||||||
|
'categories.name',
|
||||||
|
'categories.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_journal_id] = ['id' => $obj->category_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
if (isset($array[$obj->transaction_journal_id])) {
|
||||||
|
$obj->category_id = $array[$obj->transaction_journal_id]['id'];
|
||||||
|
$obj->category_name = $array[$obj->transaction_journal_id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $transactions
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function categoryDataForTransactions(array $transactions): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('category_transaction')
|
||||||
|
->leftJoin('categories', 'categories.id', '=', 'category_transaction.category_id')
|
||||||
|
->whereIn('category_transaction.transaction_id', $transactions)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'category_transaction.category_id',
|
||||||
|
'category_transaction.transaction_id',
|
||||||
|
'categories.name',
|
||||||
|
'categories.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_id] = ['id' => $obj->category_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
|
||||||
|
// first transaction
|
||||||
|
if (isset($array[$obj->id])) {
|
||||||
|
$obj->category_id = $array[$obj->id]['id'];
|
||||||
|
$obj->category_name = $array[$obj->id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractJournalIds(): array
|
||||||
|
{
|
||||||
|
return $this->workSet->pluck('transaction_journal_id')->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractTransactionIds()
|
||||||
|
{
|
||||||
|
$set = $this->workSet->pluck('id')->toArray();
|
||||||
|
$opposing = $this->workSet->pluck('opposing_id')->toArray();
|
||||||
|
$complete = $set + $opposing;
|
||||||
|
|
||||||
|
return array_unique($complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function getWorkSet()
|
||||||
|
{
|
||||||
|
$accountIds = $this->accounts->pluck('id')->toArray();
|
||||||
|
$this->workSet = Transaction
|
||||||
|
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->leftJoin(
|
||||||
|
'transactions AS opposing', function (JoinClause $join) {
|
||||||
|
$join->on('opposing.transaction_journal_id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->where('opposing.amount', '=', DB::raw('transactions.amount * -1'))
|
||||||
|
->where('transactions.identifier', '=', 'opposing.identifier');
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
|
||||||
|
->leftJoin('accounts AS opposing_accounts', 'opposing.account_id', '=', 'opposing_accounts.id')
|
||||||
|
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', 'transaction_types.id')
|
||||||
|
->leftJoin('transaction_currencies', 'transaction_journals.transaction_currency_id', '=', 'transaction_currencies.id')
|
||||||
|
->whereIn('transactions.account_id', $accountIds)
|
||||||
|
->where('transaction_journals.user_id', $this->job->user_id)
|
||||||
|
->where('transaction_journals.date', '>=', $this->start->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.date', '<=', $this->end->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.completed', 1)
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
|
->whereNull('transactions.deleted_at')
|
||||||
|
->whereNull('opposing.deleted_at')
|
||||||
|
->orderBy('transaction_journals.date', 'DESC')
|
||||||
|
->orderBy('transactions.identifier', 'ASC')
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'transactions.id',
|
||||||
|
'transactions.amount',
|
||||||
|
'transactions.description',
|
||||||
|
'transactions.account_id',
|
||||||
|
'accounts.name as account_name',
|
||||||
|
'accounts.encrypted as account_name_encrypted',
|
||||||
|
'transactions.identifier',
|
||||||
|
|
||||||
|
'opposing.id as opposing_id',
|
||||||
|
'opposing.amount AS opposing_amount',
|
||||||
|
'opposing.description as opposing_description',
|
||||||
|
'opposing.account_id as opposing_account_id',
|
||||||
|
'opposing_accounts.name as opposing_account_name',
|
||||||
|
'opposing_accounts.encrypted as opposing_account_encrypted',
|
||||||
|
'opposing.identifier as opposing_identifier',
|
||||||
|
|
||||||
|
'transaction_journals.id as transaction_journal_id',
|
||||||
|
'transaction_journals.date',
|
||||||
|
'transaction_journals.description as journal_description',
|
||||||
|
'transaction_journals.encrypted as journal_encrypted',
|
||||||
|
'transaction_journals.transaction_type_id',
|
||||||
|
'transaction_types.type as transaction_type',
|
||||||
|
'transaction_journals.transaction_currency_id',
|
||||||
|
'transaction_currencies.code AS transaction_currency_code',
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* UploadCollector.php
|
* UploadCollector.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -24,16 +26,14 @@ use Storage;
|
|||||||
*/
|
*/
|
||||||
class UploadCollector extends BasicCollector implements CollectorInterface
|
class UploadCollector extends BasicCollector implements CollectorInterface
|
||||||
{
|
{
|
||||||
/** @var string */
|
|
||||||
private $expected;
|
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $exportDisk;
|
private $exportDisk;
|
||||||
private $importKeys = [];
|
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $uploadDisk;
|
private $uploadDisk;
|
||||||
|
/** @var string */
|
||||||
|
private $vintageFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* AttachmentCollector constructor.
|
* AttachmentCollector constructor.
|
||||||
*
|
*
|
||||||
* @param ExportJob $job
|
* @param ExportJob $job
|
||||||
@@ -49,50 +49,74 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
$this->exportDisk = Storage::disk('export');
|
$this->exportDisk = Storage::disk('export');
|
||||||
|
|
||||||
// file names associated with the old import routine.
|
// file names associated with the old import routine.
|
||||||
$this->expected = 'csv-upload-' . auth()->user()->id . '-';
|
$this->vintageFormat = sprintf('csv-upload-%d-', auth()->user()->id);
|
||||||
|
|
||||||
// for the new import routine:
|
|
||||||
$this->getImportKeys();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Is called from the outside to actually start the export.
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function run(): bool
|
public function run(): bool
|
||||||
{
|
{
|
||||||
// grab upload directory.
|
// collect old upload files (names beginning with "csv-upload".
|
||||||
$files = $this->uploadDisk->files();
|
$this->collectVintageUploads();
|
||||||
|
|
||||||
foreach ($files as $entry) {
|
// then collect current upload files:
|
||||||
$this->processUpload($entry);
|
$this->collectModernUploads();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method collects all the uploads that are uploaded using the new importer. So after the summer of 2016.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function collectModernUploads(): bool
|
||||||
|
{
|
||||||
|
$set = $this->job->user->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
||||||
|
$keys = [];
|
||||||
|
if ($set->count() > 0) {
|
||||||
|
$keys = $set->pluck('key')->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$this->processModernUpload($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This method collects all the uploads that are uploaded using the "old" importer. So from before the summer of 2016.
|
||||||
*
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function getImportKeys()
|
private function collectVintageUploads():bool
|
||||||
{
|
{
|
||||||
$set = auth()->user()->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
// grab upload directory.
|
||||||
if ($set->count() > 0) {
|
$files = $this->uploadDisk->files();
|
||||||
$keys = $set->pluck('key')->toArray();
|
|
||||||
$this->importKeys = $keys;
|
|
||||||
|
|
||||||
|
foreach ($files as $entry) {
|
||||||
|
$this->processVintageUpload($entry);
|
||||||
}
|
}
|
||||||
Log::debug('Valid import keys are ', $this->importKeys);
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This method tells you when the vintage upload file was actually uploaded.
|
||||||
|
*
|
||||||
* @param string $entry
|
* @param string $entry
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getOriginalUploadDate(string $entry): string
|
private function getVintageUploadDate(string $entry): string
|
||||||
{
|
{
|
||||||
// this is an original upload.
|
// this is an original upload.
|
||||||
$parts = explode('-', str_replace(['.csv.encrypted', $this->expected], '', $entry));
|
$parts = explode('-', str_replace(['.csv.encrypted', $this->vintageFormat], '', $entry));
|
||||||
$originalUpload = intval($parts[1]);
|
$originalUpload = intval($parts[1]);
|
||||||
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
|
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
|
||||||
|
|
||||||
@@ -100,33 +124,17 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tells you if a file name is a vintage upload.
|
||||||
|
*
|
||||||
* @param string $entry
|
* @param string $entry
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function isImportFile(string $entry): bool
|
private function isVintageImport(string $entry): bool
|
||||||
{
|
{
|
||||||
$name = str_replace('.upload', '', $entry);
|
$len = strlen($this->vintageFormat);
|
||||||
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:
|
// file is part of the old import routine:
|
||||||
if (substr($entry, 0, $len) === $this->expected) {
|
if (substr($entry, 0, $len) === $this->vintageFormat) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -135,49 +143,62 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $entry
|
* @param string $key
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function processUpload(string $entry)
|
private function processModernUpload(string $key): bool
|
||||||
{
|
|
||||||
// file is old import:
|
|
||||||
if ($this->isOldImport($entry)) {
|
|
||||||
$this->saveOldImportFile($entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// file is current import.
|
|
||||||
if ($this->isImportFile($entry)) {
|
|
||||||
$this->saveImportFile($entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $entry
|
|
||||||
*/
|
|
||||||
private function saveImportFile(string $entry)
|
|
||||||
{
|
{
|
||||||
// find job associated with import file:
|
// find job associated with import file:
|
||||||
$name = str_replace('.upload', '', $entry);
|
$job = $this->job->user->importJobs()->where('key', $key)->first();
|
||||||
$job = auth()->user()->importJobs()->where('key', $name)->first();
|
if (is_null($job)) {
|
||||||
$content = '';
|
return false;
|
||||||
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) {
|
// find the file for this import:
|
||||||
|
$content = '';
|
||||||
|
try {
|
||||||
|
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('%s.upload', $key)));
|
||||||
|
} catch (DecryptException $e) {
|
||||||
|
Log::error(sprintf('Could not decrypt old import file "%s". Skipped because: %s', $key, $e->getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($content) > 0) {
|
||||||
// add to export disk.
|
// add to export disk.
|
||||||
$date = $job->created_at->format('Y-m-d');
|
$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);
|
$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->exportDisk->put($file, $content);
|
||||||
$this->getFiles()->push($file);
|
$this->getEntries()->push($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* If the file is a vintage upload, process it.
|
||||||
|
*
|
||||||
|
* @param string $entry
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function processVintageUpload(string $entry): bool
|
||||||
|
{
|
||||||
|
if ($this->isVintageImport($entry)) {
|
||||||
|
$this->saveVintageImportFile($entry);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will store the content of the old vintage upload somewhere.
|
||||||
|
*
|
||||||
* @param string $entry
|
* @param string $entry
|
||||||
*/
|
*/
|
||||||
private function saveOldImportFile(string $entry)
|
private function saveVintageImportFile(string $entry)
|
||||||
{
|
{
|
||||||
$content = '';
|
$content = '';
|
||||||
try {
|
try {
|
||||||
@@ -188,10 +209,10 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
|
|
||||||
if (strlen($content) > 0) {
|
if (strlen($content) > 0) {
|
||||||
// add to export disk.
|
// add to export disk.
|
||||||
$date = $this->getOriginalUploadDate($entry);
|
$date = $this->getVintageUploadDate($entry);
|
||||||
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
||||||
$this->exportDisk->put($file, $content);
|
$this->exportDisk->put($file, $content);
|
||||||
$this->getFiles()->push($file);
|
$this->getEntries()->push($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ConfigurationFile.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Export;
|
|
||||||
|
|
||||||
use FireflyIII\Export\Entry\Entry;
|
|
||||||
use FireflyIII\Models\ExportJob;
|
|
||||||
use Storage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConfigurationFile
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export
|
|
||||||
*/
|
|
||||||
class ConfigurationFile
|
|
||||||
{
|
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
|
||||||
private $exportDisk;
|
|
||||||
/** @var ExportJob */
|
|
||||||
private $job;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ConfigurationFile constructor.
|
|
||||||
*
|
|
||||||
* @param ExportJob $job
|
|
||||||
*/
|
|
||||||
public function __construct(ExportJob $job)
|
|
||||||
{
|
|
||||||
$this->job = $job;
|
|
||||||
$this->exportDisk = Storage::disk('export');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function make(): string
|
|
||||||
{
|
|
||||||
$fields = array_keys(Entry::getFieldsAndTypes());
|
|
||||||
$types = Entry::getFieldsAndTypes();
|
|
||||||
|
|
||||||
$configuration = [
|
|
||||||
'date-format' => 'Y-m-d', // unfortunately, this is hard-coded.
|
|
||||||
'has-headers' => true,
|
|
||||||
'map' => [], // we could build a map if necessary for easy re-import.
|
|
||||||
'roles' => [],
|
|
||||||
'mapped' => [],
|
|
||||||
'specifix' => [],
|
|
||||||
];
|
|
||||||
foreach ($fields as $field) {
|
|
||||||
$configuration['roles'][] = $types[$field];
|
|
||||||
}
|
|
||||||
$file = $this->job->key . '-configuration.json';
|
|
||||||
$this->exportDisk->put($file, json_encode($configuration, JSON_PRETTY_PRINT));
|
|
||||||
|
|
||||||
return $file;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,16 +3,17 @@
|
|||||||
* Entry.php
|
* Entry.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|
||||||
namespace FireflyIII\Export\Entry;
|
namespace FireflyIII\Export\Entry;
|
||||||
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use Crypt;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To extend the exported object, in case of new features in Firefly III for example,
|
* To extend the exported object, in case of new features in Firefly III for example,
|
||||||
@@ -33,98 +34,77 @@ use Illuminate\Support\Collection;
|
|||||||
*/
|
*/
|
||||||
final class Entry
|
final class Entry
|
||||||
{
|
{
|
||||||
/** @var string */
|
// @formatter:off
|
||||||
public $amount;
|
public $journal_id;
|
||||||
/** @var EntryBill */
|
|
||||||
public $bill;
|
|
||||||
/** @var EntryBudget */
|
|
||||||
public $budget;
|
|
||||||
/** @var EntryCategory */
|
|
||||||
public $category;
|
|
||||||
/** @var string */
|
|
||||||
public $date;
|
public $date;
|
||||||
/** @var string */
|
|
||||||
public $description;
|
public $description;
|
||||||
/** @var EntryAccount */
|
|
||||||
public $destinationAccount;
|
public $currency_code;
|
||||||
/** @var Collection */
|
public $amount;
|
||||||
public $destinationAccounts;
|
|
||||||
/** @var EntryAccount */
|
public $transaction_type;
|
||||||
public $sourceAccount;
|
|
||||||
/** @var Collection */
|
public $source_account_id;
|
||||||
public $sourceAccounts;
|
public $source_account_name;
|
||||||
|
|
||||||
|
public $destination_account_id;
|
||||||
|
public $destination_account_name;
|
||||||
|
|
||||||
|
|
||||||
|
public $budget_id;
|
||||||
|
public $budget_name;
|
||||||
|
public $category_id;
|
||||||
|
public $category_name;
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry constructor.
|
* Entry constructor.
|
||||||
*/
|
*/
|
||||||
private function __construct()
|
private function __construct()
|
||||||
{
|
{
|
||||||
$this->sourceAccounts = new Collection;
|
|
||||||
$this->destinationAccounts = new Collection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $journal
|
* @param $object
|
||||||
*
|
*
|
||||||
* @return Entry
|
* @return Entry
|
||||||
*/
|
*/
|
||||||
public static function fromJournal(TransactionJournal $journal)
|
public static function fromObject($object): Entry
|
||||||
{
|
{
|
||||||
|
$entry = new self;
|
||||||
|
|
||||||
$entry = new self;
|
// journal information:
|
||||||
$entry->description = $journal->description;
|
$entry->journal_id = $object->transaction_journal_id;
|
||||||
$entry->date = $journal->date->format('Y-m-d');
|
$entry->description = $object->journal_encrypted === 1 ? Crypt::decrypt($object->journal_description) : $object->journal_description;
|
||||||
$entry->amount = TransactionJournal::amount($journal);
|
$entry->amount = round($object->amount, 2); // always positive
|
||||||
|
$entry->date = $object->date;
|
||||||
|
$entry->transaction_type = $object->transaction_type;
|
||||||
|
$entry->currency_code = $object->transaction_currency_code;
|
||||||
|
|
||||||
$entry->budget = new EntryBudget($journal->budgets->first());
|
// source information:
|
||||||
$entry->category = new EntryCategory($journal->categories->first());
|
$entry->source_account_id = $object->account_id;
|
||||||
$entry->bill = new EntryBill($journal->bill);
|
$entry->source_account_name = $object->account_name_encrypted === 1 ? Crypt::decrypt($object->account_name) : $object->account_name;
|
||||||
|
|
||||||
$sources = TransactionJournal::sourceAccountList($journal);
|
|
||||||
$destinations = TransactionJournal::destinationAccountList($journal);
|
|
||||||
$entry->sourceAccount = new EntryAccount($sources->first());
|
|
||||||
$entry->destinationAccount = new EntryAccount($destinations->first());
|
|
||||||
|
|
||||||
foreach ($sources as $source) {
|
// destination information
|
||||||
$entry->sourceAccounts->push(new EntryAccount($source));
|
$entry->destination_account_id = $object->opposing_account_id;
|
||||||
}
|
$entry->destination_account_name = $object->opposing_account_encrypted === 1 ? Crypt::decrypt($object->opposing_account_name)
|
||||||
|
: $object->opposing_account_name;
|
||||||
|
|
||||||
foreach ($destinations as $destination) {
|
|
||||||
$entry->destinationAccounts->push(new EntryAccount($destination));
|
// category and budget
|
||||||
|
$entry->category_id = $object->category_id ?? '';
|
||||||
|
$entry->category_name = $object->category_name ?? '';
|
||||||
|
$entry->budget_id = $object->budget_id ?? '';
|
||||||
|
$entry->budget_name = $object->budget_name ?? '';
|
||||||
|
|
||||||
|
|
||||||
|
// update description when transaction description is different:
|
||||||
|
if (!is_null($object->description) && $object->description != $entry->description) {
|
||||||
|
$entry->description = $entry->description . ' (' . $object->description . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entry;
|
return $entry;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function getFieldsAndTypes(): array
|
|
||||||
{
|
|
||||||
// key = field name (see top of class)
|
|
||||||
// value = field type (see csv.php under 'roles')
|
|
||||||
return [
|
|
||||||
'description' => 'description',
|
|
||||||
'amount' => 'amount',
|
|
||||||
'date' => 'date-transaction',
|
|
||||||
'source_account_id' => 'account-id',
|
|
||||||
'source_account_name' => 'account-name',
|
|
||||||
'source_account_iban' => 'account-iban',
|
|
||||||
'source_account_type' => '_ignore',
|
|
||||||
'source_account_number' => 'account-number',
|
|
||||||
'destination_account_id' => 'opposing-id',
|
|
||||||
'destination_account_name' => 'opposing-name',
|
|
||||||
'destination_account_iban' => 'opposing-iban',
|
|
||||||
'destination_account_type' => '_ignore',
|
|
||||||
'destination_account_number' => 'account-number',
|
|
||||||
'budget_id' => 'budget-id',
|
|
||||||
'budget_name' => 'budget-name',
|
|
||||||
'category_id' => 'category-id',
|
|
||||||
'category_name' => 'category-name',
|
|
||||||
'bill_id' => 'bill-id',
|
|
||||||
'bill_name' => 'bill-name',
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryAccount.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryAccount
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryAccount
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $accountId;
|
|
||||||
/** @var string */
|
|
||||||
public $iban;
|
|
||||||
/** @var string */
|
|
||||||
public $name;
|
|
||||||
/** @var string */
|
|
||||||
public $number;
|
|
||||||
/** @var string */
|
|
||||||
public $type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryAccount constructor.
|
|
||||||
*
|
|
||||||
* @param Account $account
|
|
||||||
*/
|
|
||||||
public function __construct(Account $account)
|
|
||||||
{
|
|
||||||
$this->accountId = $account->id;
|
|
||||||
$this->name = $account->name;
|
|
||||||
$this->iban = $account->iban;
|
|
||||||
$this->type = $account->accountType->type;
|
|
||||||
$this->number = $account->getMeta('accountNumber');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryBill.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Bill;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryBill
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryBill
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $billId = '';
|
|
||||||
/** @var string */
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryBill constructor.
|
|
||||||
*
|
|
||||||
* @param Bill $bill
|
|
||||||
*/
|
|
||||||
public function __construct(Bill $bill = null)
|
|
||||||
{
|
|
||||||
if (!is_null($bill)) {
|
|
||||||
$this->billId = $bill->id;
|
|
||||||
$this->name = $bill->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryBudget.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryBudget
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryBudget
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $budgetId = '';
|
|
||||||
/** @var string */
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryBudget constructor.
|
|
||||||
*
|
|
||||||
* @param Budget $budget
|
|
||||||
*/
|
|
||||||
public function __construct(Budget $budget = null)
|
|
||||||
{
|
|
||||||
if (!is_null($budget)) {
|
|
||||||
$this->budgetId = $budget->id;
|
|
||||||
$this->name = $budget->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryCategory.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Category;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryCategory
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryCategory
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $categoryId = '';
|
|
||||||
/** @var string */
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryCategory constructor.
|
|
||||||
*
|
|
||||||
* @param Category $category
|
|
||||||
*/
|
|
||||||
public function __construct(Category $category = null)
|
|
||||||
{
|
|
||||||
if (!is_null($category)) {
|
|
||||||
$this->categoryId = $category->id;
|
|
||||||
$this->name = $category->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* BasicExporter.php
|
* BasicExporter.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* CsvExporter.php
|
* CsvExporter.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -14,7 +16,6 @@ namespace FireflyIII\Export\Exporter;
|
|||||||
use FireflyIII\Export\Entry\Entry;
|
use FireflyIII\Export\Entry\Entry;
|
||||||
use FireflyIII\Export\Entry\EntryAccount;
|
use FireflyIII\Export\Entry\EntryAccount;
|
||||||
use FireflyIII\Models\ExportJob;
|
use FireflyIII\Models\ExportJob;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use League\Csv\Writer;
|
use League\Csv\Writer;
|
||||||
use SplFileObject;
|
use SplFileObject;
|
||||||
|
|
||||||
@@ -60,110 +61,24 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
|||||||
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
|
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
|
||||||
$rows = [];
|
$rows = [];
|
||||||
|
|
||||||
// Count the maximum number of sources and destinations each entry has. May need to expand the number of export fields:
|
// get field names for header row:
|
||||||
$maxSourceAccounts = 1;
|
$first = $this->getEntries()->first();
|
||||||
$maxDestAccounts = 1;
|
$headers = array_keys(get_object_vars($first));
|
||||||
/** @var Entry $entry */
|
$rows[] = $headers;
|
||||||
foreach ($this->getEntries() as $entry) {
|
|
||||||
$sources = $entry->sourceAccounts->count();
|
|
||||||
$destinations = $entry->destinationAccounts->count();
|
|
||||||
$maxSourceAccounts = max($maxSourceAccounts, $sources);
|
|
||||||
$maxDestAccounts = max($maxDestAccounts, $destinations);
|
|
||||||
}
|
|
||||||
$rows[] = array_keys($this->getFieldsAndTypes($maxSourceAccounts, $maxDestAccounts));
|
|
||||||
|
|
||||||
/** @var Entry $entry */
|
/** @var Entry $entry */
|
||||||
foreach ($this->getEntries() as $entry) {
|
foreach ($this->getEntries() as $entry) {
|
||||||
// order is defined in Entry::getFieldsAndTypes.
|
$line = [];
|
||||||
$current = [$entry->description, $entry->amount, $entry->date];
|
foreach ($headers as $header) {
|
||||||
$sourceData = $this->getAccountData($maxSourceAccounts, $entry->sourceAccounts);
|
$line[] = $entry->$header;
|
||||||
$current = array_merge($current, $sourceData);
|
}
|
||||||
$destData = $this->getAccountData($maxDestAccounts, $entry->destinationAccounts);
|
$rows[] = $line;
|
||||||
$current = array_merge($current, $destData);
|
|
||||||
$rest = [$entry->budget->budgetId, $entry->budget->name, $entry->category->categoryId, $entry->category->name, $entry->bill->billId,
|
|
||||||
$entry->bill->name];
|
|
||||||
$current = array_merge($current, $rest);
|
|
||||||
$rows[] = $current;
|
|
||||||
}
|
}
|
||||||
$writer->insertAll($rows);
|
$writer->insertAll($rows);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $max
|
|
||||||
* @param Collection $accounts
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getAccountData(int $max, Collection $accounts): array
|
|
||||||
{
|
|
||||||
$current = [];
|
|
||||||
for ($i = 0; $i < $max; $i++) {
|
|
||||||
/** @var EntryAccount $source */
|
|
||||||
$source = $accounts->get($i);
|
|
||||||
$currentId = '';
|
|
||||||
$currentName = '';
|
|
||||||
$currentIban = '';
|
|
||||||
$currentType = '';
|
|
||||||
$currentNumber = '';
|
|
||||||
if ($source) {
|
|
||||||
$currentId = $source->accountId;
|
|
||||||
$currentName = $source->name;
|
|
||||||
$currentIban = $source->iban;
|
|
||||||
$currentType = $source->type;
|
|
||||||
$currentNumber = $source->number;
|
|
||||||
}
|
|
||||||
$current[] = $currentId;
|
|
||||||
$current[] = $currentName;
|
|
||||||
$current[] = $currentIban;
|
|
||||||
$current[] = $currentType;
|
|
||||||
$current[] = $currentNumber;
|
|
||||||
}
|
|
||||||
unset($source);
|
|
||||||
|
|
||||||
return $current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $sources
|
|
||||||
* @param int $destinations
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getFieldsAndTypes(int $sources, int $destinations): array
|
|
||||||
{
|
|
||||||
// key = field name (see top of class)
|
|
||||||
// value = field type (see csv.php under 'roles')
|
|
||||||
$array = [
|
|
||||||
'description' => 'description',
|
|
||||||
'amount' => 'amount',
|
|
||||||
'date' => 'date-transaction',
|
|
||||||
];
|
|
||||||
for ($i = 0; $i < $sources; $i++) {
|
|
||||||
$array['source_account_' . $i . '_id'] = 'account-id';
|
|
||||||
$array['source_account_' . $i . '_name'] = 'account-name';
|
|
||||||
$array['source_account_' . $i . '_iban'] = 'account-iban';
|
|
||||||
$array['source_account_' . $i . '_type'] = '_ignore';
|
|
||||||
$array['source_account_' . $i . '_number'] = 'account-number';
|
|
||||||
}
|
|
||||||
for ($i = 0; $i < $destinations; $i++) {
|
|
||||||
$array['destination_account_' . $i . '_id'] = 'account-id';
|
|
||||||
$array['destination_account_' . $i . '_name'] = 'account-name';
|
|
||||||
$array['destination_account_' . $i . '_iban'] = 'account-iban';
|
|
||||||
$array['destination_account_' . $i . '_type'] = '_ignore';
|
|
||||||
$array['destination_account_' . $i . '_number'] = 'account-number';
|
|
||||||
}
|
|
||||||
|
|
||||||
$array['budget_id'] = 'budget-id';
|
|
||||||
$array['budget_name'] = 'budget-name';
|
|
||||||
$array['category_id'] = 'category-id';
|
|
||||||
$array['category_name'] = 'category-name';
|
|
||||||
$array['bill_id'] = 'bill-id';
|
|
||||||
$array['bill_name'] = 'bill-name';
|
|
||||||
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function tempFile()
|
private function tempFile()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ExporterInterface.php
|
* ExporterInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Processor.php
|
* Processor.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -13,13 +15,13 @@ namespace FireflyIII\Export;
|
|||||||
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Export\Collector\AttachmentCollector;
|
use FireflyIII\Export\Collector\AttachmentCollector;
|
||||||
|
use FireflyIII\Export\Collector\JournalCollector;
|
||||||
use FireflyIII\Export\Collector\UploadCollector;
|
use FireflyIII\Export\Collector\UploadCollector;
|
||||||
use FireflyIII\Export\Entry\Entry;
|
use FireflyIII\Export\Entry\Entry;
|
||||||
use FireflyIII\Models\ExportJob;
|
use FireflyIII\Models\ExportJob;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
use Storage;
|
use Storage;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
|
|
||||||
@@ -38,8 +40,6 @@ class Processor
|
|||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $includeAttachments;
|
public $includeAttachments;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $includeConfig;
|
|
||||||
/** @var bool */
|
|
||||||
public $includeOldUploads;
|
public $includeOldUploads;
|
||||||
/** @var ExportJob */
|
/** @var ExportJob */
|
||||||
public $job;
|
public $job;
|
||||||
@@ -66,7 +66,6 @@ class Processor
|
|||||||
$this->accounts = $settings['accounts'];
|
$this->accounts = $settings['accounts'];
|
||||||
$this->exportFormat = $settings['exportFormat'];
|
$this->exportFormat = $settings['exportFormat'];
|
||||||
$this->includeAttachments = $settings['includeAttachments'];
|
$this->includeAttachments = $settings['includeAttachments'];
|
||||||
$this->includeConfig = $settings['includeConfig'];
|
|
||||||
$this->includeOldUploads = $settings['includeOldUploads'];
|
$this->includeOldUploads = $settings['includeOldUploads'];
|
||||||
$this->job = $settings['job'];
|
$this->job = $settings['job'];
|
||||||
$this->journals = new Collection;
|
$this->journals = new Collection;
|
||||||
@@ -82,8 +81,9 @@ class Processor
|
|||||||
{
|
{
|
||||||
/** @var AttachmentCollector $attachmentCollector */
|
/** @var AttachmentCollector $attachmentCollector */
|
||||||
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
|
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
|
||||||
|
$attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
|
||||||
$attachmentCollector->run();
|
$attachmentCollector->run();
|
||||||
$this->files = $this->files->merge($attachmentCollector->getFiles());
|
$this->files = $this->files->merge($attachmentCollector->getEntries());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -93,9 +93,13 @@ class Processor
|
|||||||
*/
|
*/
|
||||||
public function collectJournals(): bool
|
public function collectJournals(): bool
|
||||||
{
|
{
|
||||||
/** @var JournalRepositoryInterface $repository */
|
/** @var JournalCollector $collector */
|
||||||
$repository = app(JournalRepositoryInterface::class);
|
$collector = app(JournalCollector::class, [$this->job]);
|
||||||
$this->journals = $repository->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
|
$collector->setDates($this->settings['startDate'], $this->settings['endDate']);
|
||||||
|
$collector->setAccounts($this->settings['accounts']);
|
||||||
|
$collector->run();
|
||||||
|
$this->journals = $collector->getEntries();
|
||||||
|
Log::debug(sprintf('Count %d journals in collectJournals() ', $this->journals->count()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -109,7 +113,7 @@ class Processor
|
|||||||
$uploadCollector = app(UploadCollector::class, [$this->job]);
|
$uploadCollector = app(UploadCollector::class, [$this->job]);
|
||||||
$uploadCollector->run();
|
$uploadCollector->run();
|
||||||
|
|
||||||
$this->files = $this->files->merge($uploadCollector->getFiles());
|
$this->files = $this->files->merge($uploadCollector->getEntries());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -120,22 +124,11 @@ class Processor
|
|||||||
public function convertJournals(): bool
|
public function convertJournals(): bool
|
||||||
{
|
{
|
||||||
$count = 0;
|
$count = 0;
|
||||||
/** @var TransactionJournal $journal */
|
foreach ($this->journals as $object) {
|
||||||
foreach ($this->journals as $journal) {
|
$this->exportEntries->push(Entry::fromObject($object));
|
||||||
$this->exportEntries->push(Entry::fromJournal($journal));
|
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function createConfigFile(): bool
|
|
||||||
{
|
|
||||||
$this->configurationMaker = app(ConfigurationFile::class, [$this->job]);
|
|
||||||
$this->files->push($this->configurationMaker->make());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* AccountChartGeneratorInterface.php
|
* AccountChartGeneratorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -22,7 +24,6 @@ use Illuminate\Support\Collection;
|
|||||||
*/
|
*/
|
||||||
interface AccountChartGeneratorInterface
|
interface AccountChartGeneratorInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
@@ -41,6 +42,15 @@ interface AccountChartGeneratorInterface
|
|||||||
*/
|
*/
|
||||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array;
|
public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function revenueAccounts(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param array $labels
|
* @param array $labels
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ChartJsAccountChartGenerator.php
|
* ChartJsAccountChartGenerator.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -81,6 +83,30 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function revenueAccounts(Collection $accounts, Carbon $start, Carbon $end): array
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'count' => 1,
|
||||||
|
'labels' => [], 'datasets' => [[
|
||||||
|
'label' => trans('firefly.earned'),
|
||||||
|
'data' => []]]];
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
if ($account->difference > 0) {
|
||||||
|
$data['labels'][] = $account->name;
|
||||||
|
$data['datasets'][0]['data'][] = $account->difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param array $labels
|
* @param array $labels
|
||||||
@@ -103,5 +129,4 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
|||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BillChartGeneratorInterface.php
|
* BillChartGeneratorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ChartJsBillChartGenerator.php
|
* ChartJsBillChartGenerator.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BudgetChartGeneratorInterface.php
|
* BudgetChartGeneratorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ChartJsBudgetChartGenerator.php
|
* ChartJsBudgetChartGenerator.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* CategoryChartGeneratorInterface.php
|
* CategoryChartGeneratorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ChartJsCategoryChartGenerator.php
|
* ChartJsCategoryChartGenerator.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ChartJsPiggyBankChartGenerator.php
|
* ChartJsPiggyBankChartGenerator.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* PiggyBankChartGeneratorInterface.php
|
* PiggyBankChartGeneratorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ChartJsReportChartGenerator.php
|
* ChartJsReportChartGenerator.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ReportChartGeneratorInterface.php
|
* ReportChartGeneratorInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* AttachUserRole.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
|
|
||||||
use FireflyIII\Events\UserRegistration;
|
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class AttachUserRole
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class AttachUserRole
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create the event listener.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the event.
|
|
||||||
*
|
|
||||||
* @param UserRegistration $event
|
|
||||||
*/
|
|
||||||
public function handle(UserRegistration $event)
|
|
||||||
{
|
|
||||||
/** @var UserRepositoryInterface $repository */
|
|
||||||
$repository = app(UserRepositoryInterface::class);
|
|
||||||
|
|
||||||
// first user ever?
|
|
||||||
if ($repository->count() == 1) {
|
|
||||||
$repository->attachRole($event->user, 'owner');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,46 +1,42 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* BudgetLimitEventHandler.php
|
* BudgetEventHandler.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
use FireflyIII\Events\BudgetLimitStored;
|
|
||||||
use FireflyIII\Events\BudgetLimitUpdated;
|
use FireflyIII\Events\StoredBudgetLimit;
|
||||||
|
use FireflyIII\Events\UpdatedBudgetLimit;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\LimitRepetition;
|
||||||
use Illuminate\Database\QueryException;
|
use Illuminate\Database\QueryException;
|
||||||
use Log;
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimitEventHandler
|
* Handles budget related events.
|
||||||
|
*
|
||||||
|
* Class BudgetEventHandler
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Handlers\Events
|
* @package FireflyIII\Handlers\Events
|
||||||
*/
|
*/
|
||||||
class BudgetLimitEventHandler
|
class BudgetEventHandler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Create the event listener.
|
* This method creates a new budget limit repetition when a new budget limit has been created.
|
||||||
*
|
*
|
||||||
*/
|
* @param StoredBudgetLimit $event
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In a perfect world, the store() routine should be different from the update()
|
|
||||||
* routine. It would not have to check count() == 0 because there could be NO
|
|
||||||
* limit repetitions at this point. However, the database can be wrong so we check.
|
|
||||||
*
|
*
|
||||||
* @param BudgetLimitStored $event
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function store(BudgetLimitStored $event)
|
public function storeRepetition(StoredBudgetLimit $event):bool
|
||||||
{
|
{
|
||||||
$budgetLimit = $event->budgetLimit;
|
$budgetLimit = $event->budgetLimit;
|
||||||
$end = $event->end;
|
$end = $event->end;
|
||||||
@@ -69,12 +65,18 @@ class BudgetLimitEventHandler
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BudgetLimitUpdated $event
|
* Updates, if present the budget limit repetition part of a budget limit.
|
||||||
|
*
|
||||||
|
* @param UpdatedBudgetLimit $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function update(BudgetLimitUpdated $event)
|
public function updateRepetition(UpdatedBudgetLimit $event): bool
|
||||||
{
|
{
|
||||||
$budgetLimit = $event->budgetLimit;
|
$budgetLimit = $event->budgetLimit;
|
||||||
$end = $event->end;
|
$end = $event->end;
|
||||||
@@ -102,6 +104,7 @@ class BudgetLimitEventHandler
|
|||||||
$repetition->save();
|
$repetition->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ConnectJournalToPiggyBank.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionJournalStored;
|
|
||||||
use FireflyIII\Models\PiggyBank;
|
|
||||||
use FireflyIII\Models\PiggyBankEvent;
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConnectJournalToPiggyBank
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class ConnectJournalToPiggyBank
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect a new transaction journal to any related piggy banks.
|
|
||||||
*
|
|
||||||
* @param TransactionJournalStored $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionJournalStored $event): bool
|
|
||||||
{
|
|
||||||
/** @var TransactionJournal $journal */
|
|
||||||
$journal = $event->journal;
|
|
||||||
$piggyBankId = $event->piggyBankId;
|
|
||||||
|
|
||||||
/** @var PiggyBank $piggyBank */
|
|
||||||
$piggyBank = auth()->user()->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
|
||||||
|
|
||||||
if (is_null($piggyBank)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// update piggy bank rep for date of transaction journal.
|
|
||||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
|
||||||
if (is_null($repetition)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$amount = TransactionJournal::amountPositive($journal);
|
|
||||||
// if piggy account matches source account, the amount is positive
|
|
||||||
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
|
|
||||||
if (in_array($piggyBank->account_id, $sources)) {
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
|
||||||
$repetition->save();
|
|
||||||
|
|
||||||
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ConnectTransactionToPiggyBank.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionStored;
|
|
||||||
use FireflyIII\Models\PiggyBankEvent;
|
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConnectTransactionToPiggyBank
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class ConnectTransactionToPiggyBank
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect a new transaction journal to any related piggy banks.
|
|
||||||
*
|
|
||||||
* @param TransactionStored $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionStored $event): bool
|
|
||||||
{
|
|
||||||
|
|
||||||
/** @var PiggyBankRepositoryInterface $repository */
|
|
||||||
$repository = app(PiggyBankRepositoryInterface::class);
|
|
||||||
$transaction = $event->transaction;
|
|
||||||
|
|
||||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
|
||||||
|
|
||||||
// valid piggy:
|
|
||||||
if (is_null($piggyBank->id)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$amount = strval($transaction['amount']);
|
|
||||||
// piggy bank account something with amount:
|
|
||||||
if ($transaction['source_account_id'] == $piggyBank->account_id) {
|
|
||||||
// if the source of this transaction is the same as the piggy bank,
|
|
||||||
// the money is being removed from the piggy bank. So the
|
|
||||||
// amount must be negative:
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
$repetition = $piggyBank->currentRelevantRep();
|
|
||||||
// add or remove the money from the piggy bank:
|
|
||||||
$newAmount = bcadd(strval($repetition->currentamount), $amount);
|
|
||||||
$repetition->currentamount = $newAmount;
|
|
||||||
$repetition->save();
|
|
||||||
|
|
||||||
// now generate a piggy bank event:
|
|
||||||
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'date' => $transaction['date'], 'amount' => $newAmount]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* FireRulesForStore.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionJournalStored;
|
|
||||||
use FireflyIII\Models\Rule;
|
|
||||||
use FireflyIII\Models\RuleGroup;
|
|
||||||
use FireflyIII\Rules\Processor;
|
|
||||||
use FireflyIII\User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class FireRulesForStore
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class FireRulesForStore
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect a new transaction journal to any related piggy banks.
|
|
||||||
*
|
|
||||||
* @param TransactionJournalStored $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionJournalStored $event): bool
|
|
||||||
{
|
|
||||||
// get all the user's rule groups, with the rules, order by 'order'.
|
|
||||||
/** @var User $user */
|
|
||||||
$user = auth()->user();
|
|
||||||
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
|
||||||
//
|
|
||||||
/** @var RuleGroup $group */
|
|
||||||
foreach ($groups as $group) {
|
|
||||||
$rules = $group->rules()
|
|
||||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
|
||||||
->where('rule_triggers.trigger_type', 'user_action')
|
|
||||||
->where('rule_triggers.trigger_value', 'store-journal')
|
|
||||||
->where('rules.active', 1)
|
|
||||||
->get(['rules.*']);
|
|
||||||
/** @var Rule $rule */
|
|
||||||
foreach ($rules as $rule) {
|
|
||||||
|
|
||||||
$processor = Processor::make($rule);
|
|
||||||
$processor->handleTransactionJournal($event->journal);
|
|
||||||
|
|
||||||
if ($rule->stop_processing) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* FireRulesForUpdate.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionJournalUpdated;
|
|
||||||
use FireflyIII\Models\Rule;
|
|
||||||
use FireflyIII\Models\RuleGroup;
|
|
||||||
use FireflyIII\Rules\Processor;
|
|
||||||
use FireflyIII\User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class FireRulesForUpdate
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class FireRulesForUpdate
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle the event.
|
|
||||||
*
|
|
||||||
* @param TransactionJournalUpdated $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionJournalUpdated $event): bool
|
|
||||||
{
|
|
||||||
// get all the user's rule groups, with the rules, order by 'order'.
|
|
||||||
/** @var User $user */
|
|
||||||
$user = auth()->user();
|
|
||||||
$groups = $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
|
||||||
//
|
|
||||||
/** @var RuleGroup $group */
|
|
||||||
foreach ($groups as $group) {
|
|
||||||
$rules = $group->rules()
|
|
||||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
|
||||||
->where('rule_triggers.trigger_type', 'user_action')
|
|
||||||
->where('rule_triggers.trigger_value', 'update-journal')
|
|
||||||
->where('rules.active', 1)
|
|
||||||
->get(['rules.*']);
|
|
||||||
/** @var Rule $rule */
|
|
||||||
foreach ($rules as $rule) {
|
|
||||||
$processor = Processor::make($rule);
|
|
||||||
$processor->handleTransactionJournal($event->journal);
|
|
||||||
|
|
||||||
if ($rule->stop_processing) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ScanForBillsAfterStore.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionJournalStored;
|
|
||||||
use FireflyIII\Support\Events\BillScanner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class RescanJournal
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class ScanForBillsAfterStore
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan a transaction journal for possible links to bills, right after storing.
|
|
||||||
*
|
|
||||||
* @param TransactionJournalStored $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionJournalStored $event): bool
|
|
||||||
{
|
|
||||||
$journal = $event->journal;
|
|
||||||
BillScanner::scan($journal);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ScanForBillsAfterUpdate.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionJournalUpdated;
|
|
||||||
use FireflyIII\Support\Events\BillScanner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class RescanJournal
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class ScanForBillsAfterUpdate
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Scan a transaction journal for possibly related bills after it has been updated.
|
|
||||||
*
|
|
||||||
* @param TransactionJournalUpdated $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionJournalUpdated $event): bool
|
|
||||||
{
|
|
||||||
$journal = $event->journal;
|
|
||||||
BillScanner::scan($journal);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* SendRegistrationMail.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
|
|
||||||
use FireflyIII\Events\UserRegistration;
|
|
||||||
use Illuminate\Mail\Message;
|
|
||||||
use Log;
|
|
||||||
use Mail;
|
|
||||||
use Swift_TransportException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class SendRegistrationMail
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class SendRegistrationMail
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create the event listener.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the event.
|
|
||||||
*
|
|
||||||
* @param UserRegistration $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(UserRegistration $event): bool
|
|
||||||
{
|
|
||||||
$sendMail = env('SEND_REGISTRATION_MAIL', true);
|
|
||||||
if (!$sendMail) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// get the email address
|
|
||||||
$email = $event->user->email;
|
|
||||||
$address = route('index');
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
// send email.
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
|
|
||||||
$message->to($email, $email)->subject('Welcome to Firefly III! ');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
124
app/Handlers/Events/StoredJournalEventHandler.php
Normal file
124
app/Handlers/Events/StoredJournalEventHandler.php
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StoredJournalEventHandler.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
|
use FireflyIII\Events\StoredTransactionJournal;
|
||||||
|
use FireflyIII\Models\PiggyBank;
|
||||||
|
use FireflyIII\Models\PiggyBankEvent;
|
||||||
|
use FireflyIII\Models\Rule;
|
||||||
|
use FireflyIII\Models\RuleGroup;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Rules\Processor;
|
||||||
|
use FireflyIII\Support\Events\BillScanner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class StoredJournalEventHandler
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Handlers\Events
|
||||||
|
*/
|
||||||
|
class StoredJournalEventHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This method connects a new transfer to a piggy bank.
|
||||||
|
*
|
||||||
|
* @param StoredTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function connectToPiggyBank(StoredTransactionJournal $event): bool
|
||||||
|
{
|
||||||
|
/** @var TransactionJournal $journal */
|
||||||
|
$journal = $event->journal;
|
||||||
|
$piggyBankId = $event->piggyBankId;
|
||||||
|
|
||||||
|
/** @var PiggyBank $piggyBank */
|
||||||
|
$piggyBank = $journal->user->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||||
|
|
||||||
|
if (is_null($piggyBank)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// update piggy bank rep for date of transaction journal.
|
||||||
|
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||||
|
if (is_null($repetition)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$amount = TransactionJournal::amountPositive($journal);
|
||||||
|
// if piggy account matches source account, the amount is positive
|
||||||
|
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
|
||||||
|
if (in_array($piggyBank->account_id, $sources)) {
|
||||||
|
$amount = bcmul($amount, '-1');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||||
|
$repetition->save();
|
||||||
|
|
||||||
|
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method grabs all the users rules and processes them.
|
||||||
|
*
|
||||||
|
* @param StoredTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function processRules(StoredTransactionJournal $event): bool
|
||||||
|
{
|
||||||
|
// get all the user's rule groups, with the rules, order by 'order'.
|
||||||
|
$journal = $event->journal;
|
||||||
|
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||||
|
//
|
||||||
|
/** @var RuleGroup $group */
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
$rules = $group->rules()
|
||||||
|
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||||
|
->where('rule_triggers.trigger_type', 'user_action')
|
||||||
|
->where('rule_triggers.trigger_value', 'store-journal')
|
||||||
|
->where('rules.active', 1)
|
||||||
|
->get(['rules.*']);
|
||||||
|
/** @var Rule $rule */
|
||||||
|
foreach ($rules as $rule) {
|
||||||
|
|
||||||
|
$processor = Processor::make($rule);
|
||||||
|
$processor->handleTransactionJournal($journal);
|
||||||
|
|
||||||
|
if ($rule->stop_processing) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method calls a special bill scanner that will check if the stored journal is part of a bill.
|
||||||
|
*
|
||||||
|
* @param StoredTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function scanBills(StoredTransactionJournal $event): bool
|
||||||
|
{
|
||||||
|
$journal = $event->journal;
|
||||||
|
BillScanner::scan($journal);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* UpdateJournalConnection.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\TransactionJournalUpdated;
|
|
||||||
use FireflyIII\Models\PiggyBankEvent;
|
|
||||||
use FireflyIII\Models\PiggyBankRepetition;
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UpdateJournalConnection
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class UpdateJournalConnection
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the event.
|
|
||||||
*
|
|
||||||
* @param TransactionJournalUpdated $event
|
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handle(TransactionJournalUpdated $event):bool
|
|
||||||
{
|
|
||||||
$journal = $event->journal;
|
|
||||||
|
|
||||||
if (!$journal->isTransfer()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the event connected to this journal:
|
|
||||||
/** @var PiggyBankEvent $event */
|
|
||||||
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
|
|
||||||
if (is_null($event)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$piggyBank = $event->piggyBank()->first();
|
|
||||||
$repetition = null;
|
|
||||||
if (!is_null($piggyBank)) {
|
|
||||||
/** @var PiggyBankRepetition $repetition */
|
|
||||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($repetition)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$amount = TransactionJournal::amount($journal);
|
|
||||||
$diff = bcsub($amount, $event->amount); // update current repetition
|
|
||||||
|
|
||||||
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
|
|
||||||
$repetition->save();
|
|
||||||
|
|
||||||
|
|
||||||
$event->amount = $amount;
|
|
||||||
$event->save();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
128
app/Handlers/Events/UpdatedJournalEventHandler.php
Normal file
128
app/Handlers/Events/UpdatedJournalEventHandler.php
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* UpdatedJournalEventHandler.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Events\UpdatedTransactionJournal;
|
||||||
|
use FireflyIII\Models\PiggyBankEvent;
|
||||||
|
use FireflyIII\Models\PiggyBankRepetition;
|
||||||
|
use FireflyIII\Models\Rule;
|
||||||
|
use FireflyIII\Models\RuleGroup;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Rules\Processor;
|
||||||
|
use FireflyIII\Support\Events\BillScanner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UpdatedJournalEventHandler
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Handlers\Events
|
||||||
|
*/
|
||||||
|
class UpdatedJournalEventHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This method will try to reconnect a journal to a piggy bank, updating the piggy bank repetition.
|
||||||
|
*
|
||||||
|
* @param UpdatedTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function connectToPiggyBank(UpdatedTransactionJournal $event): bool
|
||||||
|
{
|
||||||
|
$journal = $event->journal;
|
||||||
|
|
||||||
|
if (!$journal->isTransfer()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the event connected to this journal:
|
||||||
|
/** @var PiggyBankEvent $event */
|
||||||
|
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
|
||||||
|
if (is_null($event)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$piggyBank = $event->piggyBank()->first();
|
||||||
|
$repetition = null;
|
||||||
|
if (!is_null($piggyBank)) {
|
||||||
|
/** @var PiggyBankRepetition $repetition */
|
||||||
|
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($repetition)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$amount = TransactionJournal::amount($journal);
|
||||||
|
$diff = bcsub($amount, $event->amount); // update current repetition
|
||||||
|
|
||||||
|
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
|
||||||
|
$repetition->save();
|
||||||
|
|
||||||
|
|
||||||
|
$event->amount = $amount;
|
||||||
|
$event->save();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will check all the rules when a journal is updated.
|
||||||
|
*
|
||||||
|
* @param UpdatedTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function processRules(UpdatedTransactionJournal $event):bool
|
||||||
|
{
|
||||||
|
// get all the user's rule groups, with the rules, order by 'order'.
|
||||||
|
$journal = $event->journal;
|
||||||
|
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||||
|
//
|
||||||
|
/** @var RuleGroup $group */
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
$rules = $group->rules()
|
||||||
|
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||||
|
->where('rule_triggers.trigger_type', 'user_action')
|
||||||
|
->where('rule_triggers.trigger_value', 'update-journal')
|
||||||
|
->where('rules.active', 1)
|
||||||
|
->get(['rules.*']);
|
||||||
|
/** @var Rule $rule */
|
||||||
|
foreach ($rules as $rule) {
|
||||||
|
$processor = Processor::make($rule);
|
||||||
|
$processor->handleTransactionJournal($journal);
|
||||||
|
|
||||||
|
if ($rule->stop_processing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method calls a special bill scanner that will check if the updated journal is part of a bill.
|
||||||
|
*
|
||||||
|
* @param UpdatedTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function scanBills(UpdatedTransactionJournal $event): bool
|
||||||
|
{
|
||||||
|
$journal = $event->journal;
|
||||||
|
BillScanner::scan($journal);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* UserConfirmation.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use FireflyIII\Events\ResendConfirmation;
|
|
||||||
use FireflyIII\Events\UserRegistration;
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Mail\Message;
|
|
||||||
use Log;
|
|
||||||
use Mail;
|
|
||||||
use Preferences;
|
|
||||||
use Swift_TransportException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UserConfirmation
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class UserConfirmation
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create the event listener.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ResendConfirmation $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function resendConfirmation(ResendConfirmation $event): bool
|
|
||||||
{
|
|
||||||
$user = $event->user;
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
$this->doConfirm($user, $ipAddress);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the event.
|
|
||||||
*
|
|
||||||
* @param UserRegistration $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function sendConfirmation(UserRegistration $event): bool
|
|
||||||
{
|
|
||||||
$user = $event->user;
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
$this->doConfirm($user, $ipAddress);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param User $user
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
private function doConfirm(User $user, string $ipAddress)
|
|
||||||
{
|
|
||||||
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
|
||||||
if ($confirmAccount === false) {
|
|
||||||
Preferences::setForUser($user, 'user_confirmed', true);
|
|
||||||
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
|
|
||||||
Preferences::mark();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$email = $user->email;
|
|
||||||
$code = str_random(16);
|
|
||||||
$route = route('do_confirm_account', [$code]);
|
|
||||||
Preferences::setForUser($user, 'user_confirmed', false);
|
|
||||||
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
|
|
||||||
Preferences::setForUser($user, 'user_confirmed_code', $code);
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
|
|
||||||
function (Message $message) use ($email) {
|
|
||||||
$message->to($email, $email)->subject('Please confirm your Firefly III account');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
225
app/Handlers/Events/UserEventHandler.php
Normal file
225
app/Handlers/Events/UserEventHandler.php
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* UserEventHandler.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use FireflyIII\Events\ConfirmedUser;
|
||||||
|
use FireflyIII\Events\RegisteredUser;
|
||||||
|
use FireflyIII\Events\ResentConfirmation;
|
||||||
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use Illuminate\Mail\Message;
|
||||||
|
use Log;
|
||||||
|
use Mail;
|
||||||
|
use Preferences;
|
||||||
|
use Session;
|
||||||
|
use Swift_TransportException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserEventHandler
|
||||||
|
*
|
||||||
|
* This class responds to any events that have anything to do with the User object.
|
||||||
|
*
|
||||||
|
* The method name reflects what is being done. This is in the present tense.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Handlers\Events
|
||||||
|
*/
|
||||||
|
class UserEventHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will bestow upon a user the "owner" role if he is the first user in the system.
|
||||||
|
*
|
||||||
|
* @param RegisteredUser $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function attachUserRole(RegisteredUser $event): bool
|
||||||
|
{
|
||||||
|
/** @var UserRepositoryInterface $repository */
|
||||||
|
$repository = app(UserRepositoryInterface::class);
|
||||||
|
|
||||||
|
// first user ever?
|
||||||
|
if ($repository->count() === 1) {
|
||||||
|
$repository->attachRole($event->user, 'owner');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle user logout events.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function logoutUser(): bool
|
||||||
|
{
|
||||||
|
// dump stuff from the session:
|
||||||
|
Session::forget('twofactor-authenticated');
|
||||||
|
Session::forget('twofactor-authenticated-date');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will send a newly registered user a confirmation message, urging him or her to activate their account.
|
||||||
|
*
|
||||||
|
* @param RegisteredUser $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function sendConfirmationMessage(RegisteredUser $event): bool
|
||||||
|
{
|
||||||
|
$user = $event->user;
|
||||||
|
$ipAddress = $event->ipAddress;
|
||||||
|
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
||||||
|
if ($confirmAccount === false) {
|
||||||
|
Preferences::setForUser($user, 'user_confirmed', true);
|
||||||
|
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
|
||||||
|
Preferences::mark();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$email = $user->email;
|
||||||
|
$code = str_random(16);
|
||||||
|
$route = route('do_confirm_account', [$code]);
|
||||||
|
Preferences::setForUser($user, 'user_confirmed', false);
|
||||||
|
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
|
||||||
|
Preferences::setForUser($user, 'user_confirmed_code', $code);
|
||||||
|
try {
|
||||||
|
Mail::send(
|
||||||
|
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
|
||||||
|
function (Message $message) use ($email) {
|
||||||
|
$message->to($email, $email)->subject('Please confirm your Firefly III account');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (Swift_TransportException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the user has somehow lost his or her confirmation message, this event will send it to the user again.
|
||||||
|
*
|
||||||
|
* At the moment, this method is exactly the same as the ::sendConfirmationMessage method, but that will change.
|
||||||
|
*
|
||||||
|
* @param ResentConfirmation $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function sendConfirmationMessageAgain(ResentConfirmation $event): bool
|
||||||
|
{
|
||||||
|
$user = $event->user;
|
||||||
|
$ipAddress = $event->ipAddress;
|
||||||
|
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
|
||||||
|
if ($confirmAccount === false) {
|
||||||
|
Preferences::setForUser($user, 'user_confirmed', true);
|
||||||
|
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
|
||||||
|
Preferences::mark();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$email = $user->email;
|
||||||
|
$code = str_random(16);
|
||||||
|
$route = route('do_confirm_account', [$code]);
|
||||||
|
Preferences::setForUser($user, 'user_confirmed', false);
|
||||||
|
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
|
||||||
|
Preferences::setForUser($user, 'user_confirmed_code', $code);
|
||||||
|
try {
|
||||||
|
Mail::send(
|
||||||
|
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
|
||||||
|
function (Message $message) use ($email) {
|
||||||
|
$message->to($email, $email)->subject('Please confirm your Firefly III account');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (Swift_TransportException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will send the user a registration mail, welcoming him or her to Firefly III.
|
||||||
|
* This message is only sent when the configuration of Firefly III says so.
|
||||||
|
*
|
||||||
|
* @param RegisteredUser $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function sendRegistrationMail(RegisteredUser $event)
|
||||||
|
{
|
||||||
|
|
||||||
|
$sendMail = env('SEND_REGISTRATION_MAIL', true);
|
||||||
|
if (!$sendMail) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// get the email address
|
||||||
|
$email = $event->user->email;
|
||||||
|
$address = route('index');
|
||||||
|
$ipAddress = $event->ipAddress;
|
||||||
|
// send email.
|
||||||
|
try {
|
||||||
|
Mail::send(
|
||||||
|
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
|
||||||
|
$message->to($email, $email)->subject('Welcome to Firefly III! ');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (Swift_TransportException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the user is confirmed, this method stores the IP address of the user
|
||||||
|
* as a preference. Since this preference cannot be edited, it is effectively hidden
|
||||||
|
* from the user yet stored conveniently.
|
||||||
|
*
|
||||||
|
* @param ConfirmedUser $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function storeConfirmationIpAddress(ConfirmedUser $event): bool
|
||||||
|
{
|
||||||
|
Preferences::setForUser($event->user, 'confirmation_ip_address', $event->ipAddress);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This message stores the users IP address on registration, in much the same
|
||||||
|
* fashion as the previous method.
|
||||||
|
*
|
||||||
|
* @param RegisteredUser $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function storeRegistrationIpAddress(RegisteredUser $event): bool
|
||||||
|
{
|
||||||
|
Preferences::setForUser($event->user, 'registration_ip_address', $event->ipAddress);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* UserEventListener.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use Session;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UserEventListener
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class UserEventListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle user logout events.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function onUserLogout(): bool
|
|
||||||
{
|
|
||||||
// dump stuff from the session:
|
|
||||||
Session::forget('twofactor-authenticated');
|
|
||||||
Session::forget('twofactor-authenticated-date');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* UserSaveIpAddress.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
|
||||||
|
|
||||||
use FireflyIII\Events\UserIsConfirmed;
|
|
||||||
use FireflyIII\Events\UserRegistration;
|
|
||||||
use 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* AttachmentHelper.php
|
* AttachmentHelper.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* AttachmentHelperInterface.php
|
* AttachmentHelperInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Account.php
|
* Account.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Balance.php
|
* Balance.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BalanceEntry.php
|
* BalanceEntry.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BalanceHeader.php
|
* BalanceHeader.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BalanceLine.php
|
* BalanceLine.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Bill.php
|
* Bill.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BillLine.php
|
* BillLine.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Budget.php
|
* Budget.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BudgetLine.php
|
* BudgetLine.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Category.php
|
* Category.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
* Expense.php
|
* Expense.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
namespace FireflyIII\Helpers\Collection;
|
namespace FireflyIII\Helpers\Collection;
|
||||||
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
@@ -36,36 +37,11 @@ class Expense
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $entry
|
* @param stdClass $entry
|
||||||
*/
|
*/
|
||||||
public function addOrCreateExpense(TransactionJournal $entry)
|
public function addOrCreateExpense(stdClass $entry)
|
||||||
{
|
{
|
||||||
// add each account individually:
|
$this->expenses->put($entry->id, $entry);
|
||||||
$destinations = TransactionJournal::destinationTransactionList($entry);
|
|
||||||
|
|
||||||
foreach ($destinations as $transaction) {
|
|
||||||
$amount = strval($transaction->amount);
|
|
||||||
$account = $transaction->account;
|
|
||||||
if (bccomp('0', $amount) === -1) {
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
$object = new stdClass;
|
|
||||||
$object->amount = $amount;
|
|
||||||
$object->name = $account->name;
|
|
||||||
$object->count = 1;
|
|
||||||
$object->id = $account->id;
|
|
||||||
|
|
||||||
// overrule some properties:
|
|
||||||
if ($this->expenses->has($account->id)) {
|
|
||||||
$object = $this->expenses->get($account->id);
|
|
||||||
$object->amount = bcadd($object->amount, $amount);
|
|
||||||
$object->count++;
|
|
||||||
}
|
|
||||||
$this->expenses->put($account->id, $object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
* Income.php
|
* Income.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
namespace FireflyIII\Helpers\Collection;
|
namespace FireflyIII\Helpers\Collection;
|
||||||
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
@@ -37,32 +38,11 @@ class Income
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $entry
|
* @param stdClass $entry
|
||||||
*/
|
*/
|
||||||
public function addOrCreateIncome(TransactionJournal $entry)
|
public function addOrCreateIncome(stdClass $entry)
|
||||||
{
|
{
|
||||||
// add each account individually:
|
$this->incomes->put($entry->id, $entry);
|
||||||
$sources = TransactionJournal::sourceTransactionList($entry);
|
|
||||||
|
|
||||||
foreach ($sources as $transaction) {
|
|
||||||
$amount = strval($transaction->amount);
|
|
||||||
$account = $transaction->account;
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
|
|
||||||
$object = new stdClass;
|
|
||||||
$object->amount = $amount;
|
|
||||||
$object->name = $account->name;
|
|
||||||
$object->count = 1;
|
|
||||||
$object->id = $account->id;
|
|
||||||
|
|
||||||
// overrule some properties:
|
|
||||||
if ($this->incomes->has($account->id)) {
|
|
||||||
$object = $this->incomes->get($account->id);
|
|
||||||
$object->amount = bcadd($object->amount, $amount);
|
|
||||||
$object->count++;
|
|
||||||
}
|
|
||||||
$this->incomes->put($account->id, $object);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* FiscalHelper.php
|
* FiscalHelper.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* FiscalHelperInterface.php
|
* FiscalHelperInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* Help.php
|
* Help.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -24,47 +26,39 @@ class Help implements HelpInterface
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param string $route
|
||||||
* @param string $key
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromCache(string $key): string
|
public function getFromCache(string $route, string $language): string
|
||||||
{
|
{
|
||||||
return Cache::get($key);
|
return Cache::get('help.' . $route . '.' . $language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param string $route
|
* @param string $route
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromGithub(string $language, string $route): array
|
public function getFromGithub(string $language, string $route): string
|
||||||
{
|
{
|
||||||
|
|
||||||
$uri = sprintf('https://raw.githubusercontent.com/JC5/firefly-iii-help/master/%s/%s.md', $language, $route);
|
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
|
||||||
$routeIndex = str_replace('.', '-', $route);
|
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
$title = trans('help.' . $routeIndex);
|
$result = Requests::get($uri);
|
||||||
$content = [
|
|
||||||
'text' => '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>',
|
|
||||||
'title' => $title,
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
$result = Requests::get($uri);
|
|
||||||
|
|
||||||
|
|
||||||
if ($result->status_code === 200) {
|
if ($result->status_code === 200) {
|
||||||
$content['text'] = $result->body;
|
$content = $result->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (strlen(trim($content['text'])) == 0) {
|
if (strlen(trim($content)) == 0) {
|
||||||
$content['text'] = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
}
|
}
|
||||||
$converter = new CommonMarkConverter();
|
$converter = new CommonMarkConverter();
|
||||||
$content['text'] = $converter->convertToHtml($content['text']);
|
$content = $converter->convertToHtml($content);
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
|
|
||||||
@@ -82,27 +76,26 @@ class Help implements HelpInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param string $route
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function inCache(string $route):bool
|
public function inCache(string $route, string $language):bool
|
||||||
{
|
{
|
||||||
return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text');
|
return Cache::has('help.' . $route . '.' . $language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param string $route
|
* @param string $route
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param array $content
|
* @param string $content
|
||||||
*
|
*
|
||||||
* @internal param $title
|
* @internal param $title
|
||||||
*/
|
*/
|
||||||
public function putInCache(string $route, string $language, array $content)
|
public function putInCache(string $route, string $language, string $content)
|
||||||
{
|
{
|
||||||
Cache::put('help.' . $route . '.text.' . $language, $content['text'], 10080); // a week.
|
Cache::put('help.' . $route . '.' . $language, $content, 10080); // a week.
|
||||||
Cache::put('help.' . $route . '.title.' . $language, $content['title'], 10080);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* HelpInterface.php
|
* HelpInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -19,19 +21,20 @@ interface HelpInterface
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $key
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromCache(string $key): string;
|
public function getFromCache(string $route, string $language): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param string $route
|
* @param string $route
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromGithub(string $language, string $route):array;
|
public function getFromGithub(string $language, string $route):string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $route
|
* @param string $route
|
||||||
@@ -42,15 +45,16 @@ interface HelpInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $route
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function inCache(string $route): bool;
|
public function inCache(string $route, string $language ): bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $route
|
* @param string $route
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param array $content
|
* @param string $content
|
||||||
*/
|
*/
|
||||||
public function putInCache(string $route, string $language, array $content);
|
public function putInCache(string $route, string $language, string $content);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* AccountReportHelper.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Helpers\Report;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use DB;
|
|
||||||
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class AccountReportHelper
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Helpers\Report
|
|
||||||
*/
|
|
||||||
class AccountReportHelper implements AccountReportHelperInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param Collection $startSet
|
|
||||||
* @param Collection $endSet
|
|
||||||
* @param Collection $backupSet
|
|
||||||
*
|
|
||||||
* @return Account
|
|
||||||
*/
|
|
||||||
public static function reportFilter(Account $account, Collection $startSet, Collection $endSet, Collection $backupSet)
|
|
||||||
{
|
|
||||||
// The balance for today always incorporates transactions made on today. So to get todays "start" balance, we sub one day.
|
|
||||||
$account->startBalance = '0';
|
|
||||||
$account->endBalance = '0';
|
|
||||||
$currentStart = $startSet->filter(
|
|
||||||
function (Account $entry) use ($account) {
|
|
||||||
return $account->id == $entry->id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$currentBackup = $backupSet->filter( // grab entry from current backup as well:
|
|
||||||
function (Account $entry) use ($account) {
|
|
||||||
return $account->id == $entry->id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// first try to set from backup
|
|
||||||
if (!is_null($currentBackup->first())) {
|
|
||||||
$account->startBalance = $currentBackup->first()->balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// overrule with data from start
|
|
||||||
if (!is_null($currentStart->first())) {
|
|
||||||
$account->startBalance = $currentStart->first()->balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
$currentEnd = $endSet->filter(
|
|
||||||
function (Account $entry) use ($account) {
|
|
||||||
return $account->id == $entry->id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!is_null($currentEnd->first())) {
|
|
||||||
$account->endBalance = $currentEnd->first()->balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method generates a full report for the given period on all
|
|
||||||
* given accounts.
|
|
||||||
*
|
|
||||||
* a special consideration for accounts that did exist on this exact day.
|
|
||||||
* we also grab the balance from today just in case, to see if that changes things.
|
|
||||||
* it's a fall back for users who (rightly so) start keeping score at the first of
|
|
||||||
* the month and find the first report lacking / broken.
|
|
||||||
*
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
* @param Collection $accounts
|
|
||||||
*
|
|
||||||
* @return AccountCollection
|
|
||||||
*/
|
|
||||||
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection
|
|
||||||
{
|
|
||||||
$startAmount = '0';
|
|
||||||
$endAmount = '0';
|
|
||||||
$diff = '0';
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
|
||||||
$yesterday = clone $start;
|
|
||||||
$yesterday->subDay();
|
|
||||||
$startSet = $this->getSet($ids, $yesterday); // get balances for start.
|
|
||||||
$backupSet = $this->getSet($ids, $start);
|
|
||||||
$endSet = $this->getSet($ids, $end);
|
|
||||||
|
|
||||||
$accounts->each(
|
|
||||||
function (Account $account) use ($startSet, $endSet, $backupSet) {
|
|
||||||
return self::reportFilter($account, $startSet, $endSet, $backupSet);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// summarize:
|
|
||||||
foreach ($accounts as $account) {
|
|
||||||
$startAmount = bcadd($startAmount, $account->startBalance);
|
|
||||||
$endAmount = bcadd($endAmount, $account->endBalance);
|
|
||||||
$diff = bcadd($diff, bcsub($account->endBalance, $account->startBalance));
|
|
||||||
}
|
|
||||||
|
|
||||||
$object = new AccountCollection;
|
|
||||||
$object->setStart($startAmount);
|
|
||||||
$object->setEnd($endAmount);
|
|
||||||
$object->setDifference($diff);
|
|
||||||
$object->setAccounts($accounts);
|
|
||||||
|
|
||||||
return $object;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $ids
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
private function getSet(array $ids, Carbon $date): Collection
|
|
||||||
{
|
|
||||||
return Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
|
||||||
->whereIn('accounts.id', $ids)
|
|
||||||
->whereNull('transaction_journals.deleted_at')
|
|
||||||
->whereNull('transactions.deleted_at')
|
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
|
|
||||||
->groupBy('accounts.id')
|
|
||||||
->get(['accounts.id', DB::raw('SUM(`transactions`.`amount`) as `balance`')]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* AccountReportHelperInterface.php
|
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
|
||||||
*
|
|
||||||
* This software may be modified and distributed under the terms
|
|
||||||
* of the MIT license. See the LICENSE file for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace FireflyIII\Helpers\Report;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface AccountReportHelperInterface
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Helpers\Report
|
|
||||||
*/
|
|
||||||
interface AccountReportHelperInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method generates a full report for the given period on all
|
|
||||||
* given accounts
|
|
||||||
*
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
* @param Collection $accounts
|
|
||||||
*
|
|
||||||
* @return AccountCollection
|
|
||||||
*/
|
|
||||||
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,10 @@
|
|||||||
* BalanceReportHelper.php
|
* BalanceReportHelper.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -126,7 +128,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
|||||||
->get(
|
->get(
|
||||||
[
|
[
|
||||||
't_destination.account_id',
|
't_destination.account_id',
|
||||||
DB::raw('SUM(`t_destination`.`amount`) as `sum`'),
|
DB::raw('SUM(t_destination.amount) AS sum'),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BalanceReportHelperInterface.php
|
* BalanceReportHelperInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BudgetReportHelper.php
|
* BudgetReportHelper.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* BudgetReportHelperInterface.php
|
* BudgetReportHelperInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ReportHelper.php
|
* ReportHelper.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -22,7 +24,7 @@ use FireflyIII\Models\Bill;
|
|||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
@@ -30,6 +32,7 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
|||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Query\JoinClause;
|
use Illuminate\Database\Query\JoinClause;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ReportHelper
|
* Class ReportHelper
|
||||||
@@ -99,7 +102,8 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
$billLine->setHit(true);
|
$billLine->setHit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($billLine->isActive()) {
|
// non active AND non hit? do not add:
|
||||||
|
if ($billLine->isActive() || $billLine->isHit()) {
|
||||||
$collection->addBill($billLine);
|
$collection->addBill($billLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,14 +148,14 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): Expense
|
public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): Expense
|
||||||
{
|
{
|
||||||
$object = new Expense;
|
$object = new Expense;
|
||||||
/** @var AccountRepositoryInterface $repos */
|
|
||||||
$repos = app(AccountRepositoryInterface::class);
|
|
||||||
$journals = $repos->expensesInPeriod($accounts, $start, $end);
|
|
||||||
|
|
||||||
/** @var TransactionJournal $entry */
|
/** @var AccountTaskerInterface $tasker */
|
||||||
foreach ($journals as $entry) {
|
$tasker = app(AccountTaskerInterface::class);
|
||||||
$amount = TransactionJournal::amount($entry);
|
$collection = $tasker->expenseReport($accounts, $accounts, $start, $end);
|
||||||
$object->addToTotal($amount);
|
|
||||||
|
/** @var stdClass $entry */
|
||||||
|
foreach ($collection as $entry) {
|
||||||
|
$object->addToTotal($entry->amount);
|
||||||
$object->addOrCreateExpense($entry);
|
$object->addOrCreateExpense($entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,13 +174,13 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): Income
|
public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): Income
|
||||||
{
|
{
|
||||||
$object = new Income;
|
$object = new Income;
|
||||||
/** @var AccountRepositoryInterface $repos */
|
/** @var AccountTaskerInterface $tasker */
|
||||||
$repos = app(AccountRepositoryInterface::class);
|
$tasker = app(AccountTaskerInterface::class);
|
||||||
$journals = $repos->incomesInPeriod($accounts, $start, $end);
|
$collection = $tasker->incomeReport($accounts, $accounts, $start, $end);
|
||||||
|
|
||||||
foreach ($journals as $entry) {
|
/** @var stdClass $entry */
|
||||||
$amount = TransactionJournal::amount($entry);
|
foreach ($collection as $entry) {
|
||||||
$object->addToTotal($amount);
|
$object->addToTotal($entry->amount);
|
||||||
$object->addOrCreateIncome($entry);
|
$object->addOrCreateIncome($entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,9 +259,19 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
->where(
|
->where(
|
||||||
function (Builder $q) use ($ids) {
|
// source.account_id in accountIds XOR destination.account_id in accountIds
|
||||||
$q->whereIn('source.account_id', $ids)
|
function (Builder $query) use ($ids) {
|
||||||
->whereIn('destination.account_id', $ids, 'xor');
|
$query->where(
|
||||||
|
function (Builder $q1) use ($ids) {
|
||||||
|
$q1->whereIn('source.account_id', $ids)
|
||||||
|
->whereNotIn('destination.account_id', $ids);
|
||||||
|
}
|
||||||
|
)->orWhere(
|
||||||
|
function (Builder $q2) use ($ids) {
|
||||||
|
$q2->whereIn('destination.account_id', $ids)
|
||||||
|
->whereNotIn('source.account_id', $ids);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
->get(['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'destination.amount']);
|
->get(['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'destination.amount']);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ReportHelperInterface.php
|
* ReportHelperInterface.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* AccountController.php
|
* AccountController.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -13,11 +15,13 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use ExpandedForm;
|
use ExpandedForm;
|
||||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Http\Requests\AccountFormRequest;
|
use FireflyIII\Http\Requests\AccountFormRequest;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
||||||
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -42,8 +46,16 @@ class AccountController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('mainTitleIcon', 'fa-credit-card');
|
|
||||||
View::share('title', trans('firefly.accounts'));
|
// translations:
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('mainTitleIcon', 'fa-credit-card');
|
||||||
|
View::share('title', trans('firefly.accounts'));
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,16 +82,16 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AccountCrudInterface $crud
|
* @param ARI $repository
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function delete(AccountCrudInterface $crud, Account $account)
|
public function delete(ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
$typeName = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
$typeName = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||||
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
|
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
|
||||||
$accountList = ExpandedForm::makeSelectListWithEmpty($crud->getAccountsByType([$account->accountType->type]));
|
$accountList = ExpandedForm::makeSelectListWithEmpty($repository->getAccountsByType([$account->accountType->type]));
|
||||||
unset($accountList[$account->id]);
|
unset($accountList[$account->id]);
|
||||||
|
|
||||||
// put previous url in session
|
// put previous url in session
|
||||||
@@ -91,19 +103,19 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AccountCrudInterface $crud
|
* @param ARI $repository
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function destroy(AccountCrudInterface $crud, Account $account)
|
public function destroy(ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
$type = $account->accountType->type;
|
$type = $account->accountType->type;
|
||||||
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
||||||
$name = $account->name;
|
$name = $account->name;
|
||||||
$moveTo = $crud->find(intval(Input::get('move_account_before_delete')));
|
$moveTo = $repository->find(intval(Input::get('move_account_before_delete')));
|
||||||
|
|
||||||
$crud->destroy($account, $moveTo);
|
$repository->destroy($account, $moveTo);
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.' . $typeName . '_deleted', ['name' => $name])));
|
Session::flash('success', strval(trans('firefly.' . $typeName . '_deleted', ['name' => $name])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
@@ -112,18 +124,16 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ARI $repository
|
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function edit(ARI $repository, Account $account)
|
public function edit(Account $account)
|
||||||
{
|
{
|
||||||
|
|
||||||
$what = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
$what = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||||
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
|
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
|
||||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||||
$openingBalance = $repository->openingBalanceTransaction($account);
|
|
||||||
|
|
||||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||||
if (session('accounts.edit.fromUpdate') !== true) {
|
if (session('accounts.edit.fromUpdate') !== true) {
|
||||||
@@ -134,21 +144,19 @@ class AccountController extends Controller
|
|||||||
// pre fill some useful values.
|
// pre fill some useful values.
|
||||||
|
|
||||||
// the opening balance is tricky:
|
// the opening balance is tricky:
|
||||||
$openingBalanceAmount = null;
|
$openingBalanceAmount = $account->getOpeningBalanceAmount();
|
||||||
|
$openingBalanceAmount = $account->getOpeningBalanceAmount() === '0' ? '' : $openingBalanceAmount;
|
||||||
if ($openingBalance->id) {
|
$openingBalanceDate = $account->getOpeningBalanceDate();
|
||||||
$transaction = $repository->getFirstTransaction($openingBalance, $account);
|
$openingBalanceDate = $openingBalanceDate->year === 1900 ? null : $openingBalanceDate->format('Y-m-d');
|
||||||
$openingBalanceAmount = $transaction->amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
$preFilled = [
|
$preFilled = [
|
||||||
'accountNumber' => $account->getMeta('accountNumber'),
|
'accountNumber' => $account->getMeta('accountNumber'),
|
||||||
'accountRole' => $account->getMeta('accountRole'),
|
'accountRole' => $account->getMeta('accountRole'),
|
||||||
'ccType' => $account->getMeta('ccType'),
|
'ccType' => $account->getMeta('ccType'),
|
||||||
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
||||||
'openingBalanceDate' => $openingBalance->id ? $openingBalance->date->format('Y-m-d') : null,
|
'openingBalanceDate' => $openingBalanceDate,
|
||||||
'openingBalance' => $openingBalanceAmount,
|
'openingBalance' => $openingBalanceAmount,
|
||||||
'virtualBalance' => round($account->virtual_balance, 2),
|
'virtualBalance' => $account->virtual_balance,
|
||||||
];
|
];
|
||||||
Session::flash('preFilled', $preFilled);
|
Session::flash('preFilled', $preFilled);
|
||||||
Session::flash('gaEventCategory', 'accounts');
|
Session::flash('gaEventCategory', 'accounts');
|
||||||
@@ -158,19 +166,19 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AccountCrudInterface $crud
|
* @param ARI $repository
|
||||||
* @param string $what
|
* @param string $what
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function index(AccountCrudInterface $crud, string $what)
|
public function index(ARI $repository, string $what)
|
||||||
{
|
{
|
||||||
$what = $what ?? 'asset';
|
$what = $what ?? 'asset';
|
||||||
|
|
||||||
$subTitle = trans('firefly.' . $what . '_accounts');
|
$subTitle = trans('firefly.' . $what . '_accounts');
|
||||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||||
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
||||||
$accounts = $crud->getAccountsByType($types);
|
$accounts = $repository->getAccountsByType($types);
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = clone session('start', Carbon::now()->startOfMonth());
|
$start = clone session('start', Carbon::now()->startOfMonth());
|
||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
@@ -194,13 +202,17 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ARI $repository
|
* @param AccountTaskerInterface $tasker
|
||||||
* @param Account $account
|
* @param ARI $repository
|
||||||
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function show(ARI $repository, Account $account)
|
public function show(AccountTaskerInterface $tasker, ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
|
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
||||||
|
return $this->redirectToOriginalAccount($account);
|
||||||
|
}
|
||||||
// show journals from current period only:
|
// show journals from current period only:
|
||||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||||
$subTitle = $account->name;
|
$subTitle = $account->name;
|
||||||
@@ -212,7 +224,7 @@ class AccountController extends Controller
|
|||||||
$page = intval(Input::get('page'));
|
$page = intval(Input::get('page'));
|
||||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||||
$offset = ($page - 1) * $pageSize;
|
$offset = ($page - 1) * $pageSize;
|
||||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||||
$count = $set->count();
|
$count = $set->count();
|
||||||
$subSet = $set->splice($offset, $pageSize);
|
$subSet = $set->splice($offset, $pageSize);
|
||||||
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
||||||
@@ -220,10 +232,7 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
// grouped other months thing:
|
// grouped other months thing:
|
||||||
// oldest transaction in account:
|
// oldest transaction in account:
|
||||||
$start = $repository->firstUseDate($account);
|
$start = $repository->oldestJournalDate($account);
|
||||||
if ($start->year == 1900) {
|
|
||||||
$start = new Carbon;
|
|
||||||
}
|
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = Navigation::startOfPeriod($start, $range);
|
$start = Navigation::startOfPeriod($start, $range);
|
||||||
$end = Navigation::endOfX(new Carbon, $range);
|
$end = Navigation::endOfX(new Carbon, $range);
|
||||||
@@ -243,11 +252,17 @@ class AccountController extends Controller
|
|||||||
return view('accounts.show', compact('account', 'what', 'entries', 'subTitleIcon', 'journals', 'subTitle'));
|
return view('accounts.show', compact('account', 'what', 'entries', 'subTitleIcon', 'journals', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only include asset accounts when this account is an asset:
|
||||||
|
$assets = new Collection;
|
||||||
|
if (in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEFAULT])) {
|
||||||
|
$assets = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
||||||
|
}
|
||||||
|
|
||||||
while ($end >= $start) {
|
while ($end >= $start) {
|
||||||
$end = Navigation::startOfPeriod($end, $range);
|
$end = Navigation::startOfPeriod($end, $range);
|
||||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||||
$spent = $this->spentInPeriod($account, $end, $currentEnd);
|
$spent = $tasker->amountOutInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||||
$earned = $this->earnedInPeriod($account, $end, $currentEnd);
|
$earned = $tasker->amountInInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||||
$dateStr = $end->format('Y-m-d');
|
$dateStr = $end->format('Y-m-d');
|
||||||
$dateName = Navigation::periodShow($end, $range);
|
$dateName = Navigation::periodShow($end, $range);
|
||||||
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
||||||
@@ -260,13 +275,13 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ARI $repository
|
* @param AccountTaskerInterface $tasker
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param string $date
|
* @param string $date
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function showWithDate(ARI $repository, Account $account, string $date)
|
public function showWithDate(AccountTaskerInterface $tasker, Account $account, string $date)
|
||||||
{
|
{
|
||||||
$carbon = new Carbon($date);
|
$carbon = new Carbon($date);
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
@@ -277,7 +292,7 @@ class AccountController extends Controller
|
|||||||
$page = $page === 0 ? 1 : $page;
|
$page = $page === 0 ? 1 : $page;
|
||||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||||
$offset = ($page - 1) * $pageSize;
|
$offset = ($page - 1) * $pageSize;
|
||||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||||
$count = $set->count();
|
$count = $set->count();
|
||||||
$subSet = $set->splice($offset, $pageSize);
|
$subSet = $set->splice($offset, $pageSize);
|
||||||
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
||||||
@@ -287,30 +302,16 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AccountFormRequest $request
|
* @param AccountFormRequest $request
|
||||||
* @param AccountCrudInterface $crud
|
* @param ARI $repository
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function store(AccountFormRequest $request, AccountCrudInterface $crud)
|
public function store(AccountFormRequest $request, ARI $repository)
|
||||||
{
|
{
|
||||||
$accountData = [
|
$data = $request->getAccountData();
|
||||||
'name' => $request->input('name'),
|
$account = $repository->store($data);
|
||||||
'accountType' => $request->input('what'),
|
|
||||||
'virtualBalance' => round($request->input('virtualBalance'), 2),
|
|
||||||
'virtualBalanceCurrency' => intval($request->input('amount_currency_id_virtualBalance')),
|
|
||||||
'active' => true,
|
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'iban' => $request->input('iban'),
|
|
||||||
'accountNumber' => $request->input('accountNumber'),
|
|
||||||
'accountRole' => $request->input('accountRole'),
|
|
||||||
'openingBalance' => round($request->input('openingBalance'), 2),
|
|
||||||
'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')),
|
|
||||||
'openingBalanceCurrency' => intval($request->input('amount_currency_id_openingBalance')),
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
$account = $crud->store($accountData);
|
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.stored_new_account', ['name' => $account->name])));
|
Session::flash('success', strval(trans('firefly.stored_new_account', ['name' => $account->name])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
@@ -334,30 +335,16 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AccountFormRequest $request
|
* @param AccountFormRequest $request
|
||||||
* @param AccountCrudInterface $crud
|
* @param ARI $repository
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function update(AccountFormRequest $request, AccountCrudInterface $crud, Account $account)
|
public function update(AccountFormRequest $request, ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
|
$data = $request->getAccountData();
|
||||||
$accountData = [
|
$repository->update($account, $data);
|
||||||
'name' => $request->input('name'),
|
|
||||||
'active' => $request->input('active'),
|
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'iban' => $request->input('iban'),
|
|
||||||
'accountNumber' => $request->input('accountNumber'),
|
|
||||||
'accountRole' => $request->input('accountRole'),
|
|
||||||
'virtualBalance' => round($request->input('virtualBalance'), 2),
|
|
||||||
'openingBalance' => round($request->input('openingBalance'), 2),
|
|
||||||
'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')),
|
|
||||||
'openingBalanceCurrency' => intval($request->input('amount_currency_id_openingBalance')),
|
|
||||||
'ccType' => $request->input('ccType'),
|
|
||||||
'ccMonthlyPaymentDate' => $request->input('ccMonthlyPaymentDate'),
|
|
||||||
];
|
|
||||||
$crud->update($account, $accountData);
|
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
@@ -391,67 +378,27 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asset accounts actually earn money by being the destination of a deposit or the destination
|
|
||||||
* of a transfer. The money moves to them.
|
|
||||||
*
|
|
||||||
* A revenue account doesn't really earn money itself. Money is earned "from" the revenue account.
|
|
||||||
* So, the call to find out how many money has been earned by/from a revenue account is slightly different.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
*
|
||||||
* @return string
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
private function earnedInPeriod(Account $account, Carbon $start, Carbon $end)
|
private function redirectToOriginalAccount(Account $account)
|
||||||
{
|
{
|
||||||
/** @var ARI $repository */
|
/** @var Transaction $transaction */
|
||||||
$repository = app(ARI::class);
|
$transaction = $account->transactions()->first();
|
||||||
$collection = new Collection([$account]);
|
if (is_null($transaction)) {
|
||||||
$type = $account->accountType->type;
|
throw new FireflyException('Expected a transaction. This account has none. BEEP, error.');
|
||||||
switch ($type) {
|
|
||||||
case AccountType::DEFAULT:
|
|
||||||
case AccountType::ASSET:
|
|
||||||
return $repository->earnedInPeriod($collection, $start, $end);
|
|
||||||
case AccountType::REVENUE:
|
|
||||||
return $repository->earnedFromInPeriod($collection, $start, $end);
|
|
||||||
default:
|
|
||||||
return '0';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$journal = $transaction->transactionJournal;
|
||||||
* Asset accounts actually spend money by being the source of a withdrawal or the source
|
/** @var Transaction $opposingTransaction */
|
||||||
* of a transfer. The money moves away from them.
|
$opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first();
|
||||||
*
|
|
||||||
* An expense account doesn't really spend money itself. Money is spent "at" the expense account.
|
if (is_null($opposingTransaction)) {
|
||||||
* So, the call to find out how many money has been spent on/at an expense account is slightly different.
|
throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.');
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param Account $account
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function spentInPeriod(Account $account, Carbon $start, Carbon $end): string
|
|
||||||
{
|
|
||||||
/** @var ARI $repository */
|
|
||||||
$repository = app(ARI::class);
|
|
||||||
$collection = new Collection([$account]);
|
|
||||||
$type = $account->accountType->type;
|
|
||||||
switch ($type) {
|
|
||||||
case AccountType::DEFAULT:
|
|
||||||
case AccountType::ASSET:
|
|
||||||
return $repository->spentInPeriod($collection, $start, $end);
|
|
||||||
case AccountType::EXPENSE:
|
|
||||||
return $repository->spentAtInPeriod($collection, $start, $end);
|
|
||||||
default:
|
|
||||||
return '0';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
return redirect(route('accounts.show', [$opposingTransaction->account_id]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
* ConfigurationController.php
|
* ConfigurationController.php
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This software may be modified and distributed under the terms
|
* This software may be modified and distributed under the terms of the
|
||||||
* of the MIT license. See the LICENSE file for details.
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
@@ -35,8 +37,15 @@ class ConfigurationController extends Controller
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
View::share('title', strval(trans('firefly.administration')));
|
|
||||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', strval(trans('firefly.administration')));
|
||||||
|
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,14 +67,16 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ConfigurationRequest $request
|
* @param ConfigurationRequest $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function store(ConfigurationRequest $request)
|
public function store(ConfigurationRequest $request)
|
||||||
{
|
{
|
||||||
// get config values:
|
// get config values:
|
||||||
$singleUserMode = intval($request->get('single_user_mode')) === 1 ? true : false;
|
$data = $request->getConfigurationData();
|
||||||
|
|
||||||
// store config values
|
// store config values
|
||||||
FireflyConfig::set('single_user_mode', $singleUserMode);
|
FireflyConfig::set('single_user_mode', $data['single_user_mode']);
|
||||||
|
|
||||||
// flash message
|
// flash message
|
||||||
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user