mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-16 10:54:39 +00:00
Compare commits
228 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 | ||
|
8a106bd16a |
70
CHANGELOG.md
70
CHANGELOG.md
@@ -2,6 +2,76 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [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
|
||||
|
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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
152
app/Console/Commands/CreateImport.php
Normal file
152
app/Console/Commands/CreateImport.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* CreateImport.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Artisan;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Console\Command;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class CreateImport
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class CreateImport extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Use this command to create a new import. Your user ID can be found on the /profile page.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:create-import {file} {configuration} {--user=1} {--type=csv} {--start}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// find the file
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
$configuration = $this->argument('configuration');
|
||||
$user = $userRepository->find(intval($this->option('user')));
|
||||
$cwd = getcwd();
|
||||
$type = strtolower($this->option('type'));
|
||||
|
||||
if (!$this->validArguments()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// try to parse configuration data:
|
||||
$configurationData = json_decode(file_get_contents($configuration));
|
||||
if (is_null($configurationData)) {
|
||||
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->info(sprintf('Going to create a job to import file: %s', $file));
|
||||
$this->info(sprintf('Using configuration file: %s', $configuration));
|
||||
$this->info(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
||||
$this->info(sprintf('Type of import: %s', $type));
|
||||
|
||||
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
|
||||
|
||||
$job = $jobRepository->create($type);
|
||||
$this->line(sprintf('Created job "%s"...', $job->key));
|
||||
|
||||
// put the file in the proper place:
|
||||
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
|
||||
$this->line('Stored import data...');
|
||||
|
||||
// store the configuration in the job:
|
||||
$job->configuration = $configurationData;
|
||||
$job->status = 'settings_complete';
|
||||
$job->save();
|
||||
$this->line('Stored configuration...');
|
||||
|
||||
// if user wants to run it, do!
|
||||
if ($this->option('start') === true) {
|
||||
$this->line('The import will start in a moment. This process is not visible...');
|
||||
Log::debug('Go for import!');
|
||||
Artisan::call('firefly:start-import', ['key' => $job->key]);
|
||||
$this->line('Done!');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function validArguments(): bool
|
||||
{
|
||||
// find the file
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
$configuration = $this->argument('configuration');
|
||||
$user = $userRepository->find(intval($this->option('user')));
|
||||
$cwd = getcwd();
|
||||
$validTypes = array_keys(config('firefly.import_formats'));
|
||||
$type = strtolower($this->option('type'));
|
||||
|
||||
if (is_null($user->id)) {
|
||||
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!in_array($type, $validTypes)) {
|
||||
$this->error(sprintf('Cannot import file of type "%s"', $type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($file)) {
|
||||
$this->error(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($configuration)) {
|
||||
$this->error(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
* EncryptFile.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Import.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -30,14 +32,14 @@ class Import extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Import stuff into Firefly III.';
|
||||
protected $description = 'This will start a new import.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:import {key}';
|
||||
protected $signature = 'firefly:start-import {key}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
@@ -55,9 +57,12 @@ class Import extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Log::debug('Start start-import command');
|
||||
$jobKey = $this->argument('key');
|
||||
$job = ImportJob::whereKey($jobKey)->first();
|
||||
if (!$this->isValid($job)) {
|
||||
Log::error('Job is not valid for some reason. Exit.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ScanAttachments.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
121
app/Console/Commands/UpgradeDatabase.php
Normal file
121
app/Console/Commands/UpgradeDatabase.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
* UpgradeDatabase.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class UpgradeDatabase
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class UpgradeDatabase extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Will run various commands to update database records.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:upgrade-database';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->setTransactionIdentifier();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird.
|
||||
*/
|
||||
private function setTransactionIdentifier()
|
||||
{
|
||||
$subQuery = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->groupBy(['transaction_journals.id'])
|
||||
->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]);
|
||||
|
||||
$result = DB::table(DB::raw('(' . $subQuery->toSql() . ') AS derived'))
|
||||
->mergeBindings($subQuery->getQuery())
|
||||
->where('t_count', '>', 2)
|
||||
->select(['id', 't_count']);
|
||||
$journalIds = array_unique($result->pluck('id')->toArray());
|
||||
|
||||
foreach ($journalIds as $journalId) {
|
||||
// grab all positive transactiosn from this journal that are not deleted.
|
||||
// for each one, grab the negative opposing one which has 0 as an identifier and give it the same identifier.
|
||||
$identifier = 0;
|
||||
$processed = [];
|
||||
$transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get();
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
// find opposing:
|
||||
$amount = bcmul(strval($transaction->amount), '-1');
|
||||
|
||||
try {
|
||||
/** @var Transaction $opposing */
|
||||
$opposing = Transaction
|
||||
::where('transaction_journal_id', $journalId)
|
||||
->where('amount', $amount)->where('identifier', '=', 0)
|
||||
->whereNotIn('id', $processed)
|
||||
->first();
|
||||
} catch (QueryException $e) {
|
||||
Log::error($e->getMessage());
|
||||
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
|
||||
$this->error('This field is required for Firefly III version ' . config('firefly.version') . ' to run.');
|
||||
$this->error('Please run "php artisan migrate" to add this field to the table.');
|
||||
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
|
||||
break 2;
|
||||
}
|
||||
if (!is_null($opposing)) {
|
||||
// give both a new identifier:
|
||||
$transaction->identifier = $identifier;
|
||||
$transaction->save();
|
||||
$opposing->identifier = $identifier;
|
||||
$opposing->save();
|
||||
$processed[] = $transaction->id;
|
||||
$processed[] = $opposing->id;
|
||||
$this->line(sprintf('Database upgrade for journal #%d, transactions #%d and #%d', $journalId, $transaction->id, $opposing->id));
|
||||
}
|
||||
$identifier++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
* UpgradeFireflyInstructions.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* VerifyDatabase.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -13,6 +15,7 @@ namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Tag;
|
||||
@@ -82,6 +85,9 @@ class VerifyDatabase extends Command
|
||||
|
||||
// transfers with budgets.
|
||||
$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;
|
||||
$this->error(
|
||||
'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called `accounts` and change the `deleted_at` field to: "' . $date . '"'
|
||||
' Find it in the table called "accounts" and change the "deleted_at" field to: "' . $date . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function reportIncorrectJournals()
|
||||
{
|
||||
$configuration = [
|
||||
// a withdrawal can not have revenue account:
|
||||
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
|
||||
|
||||
// deposit cannot have an expense account:
|
||||
TransactionType::DEPOSIT => [AccountType::EXPENSE],
|
||||
|
||||
// transfer cannot have either:
|
||||
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
||||
];
|
||||
foreach ($configuration as $transactionType => $accountTypes) {
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'account_types.id', 'accounts.account_type_id')
|
||||
->leftJoin('users', 'users.id', '=', 'transaction_journals.user_id')
|
||||
->where('transaction_types.type', $transactionType)
|
||||
->whereIn('account_types.type', $accountTypes)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->get(['transaction_journals.id', 'transaction_journals.user_id', 'users.email', 'account_types.type as a_type', 'transaction_types.type']);
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction journal #%d (user #%d, %s) is of type "%s" but ' .
|
||||
'is linked to a "%s". The transaction journal should be recreated.',
|
||||
$entry->id,
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->type,
|
||||
$entry->a_type
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Any deleted transaction journals that have transactions that are NOT deleted:
|
||||
*/
|
||||
@@ -222,7 +267,7 @@ class VerifyDatabase extends Command
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called `transactions` and change the `deleted_at` field to: "' . $entry->journal_deleted . '"'
|
||||
' Find it in the table called "transactions" and change the "deleted_at" field to: "' . $entry->journal_deleted . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -240,7 +285,7 @@ class VerifyDatabase extends Command
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table `transaction_journals` and delete the entry with id #' . $entry->id
|
||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table "transaction_journals" and delete the entry with id #' . $entry->id
|
||||
);
|
||||
}
|
||||
|
||||
@@ -301,7 +346,7 @@ class VerifyDatabase extends Command
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Transaction journal #' . $entry->journal_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called `transaction_journals` and change the `deleted_at` field to: "' . $entry->transaction_deleted . '"'
|
||||
' Find it in the table called "transaction_journals" and change the "deleted_at" field to: "' . $entry->transaction_deleted . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -3,17 +3,21 @@
|
||||
* Kernel.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use FireflyIII\Console\Commands\CreateImport;
|
||||
use FireflyIII\Console\Commands\EncryptFile;
|
||||
use FireflyIII\Console\Commands\Import;
|
||||
use FireflyIII\Console\Commands\ScanAttachments;
|
||||
use FireflyIII\Console\Commands\UpgradeDatabase;
|
||||
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
||||
use FireflyIII\Console\Commands\VerifyDatabase;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
@@ -55,8 +59,10 @@ class Kernel extends ConsoleKernel
|
||||
UpgradeFireflyInstructions::class,
|
||||
VerifyDatabase::class,
|
||||
Import::class,
|
||||
CreateImport::class,
|
||||
EncryptFile::class,
|
||||
ScanAttachments::class,
|
||||
UpgradeDatabase::class,
|
||||
|
||||
];
|
||||
|
||||
|
@@ -1,561 +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 $types
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveAccountsByType(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);
|
||||
}
|
||||
$query->where('active', 1);
|
||||
$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,116 +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 $types
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveAccountsByType(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
|
||||
/**
|
||||
* UserRegistration.php
|
||||
* ConfirmedUser.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserRegistration
|
||||
* Class ConfirmedUser
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserRegistration extends Event
|
||||
class ConfirmedUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
@@ -27,7 +29,7 @@ class UserRegistration extends Event
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
* Create a new event instance. This event is triggered when a user confirms their new account.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $ipAddress
|
@@ -3,8 +3,10 @@
|
||||
* Event.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* UserIsDeleted.php
|
||||
* RegisteredUser.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserIsDeleted
|
||||
* Class RegisteredUser
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserIsDeleted extends Event
|
||||
class RegisteredUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
@@ -27,7 +29,7 @@ class UserIsDeleted extends Event
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
* Create a new event instance. This event is triggered when a new user registers.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $ipAddress
|
@@ -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
|
||||
/**
|
||||
* UserIsConfirmed.php
|
||||
* ResentConfirmation.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserIsConfirmed
|
||||
* Class ResentConfirmation
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class UserIsConfirmed extends Event
|
||||
class ResentConfirmation extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
@@ -27,7 +29,7 @@ class UserIsConfirmed extends Event
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
* Create a new event instance. This event is triggered when a users wants a new confirmation.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $ipAddress
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitStored.php
|
||||
* StoredBudgetLimit.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitStored
|
||||
* Class StoredBudgetLimit
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class BudgetLimitStored extends Event
|
||||
class StoredBudgetLimit extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionJournalStored.php
|
||||
* StoredTransactionJournal.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalStored
|
||||
* Class StoredTransactionJournal
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionJournalStored extends Event
|
||||
class StoredTransactionJournal extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionStored.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalStored
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionStored extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $transaction = [];
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param array $transaction
|
||||
*/
|
||||
public function __construct(array $transaction)
|
||||
{
|
||||
//
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
|
||||
}
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitUpdated.php
|
||||
* UpdatedBudgetLimit.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -16,11 +18,11 @@ use FireflyIII\Models\BudgetLimit;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitUpdated
|
||||
* Class UpdatedBudgetLimit
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class BudgetLimitUpdated extends Event
|
||||
class UpdatedBudgetLimit extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionJournalUpdated.php
|
||||
* UpdatedTransactionJournal.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -15,11 +17,11 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalUpdated
|
||||
* Class UpdatedTransactionJournal
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionJournalUpdated extends Event
|
||||
class UpdatedTransactionJournal extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
@@ -3,8 +3,10 @@
|
||||
* FireflyException.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Handler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -106,7 +108,8 @@ class Handler extends ExceptionHandler
|
||||
/**
|
||||
* Convert an authentication exception into an unauthenticated response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function unauthenticated($request)
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* NotImplementedException.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ValidationException.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,19 +3,20 @@
|
||||
* AttachmentCollector.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use Amount;
|
||||
use Carbon\Carbon;
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -29,12 +30,14 @@ use Storage;
|
||||
*/
|
||||
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $explanationString = '';
|
||||
/** @var Carbon */
|
||||
private $end;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $exportDisk;
|
||||
/** @var AttachmentRepositoryInterface */
|
||||
private $repository;
|
||||
/** @var Carbon */
|
||||
private $start;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $uploadDisk;
|
||||
|
||||
@@ -67,34 +70,17 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
$this->exportAttachment($attachment);
|
||||
}
|
||||
|
||||
// put the explanation string in a file and attach it as well.
|
||||
$file = $this->job->key . '-Source of all your attachments explained.txt';
|
||||
$this->exportDisk->put($file, $this->explanationString);
|
||||
$this->getFiles()->push($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*/
|
||||
private function explain(Attachment $attachment)
|
||||
public function setDates(Carbon $start, Carbon $end)
|
||||
{
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $attachment->attachable;
|
||||
$args = [
|
||||
'attachment_name' => e($attachment->filename),
|
||||
'attachment_id' => $attachment->id,
|
||||
'type' => strtolower($journal->transactionType->type),
|
||||
'description' => e($journal->description),
|
||||
'journal_id' => $journal->id,
|
||||
'date' => $journal->date->formatLocalized(strval(trans('config.month_and_day'))),
|
||||
'amount' => Amount::formatJournal($journal, false),
|
||||
];
|
||||
$string = trans('firefly.attachment_explanation', $args) . "\n";
|
||||
Log::debug('Appended explanation string', ['string' => $string]);
|
||||
$this->explanationString .= $string;
|
||||
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,10 +96,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
||||
$exportFile = $this->exportFileName($attachment);
|
||||
$this->exportDisk->put($exportFile, $decrypted);
|
||||
$this->getFiles()->push($exportFile);
|
||||
$this->getEntries()->push($exportFile);
|
||||
|
||||
// explain:
|
||||
$this->explain($attachment);
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
||||
}
|
||||
@@ -141,7 +125,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
*/
|
||||
private function getAttachments(): Collection
|
||||
{
|
||||
$attachments = $this->repository->get();
|
||||
$attachments = $this->repository->getBetween($this->start, $this->end);
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BasicCollector.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -25,7 +27,7 @@ class BasicCollector
|
||||
/** @var ExportJob */
|
||||
protected $job;
|
||||
/** @var Collection */
|
||||
private $files;
|
||||
private $entries;
|
||||
|
||||
/**
|
||||
* BasicCollector constructor.
|
||||
@@ -34,24 +36,24 @@ class BasicCollector
|
||||
*/
|
||||
public function __construct(ExportJob $job)
|
||||
{
|
||||
$this->files = new Collection;
|
||||
$this->job = $job;
|
||||
$this->entries = new Collection;
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getFiles(): Collection
|
||||
public function getEntries(): Collection
|
||||
{
|
||||
return $this->files;
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $files
|
||||
* @param Collection $entries
|
||||
*/
|
||||
public function setFiles(Collection $files)
|
||||
public function setEntries(Collection $entries)
|
||||
{
|
||||
$this->files = $files;
|
||||
$this->entries = $entries;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* CollectorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -23,7 +25,7 @@ interface CollectorInterface
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getFiles(): Collection;
|
||||
public function getEntries(): Collection;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
@@ -31,9 +33,9 @@ interface CollectorInterface
|
||||
public function run(): bool;
|
||||
|
||||
/**
|
||||
* @param Collection $files
|
||||
* @param Collection $entries
|
||||
*
|
||||
*/
|
||||
public function setFiles(Collection $files);
|
||||
public function setEntries(Collection $entries);
|
||||
|
||||
}
|
||||
|
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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -24,16 +26,14 @@ use Storage;
|
||||
*/
|
||||
class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $expected;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $exportDisk;
|
||||
private $importKeys = [];
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $uploadDisk;
|
||||
/** @var string */
|
||||
private $vintageFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
* AttachmentCollector constructor.
|
||||
*
|
||||
* @param ExportJob $job
|
||||
@@ -49,50 +49,74 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
$this->exportDisk = Storage::disk('export');
|
||||
|
||||
// file names associated with the old import routine.
|
||||
$this->expected = 'csv-upload-' . auth()->user()->id . '-';
|
||||
$this->vintageFormat = sprintf('csv-upload-%d-', auth()->user()->id);
|
||||
|
||||
// for the new import routine:
|
||||
$this->getImportKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is called from the outside to actually start the export.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function run(): bool
|
||||
{
|
||||
// grab upload directory.
|
||||
$files = $this->uploadDisk->files();
|
||||
// collect old upload files (names beginning with "csv-upload".
|
||||
$this->collectVintageUploads();
|
||||
|
||||
foreach ($files as $entry) {
|
||||
$this->processUpload($entry);
|
||||
// then collect current upload files:
|
||||
$this->collectModernUploads();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method collects all the uploads that are uploaded using the new importer. So after the summer of 2016.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function collectModernUploads(): bool
|
||||
{
|
||||
$set = $this->job->user->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
||||
$keys = [];
|
||||
if ($set->count() > 0) {
|
||||
$keys = $set->pluck('key')->toArray();
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$this->processModernUpload($key);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method collects all the uploads that are uploaded using the "old" importer. So from before the summer of 2016.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function getImportKeys()
|
||||
private function collectVintageUploads():bool
|
||||
{
|
||||
$set = auth()->user()->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
||||
if ($set->count() > 0) {
|
||||
$keys = $set->pluck('key')->toArray();
|
||||
$this->importKeys = $keys;
|
||||
// grab upload directory.
|
||||
$files = $this->uploadDisk->files();
|
||||
|
||||
foreach ($files as $entry) {
|
||||
$this->processVintageUpload($entry);
|
||||
}
|
||||
Log::debug('Valid import keys are ', $this->importKeys);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tells you when the vintage upload file was actually uploaded.
|
||||
*
|
||||
* @param string $entry
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getOriginalUploadDate(string $entry): string
|
||||
private function getVintageUploadDate(string $entry): string
|
||||
{
|
||||
// this is an original upload.
|
||||
$parts = explode('-', str_replace(['.csv.encrypted', $this->expected], '', $entry));
|
||||
$parts = explode('-', str_replace(['.csv.encrypted', $this->vintageFormat], '', $entry));
|
||||
$originalUpload = intval($parts[1]);
|
||||
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
|
||||
|
||||
@@ -100,33 +124,17 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells you if a file name is a vintage upload.
|
||||
*
|
||||
* @param string $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isImportFile(string $entry): bool
|
||||
private function isVintageImport(string $entry): bool
|
||||
{
|
||||
$name = str_replace('.upload', '', $entry);
|
||||
if (in_array($name, $this->importKeys)) {
|
||||
Log::debug(sprintf('Import file "%s" is in array', $name), $this->importKeys);
|
||||
|
||||
return true;
|
||||
}
|
||||
Log::debug(sprintf('Import file "%s" is NOT in array', $name), $this->importKeys);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isOldImport(string $entry): bool
|
||||
{
|
||||
$len = strlen($this->expected);
|
||||
$len = strlen($this->vintageFormat);
|
||||
// file is part of the old import routine:
|
||||
if (substr($entry, 0, $len) === $this->expected) {
|
||||
if (substr($entry, 0, $len) === $this->vintageFormat) {
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -135,49 +143,62 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $entry
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function processUpload(string $entry)
|
||||
{
|
||||
// file is old import:
|
||||
if ($this->isOldImport($entry)) {
|
||||
$this->saveOldImportFile($entry);
|
||||
}
|
||||
|
||||
// file is current import.
|
||||
if ($this->isImportFile($entry)) {
|
||||
$this->saveImportFile($entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*/
|
||||
private function saveImportFile(string $entry)
|
||||
private function processModernUpload(string $key): bool
|
||||
{
|
||||
// find job associated with import file:
|
||||
$name = str_replace('.upload', '', $entry);
|
||||
$job = auth()->user()->importJobs()->where('key', $name)->first();
|
||||
$content = '';
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
$job = $this->job->user->importJobs()->where('key', $key)->first();
|
||||
if (is_null($job)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_null($job) && strlen($content) > 0) {
|
||||
// find the file for this import:
|
||||
$content = '';
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('%s.upload', $key)));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error(sprintf('Could not decrypt old import file "%s". Skipped because: %s', $key, $e->getMessage()));
|
||||
}
|
||||
|
||||
if (strlen($content) > 0) {
|
||||
// add to export disk.
|
||||
$date = $job->created_at->format('Y-m-d');
|
||||
$file = sprintf('%s-Old %s import dated %s.%s', $this->job->key, strtoupper($job->file_type), $date, $job->file_type);
|
||||
$this->exportDisk->put($file, $content);
|
||||
$this->getFiles()->push($file);
|
||||
$this->getEntries()->push($file);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the file is a vintage upload, process it.
|
||||
*
|
||||
* @param string $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function processVintageUpload(string $entry): bool
|
||||
{
|
||||
if ($this->isVintageImport($entry)) {
|
||||
$this->saveVintageImportFile($entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This will store the content of the old vintage upload somewhere.
|
||||
*
|
||||
* @param string $entry
|
||||
*/
|
||||
private function saveOldImportFile(string $entry)
|
||||
private function saveVintageImportFile(string $entry)
|
||||
{
|
||||
$content = '';
|
||||
try {
|
||||
@@ -188,10 +209,10 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
|
||||
if (strlen($content) > 0) {
|
||||
// add to export disk.
|
||||
$date = $this->getOriginalUploadDate($entry);
|
||||
$date = $this->getVintageUploadDate($entry);
|
||||
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
||||
$this->exportDisk->put($file, $content);
|
||||
$this->getFiles()->push($file);
|
||||
$this->getEntries()->push($file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Export\Entry;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use Crypt;
|
||||
|
||||
/**
|
||||
* To extend the exported object, in case of new features in Firefly III for example,
|
||||
@@ -33,98 +34,77 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
final class Entry
|
||||
{
|
||||
/** @var string */
|
||||
public $amount;
|
||||
/** @var EntryBill */
|
||||
public $bill;
|
||||
/** @var EntryBudget */
|
||||
public $budget;
|
||||
/** @var EntryCategory */
|
||||
public $category;
|
||||
/** @var string */
|
||||
// @formatter:off
|
||||
public $journal_id;
|
||||
public $date;
|
||||
/** @var string */
|
||||
public $description;
|
||||
/** @var EntryAccount */
|
||||
public $destinationAccount;
|
||||
/** @var Collection */
|
||||
public $destinationAccounts;
|
||||
/** @var EntryAccount */
|
||||
public $sourceAccount;
|
||||
/** @var Collection */
|
||||
public $sourceAccounts;
|
||||
|
||||
public $currency_code;
|
||||
public $amount;
|
||||
|
||||
public $transaction_type;
|
||||
|
||||
public $source_account_id;
|
||||
public $source_account_name;
|
||||
|
||||
public $destination_account_id;
|
||||
public $destination_account_name;
|
||||
|
||||
|
||||
public $budget_id;
|
||||
public $budget_name;
|
||||
public $category_id;
|
||||
public $category_name;
|
||||
// @formatter:on
|
||||
|
||||
/**
|
||||
* Entry constructor.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$this->sourceAccounts = new Collection;
|
||||
$this->destinationAccounts = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param $object
|
||||
*
|
||||
* @return Entry
|
||||
*/
|
||||
public static function fromJournal(TransactionJournal $journal)
|
||||
public static function fromObject($object): Entry
|
||||
{
|
||||
$entry = new self;
|
||||
|
||||
$entry = new self;
|
||||
$entry->description = $journal->description;
|
||||
$entry->date = $journal->date->format('Y-m-d');
|
||||
$entry->amount = TransactionJournal::amount($journal);
|
||||
// journal information:
|
||||
$entry->journal_id = $object->transaction_journal_id;
|
||||
$entry->description = $object->journal_encrypted === 1 ? Crypt::decrypt($object->journal_description) : $object->journal_description;
|
||||
$entry->amount = round($object->amount, 2); // always positive
|
||||
$entry->date = $object->date;
|
||||
$entry->transaction_type = $object->transaction_type;
|
||||
$entry->currency_code = $object->transaction_currency_code;
|
||||
|
||||
$entry->budget = new EntryBudget($journal->budgets->first());
|
||||
$entry->category = new EntryCategory($journal->categories->first());
|
||||
$entry->bill = new EntryBill($journal->bill);
|
||||
// source information:
|
||||
$entry->source_account_id = $object->account_id;
|
||||
$entry->source_account_name = $object->account_name_encrypted === 1 ? Crypt::decrypt($object->account_name) : $object->account_name;
|
||||
|
||||
$sources = TransactionJournal::sourceAccountList($journal);
|
||||
$destinations = TransactionJournal::destinationAccountList($journal);
|
||||
$entry->sourceAccount = new EntryAccount($sources->first());
|
||||
$entry->destinationAccount = new EntryAccount($destinations->first());
|
||||
|
||||
foreach ($sources as $source) {
|
||||
$entry->sourceAccounts->push(new EntryAccount($source));
|
||||
}
|
||||
// destination information
|
||||
$entry->destination_account_id = $object->opposing_account_id;
|
||||
$entry->destination_account_name = $object->opposing_account_encrypted === 1 ? Crypt::decrypt($object->opposing_account_name)
|
||||
: $object->opposing_account_name;
|
||||
|
||||
foreach ($destinations as $destination) {
|
||||
$entry->destinationAccounts->push(new EntryAccount($destination));
|
||||
|
||||
// category and budget
|
||||
$entry->category_id = $object->category_id ?? '';
|
||||
$entry->category_name = $object->category_name ?? '';
|
||||
$entry->budget_id = $object->budget_id ?? '';
|
||||
$entry->budget_name = $object->budget_name ?? '';
|
||||
|
||||
|
||||
// update description when transaction description is different:
|
||||
if (!is_null($object->description) && $object->description != $entry->description) {
|
||||
$entry->description = $entry->description . ' (' . $object->description . ')';
|
||||
}
|
||||
|
||||
return $entry;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getFieldsAndTypes(): array
|
||||
{
|
||||
// key = field name (see top of class)
|
||||
// value = field type (see csv.php under 'roles')
|
||||
return [
|
||||
'description' => 'description',
|
||||
'amount' => 'amount',
|
||||
'date' => 'date-transaction',
|
||||
'source_account_id' => 'account-id',
|
||||
'source_account_name' => 'account-name',
|
||||
'source_account_iban' => 'account-iban',
|
||||
'source_account_type' => '_ignore',
|
||||
'source_account_number' => 'account-number',
|
||||
'destination_account_id' => 'opposing-id',
|
||||
'destination_account_name' => 'opposing-name',
|
||||
'destination_account_iban' => 'opposing-iban',
|
||||
'destination_account_type' => '_ignore',
|
||||
'destination_account_number' => 'account-number',
|
||||
'budget_id' => 'budget-id',
|
||||
'budget_name' => 'budget-name',
|
||||
'category_id' => 'category-id',
|
||||
'category_name' => 'category-name',
|
||||
'bill_id' => 'bill-id',
|
||||
'bill_name' => 'bill-name',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* CsvExporter.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -14,7 +16,6 @@ namespace FireflyIII\Export\Exporter;
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use FireflyIII\Export\Entry\EntryAccount;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Csv\Writer;
|
||||
use SplFileObject;
|
||||
|
||||
@@ -60,110 +61,24 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
|
||||
$rows = [];
|
||||
|
||||
// Count the maximum number of sources and destinations each entry has. May need to expand the number of export fields:
|
||||
$maxSourceAccounts = 1;
|
||||
$maxDestAccounts = 1;
|
||||
/** @var Entry $entry */
|
||||
foreach ($this->getEntries() as $entry) {
|
||||
$sources = $entry->sourceAccounts->count();
|
||||
$destinations = $entry->destinationAccounts->count();
|
||||
$maxSourceAccounts = max($maxSourceAccounts, $sources);
|
||||
$maxDestAccounts = max($maxDestAccounts, $destinations);
|
||||
}
|
||||
$rows[] = array_keys($this->getFieldsAndTypes($maxSourceAccounts, $maxDestAccounts));
|
||||
// get field names for header row:
|
||||
$first = $this->getEntries()->first();
|
||||
$headers = array_keys(get_object_vars($first));
|
||||
$rows[] = $headers;
|
||||
|
||||
/** @var Entry $entry */
|
||||
foreach ($this->getEntries() as $entry) {
|
||||
// order is defined in Entry::getFieldsAndTypes.
|
||||
$current = [$entry->description, $entry->amount, $entry->date];
|
||||
$sourceData = $this->getAccountData($maxSourceAccounts, $entry->sourceAccounts);
|
||||
$current = array_merge($current, $sourceData);
|
||||
$destData = $this->getAccountData($maxDestAccounts, $entry->destinationAccounts);
|
||||
$current = array_merge($current, $destData);
|
||||
$rest = [$entry->budget->budgetId, $entry->budget->name, $entry->category->categoryId, $entry->category->name, $entry->bill->billId,
|
||||
$entry->bill->name];
|
||||
$current = array_merge($current, $rest);
|
||||
$rows[] = $current;
|
||||
$line = [];
|
||||
foreach ($headers as $header) {
|
||||
$line[] = $entry->$header;
|
||||
}
|
||||
$rows[] = $line;
|
||||
}
|
||||
$writer->insertAll($rows);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $max
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getAccountData(int $max, Collection $accounts): array
|
||||
{
|
||||
$current = [];
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
/** @var EntryAccount $source */
|
||||
$source = $accounts->get($i);
|
||||
$currentId = '';
|
||||
$currentName = '';
|
||||
$currentIban = '';
|
||||
$currentType = '';
|
||||
$currentNumber = '';
|
||||
if ($source) {
|
||||
$currentId = $source->accountId;
|
||||
$currentName = $source->name;
|
||||
$currentIban = $source->iban;
|
||||
$currentType = $source->type;
|
||||
$currentNumber = $source->number;
|
||||
}
|
||||
$current[] = $currentId;
|
||||
$current[] = $currentName;
|
||||
$current[] = $currentIban;
|
||||
$current[] = $currentType;
|
||||
$current[] = $currentNumber;
|
||||
}
|
||||
unset($source);
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $sources
|
||||
* @param int $destinations
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getFieldsAndTypes(int $sources, int $destinations): array
|
||||
{
|
||||
// key = field name (see top of class)
|
||||
// value = field type (see csv.php under 'roles')
|
||||
$array = [
|
||||
'description' => 'description',
|
||||
'amount' => 'amount',
|
||||
'date' => 'date-transaction',
|
||||
];
|
||||
for ($i = 0; $i < $sources; $i++) {
|
||||
$array['source_account_' . $i . '_id'] = 'account-id';
|
||||
$array['source_account_' . $i . '_name'] = 'account-name';
|
||||
$array['source_account_' . $i . '_iban'] = 'account-iban';
|
||||
$array['source_account_' . $i . '_type'] = '_ignore';
|
||||
$array['source_account_' . $i . '_number'] = 'account-number';
|
||||
}
|
||||
for ($i = 0; $i < $destinations; $i++) {
|
||||
$array['destination_account_' . $i . '_id'] = 'account-id';
|
||||
$array['destination_account_' . $i . '_name'] = 'account-name';
|
||||
$array['destination_account_' . $i . '_iban'] = 'account-iban';
|
||||
$array['destination_account_' . $i . '_type'] = '_ignore';
|
||||
$array['destination_account_' . $i . '_number'] = 'account-number';
|
||||
}
|
||||
|
||||
$array['budget_id'] = 'budget-id';
|
||||
$array['budget_name'] = 'budget-name';
|
||||
$array['category_id'] = 'category-id';
|
||||
$array['category_name'] = 'category-name';
|
||||
$array['bill_id'] = 'bill-id';
|
||||
$array['bill_name'] = 'bill-name';
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
private function tempFile()
|
||||
{
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ExporterInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Processor.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -13,13 +15,13 @@ namespace FireflyIII\Export;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Export\Collector\AttachmentCollector;
|
||||
use FireflyIII\Export\Collector\JournalCollector;
|
||||
use FireflyIII\Export\Collector\UploadCollector;
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Filesystem\FilesystemAdapter;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Storage;
|
||||
use ZipArchive;
|
||||
|
||||
@@ -38,8 +40,6 @@ class Processor
|
||||
/** @var bool */
|
||||
public $includeAttachments;
|
||||
/** @var bool */
|
||||
public $includeConfig;
|
||||
/** @var bool */
|
||||
public $includeOldUploads;
|
||||
/** @var ExportJob */
|
||||
public $job;
|
||||
@@ -66,7 +66,6 @@ class Processor
|
||||
$this->accounts = $settings['accounts'];
|
||||
$this->exportFormat = $settings['exportFormat'];
|
||||
$this->includeAttachments = $settings['includeAttachments'];
|
||||
$this->includeConfig = $settings['includeConfig'];
|
||||
$this->includeOldUploads = $settings['includeOldUploads'];
|
||||
$this->job = $settings['job'];
|
||||
$this->journals = new Collection;
|
||||
@@ -82,8 +81,9 @@ class Processor
|
||||
{
|
||||
/** @var AttachmentCollector $attachmentCollector */
|
||||
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
|
||||
$attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
|
||||
$attachmentCollector->run();
|
||||
$this->files = $this->files->merge($attachmentCollector->getFiles());
|
||||
$this->files = $this->files->merge($attachmentCollector->getEntries());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -93,9 +93,13 @@ class Processor
|
||||
*/
|
||||
public function collectJournals(): bool
|
||||
{
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$this->journals = $repository->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
|
||||
/** @var JournalCollector $collector */
|
||||
$collector = app(JournalCollector::class, [$this->job]);
|
||||
$collector->setDates($this->settings['startDate'], $this->settings['endDate']);
|
||||
$collector->setAccounts($this->settings['accounts']);
|
||||
$collector->run();
|
||||
$this->journals = $collector->getEntries();
|
||||
Log::debug(sprintf('Count %d journals in collectJournals() ', $this->journals->count()));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -109,7 +113,7 @@ class Processor
|
||||
$uploadCollector = app(UploadCollector::class, [$this->job]);
|
||||
$uploadCollector->run();
|
||||
|
||||
$this->files = $this->files->merge($uploadCollector->getFiles());
|
||||
$this->files = $this->files->merge($uploadCollector->getEntries());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -120,22 +124,11 @@ class Processor
|
||||
public function convertJournals(): bool
|
||||
{
|
||||
$count = 0;
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($this->journals as $journal) {
|
||||
$this->exportEntries->push(Entry::fromJournal($journal));
|
||||
foreach ($this->journals as $object) {
|
||||
$this->exportEntries->push(Entry::fromObject($object));
|
||||
$count++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function createConfigFile(): bool
|
||||
{
|
||||
$this->configurationMaker = app(ConfigurationFile::class, [$this->job]);
|
||||
$this->files->push($this->configurationMaker->make());
|
||||
Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* AccountChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -22,7 +24,6 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface AccountChartGeneratorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
@@ -41,6 +42,15 @@ interface AccountChartGeneratorInterface
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function revenueAccounts(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $labels
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsAccountChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -81,6 +83,30 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function revenueAccounts(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [], 'datasets' => [[
|
||||
'label' => trans('firefly.earned'),
|
||||
'data' => []]]];
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->difference > 0) {
|
||||
$data['labels'][] = $account->name;
|
||||
$data['datasets'][0]['data'][] = $account->difference;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $labels
|
||||
@@ -103,5 +129,4 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BillChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsBillChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsBudgetChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* CategoryChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsCategoryChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsPiggyBankChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* PiggyBankChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ChartJsReportChartGenerator.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ReportChartGeneratorInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AttachUserRole.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class AttachUserRole
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class AttachUserRole
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*/
|
||||
public function handle(UserRegistration $event)
|
||||
{
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
|
||||
// first user ever?
|
||||
if ($repository->count() == 1) {
|
||||
$repository->attachRole($event->user, 'owner');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,46 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitEventHandler.php
|
||||
* BudgetEventHandler.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\BudgetLimitStored;
|
||||
use FireflyIII\Events\BudgetLimitUpdated;
|
||||
|
||||
use FireflyIII\Events\StoredBudgetLimit;
|
||||
use FireflyIII\Events\UpdatedBudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitEventHandler
|
||||
* Handles budget related events.
|
||||
*
|
||||
* Class BudgetEventHandler
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class BudgetLimitEventHandler
|
||||
class BudgetEventHandler
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
* This method creates a new budget limit repetition when a new budget limit has been created.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In a perfect world, the store() routine should be different from the update()
|
||||
* routine. It would not have to check count() == 0 because there could be NO
|
||||
* limit repetitions at this point. However, the database can be wrong so we check.
|
||||
* @param StoredBudgetLimit $event
|
||||
*
|
||||
* @param BudgetLimitStored $event
|
||||
* @return bool
|
||||
*/
|
||||
public function store(BudgetLimitStored $event)
|
||||
public function storeRepetition(StoredBudgetLimit $event):bool
|
||||
{
|
||||
$budgetLimit = $event->budgetLimit;
|
||||
$end = $event->end;
|
||||
@@ -69,12 +65,18 @@ class BudgetLimitEventHandler
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param BudgetLimitUpdated $event
|
||||
* Updates, if present the budget limit repetition part of a budget limit.
|
||||
*
|
||||
* @param UpdatedBudgetLimit $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update(BudgetLimitUpdated $event)
|
||||
public function updateRepetition(UpdatedBudgetLimit $event): bool
|
||||
{
|
||||
$budgetLimit = $event->budgetLimit;
|
||||
$end = $event->end;
|
||||
@@ -102,6 +104,7 @@ class BudgetLimitEventHandler
|
||||
$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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* AttachmentHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Account.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Balance.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceEntry.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceHeader.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BalanceLine.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Bill.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BillLine.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Budget.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetLine.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Category.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,14 +3,15 @@
|
||||
* Expense.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
@@ -36,36 +37,11 @@ class Expense
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $entry
|
||||
* @param stdClass $entry
|
||||
*/
|
||||
public function addOrCreateExpense(TransactionJournal $entry)
|
||||
public function addOrCreateExpense(stdClass $entry)
|
||||
{
|
||||
// add each account individually:
|
||||
$destinations = TransactionJournal::destinationTransactionList($entry);
|
||||
|
||||
foreach ($destinations as $transaction) {
|
||||
$amount = strval($transaction->amount);
|
||||
$account = $transaction->account;
|
||||
if (bccomp('0', $amount) === -1) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
$object = new stdClass;
|
||||
$object->amount = $amount;
|
||||
$object->name = $account->name;
|
||||
$object->count = 1;
|
||||
$object->id = $account->id;
|
||||
|
||||
// overrule some properties:
|
||||
if ($this->expenses->has($account->id)) {
|
||||
$object = $this->expenses->get($account->id);
|
||||
$object->amount = bcadd($object->amount, $amount);
|
||||
$object->count++;
|
||||
}
|
||||
$this->expenses->put($account->id, $object);
|
||||
}
|
||||
|
||||
|
||||
$this->expenses->put($entry->id, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,14 +3,15 @@
|
||||
* Income.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
@@ -37,32 +38,11 @@ class Income
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $entry
|
||||
* @param stdClass $entry
|
||||
*/
|
||||
public function addOrCreateIncome(TransactionJournal $entry)
|
||||
public function addOrCreateIncome(stdClass $entry)
|
||||
{
|
||||
// add each account individually:
|
||||
$sources = TransactionJournal::sourceTransactionList($entry);
|
||||
|
||||
foreach ($sources as $transaction) {
|
||||
$amount = strval($transaction->amount);
|
||||
$account = $transaction->account;
|
||||
$amount = bcmul($amount, '-1');
|
||||
|
||||
$object = new stdClass;
|
||||
$object->amount = $amount;
|
||||
$object->name = $account->name;
|
||||
$object->count = 1;
|
||||
$object->id = $account->id;
|
||||
|
||||
// overrule some properties:
|
||||
if ($this->incomes->has($account->id)) {
|
||||
$object = $this->incomes->get($account->id);
|
||||
$object->amount = bcadd($object->amount, $amount);
|
||||
$object->count++;
|
||||
}
|
||||
$this->incomes->put($account->id, $object);
|
||||
}
|
||||
$this->incomes->put($entry->id, $entry);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* FiscalHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* FiscalHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* Help.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -24,47 +26,39 @@ class Help implements HelpInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $route
|
||||
* @param string $language
|
||||
*
|
||||
* @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 $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);
|
||||
$routeIndex = str_replace('.', '-', $route);
|
||||
$title = trans('help.' . $routeIndex);
|
||||
$content = [
|
||||
'text' => '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>',
|
||||
'title' => $title,
|
||||
];
|
||||
|
||||
|
||||
$result = Requests::get($uri);
|
||||
|
||||
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
|
||||
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||
$result = Requests::get($uri);
|
||||
|
||||
if ($result->status_code === 200) {
|
||||
$content['text'] = $result->body;
|
||||
$content = $result->body;
|
||||
}
|
||||
|
||||
|
||||
if (strlen(trim($content['text'])) == 0) {
|
||||
$content['text'] = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||
if (strlen(trim($content)) == 0) {
|
||||
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||
}
|
||||
$converter = new CommonMarkConverter();
|
||||
$content['text'] = $converter->convertToHtml($content['text']);
|
||||
$converter = new CommonMarkConverter();
|
||||
$content = $converter->convertToHtml($content);
|
||||
|
||||
return $content;
|
||||
|
||||
@@ -82,27 +76,26 @@ class Help implements HelpInterface
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $route
|
||||
* @param string $language
|
||||
*
|
||||
* @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 $language
|
||||
* @param array $content
|
||||
* @param string $content
|
||||
*
|
||||
* @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 . '.title.' . $language, $content['title'], 10080);
|
||||
Cache::put('help.' . $route . '.' . $language, $content, 10080); // a week.
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* HelpInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -19,19 +21,20 @@ interface HelpInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $route
|
||||
* @param string $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFromCache(string $key): string;
|
||||
public function getFromCache(string $route, string $language): string;
|
||||
|
||||
/**
|
||||
* @param string $language
|
||||
* @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
|
||||
@@ -42,15 +45,16 @@ interface HelpInterface
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string $language
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function inCache(string $route): bool;
|
||||
public function inCache(string $route, string $language ): bool;
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -126,7 +128,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
->get(
|
||||
[
|
||||
'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
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetReportHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* BudgetReportHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ReportHelper.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -22,7 +24,7 @@ use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
@@ -30,6 +32,7 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class ReportHelper
|
||||
@@ -99,7 +102,8 @@ class ReportHelper implements ReportHelperInterface
|
||||
$billLine->setHit(true);
|
||||
}
|
||||
|
||||
if ($billLine->isActive()) {
|
||||
// non active AND non hit? do not add:
|
||||
if ($billLine->isActive() || $billLine->isHit()) {
|
||||
$collection->addBill($billLine);
|
||||
}
|
||||
}
|
||||
@@ -144,14 +148,14 @@ class ReportHelper implements ReportHelperInterface
|
||||
public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): Expense
|
||||
{
|
||||
$object = new Expense;
|
||||
/** @var AccountRepositoryInterface $repos */
|
||||
$repos = app(AccountRepositoryInterface::class);
|
||||
$journals = $repos->expensesInPeriod($accounts, $start, $end);
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($journals as $entry) {
|
||||
$amount = TransactionJournal::amount($entry);
|
||||
$object->addToTotal($amount);
|
||||
/** @var AccountTaskerInterface $tasker */
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
$collection = $tasker->expenseReport($accounts, $accounts, $start, $end);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($collection as $entry) {
|
||||
$object->addToTotal($entry->amount);
|
||||
$object->addOrCreateExpense($entry);
|
||||
}
|
||||
|
||||
@@ -170,13 +174,13 @@ class ReportHelper implements ReportHelperInterface
|
||||
public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): Income
|
||||
{
|
||||
$object = new Income;
|
||||
/** @var AccountRepositoryInterface $repos */
|
||||
$repos = app(AccountRepositoryInterface::class);
|
||||
$journals = $repos->incomesInPeriod($accounts, $start, $end);
|
||||
/** @var AccountTaskerInterface $tasker */
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
$collection = $tasker->incomeReport($accounts, $accounts, $start, $end);
|
||||
|
||||
foreach ($journals as $entry) {
|
||||
$amount = TransactionJournal::amount($entry);
|
||||
$object->addToTotal($amount);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($collection as $entry) {
|
||||
$object->addToTotal($entry->amount);
|
||||
$object->addOrCreateIncome($entry);
|
||||
}
|
||||
|
||||
@@ -255,9 +259,19 @@ class ReportHelper implements ReportHelperInterface
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where(
|
||||
function (Builder $q) use ($ids) {
|
||||
$q->whereIn('source.account_id', $ids)
|
||||
->whereIn('destination.account_id', $ids, 'xor');
|
||||
// source.account_id in accountIds XOR destination.account_id in accountIds
|
||||
function (Builder $query) use ($ids) {
|
||||
$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']);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ReportHelperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* AccountController.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
@@ -13,11 +15,13 @@ namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Requests\AccountFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -42,8 +46,16 @@ class AccountController extends Controller
|
||||
public function __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 Account $account
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(AccountCrudInterface $crud, Account $account)
|
||||
public function delete(ARI $repository, Account $account)
|
||||
{
|
||||
$typeName = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$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]);
|
||||
|
||||
// put previous url in session
|
||||
@@ -91,19 +103,19 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param Account $account
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @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;
|
||||
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
||||
$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])));
|
||||
Preferences::mark();
|
||||
@@ -112,18 +124,16 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function edit(ARI $repository, Account $account)
|
||||
public function edit(Account $account)
|
||||
{
|
||||
|
||||
$what = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$openingBalance = $repository->openingBalanceTransaction($account);
|
||||
$what = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (session('accounts.edit.fromUpdate') !== true) {
|
||||
@@ -134,21 +144,19 @@ class AccountController extends Controller
|
||||
// pre fill some useful values.
|
||||
|
||||
// the opening balance is tricky:
|
||||
$openingBalanceAmount = null;
|
||||
|
||||
if ($openingBalance->id) {
|
||||
$transaction = $repository->getFirstTransaction($openingBalance, $account);
|
||||
$openingBalanceAmount = $transaction->amount;
|
||||
}
|
||||
$openingBalanceAmount = $account->getOpeningBalanceAmount();
|
||||
$openingBalanceAmount = $account->getOpeningBalanceAmount() === '0' ? '' : $openingBalanceAmount;
|
||||
$openingBalanceDate = $account->getOpeningBalanceDate();
|
||||
$openingBalanceDate = $openingBalanceDate->year === 1900 ? null : $openingBalanceDate->format('Y-m-d');
|
||||
|
||||
$preFilled = [
|
||||
'accountNumber' => $account->getMeta('accountNumber'),
|
||||
'accountRole' => $account->getMeta('accountRole'),
|
||||
'ccType' => $account->getMeta('ccType'),
|
||||
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
||||
'openingBalanceDate' => $openingBalance->id ? $openingBalance->date->format('Y-m-d') : null,
|
||||
'openingBalanceDate' => $openingBalanceDate,
|
||||
'openingBalance' => $openingBalanceAmount,
|
||||
'virtualBalance' => round($account->virtual_balance, 2),
|
||||
'virtualBalance' => $account->virtual_balance,
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
Session::flash('gaEventCategory', 'accounts');
|
||||
@@ -158,19 +166,19 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param string $what
|
||||
* @param ARI $repository
|
||||
* @param string $what
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(AccountCrudInterface $crud, string $what)
|
||||
public function index(ARI $repository, string $what)
|
||||
{
|
||||
$what = $what ?? 'asset';
|
||||
|
||||
$subTitle = trans('firefly.' . $what . '_accounts');
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
||||
$accounts = $crud->getAccountsByType($types);
|
||||
$accounts = $repository->getAccountsByType($types);
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
@@ -194,13 +202,17 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
* @param AccountTaskerInterface $tasker
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @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:
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$subTitle = $account->name;
|
||||
@@ -212,7 +224,7 @@ class AccountController extends Controller
|
||||
$page = intval(Input::get('page'));
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
$count = $set->count();
|
||||
$subSet = $set->splice($offset, $pageSize);
|
||||
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
||||
@@ -220,10 +232,7 @@ class AccountController extends Controller
|
||||
|
||||
// grouped other months thing:
|
||||
// oldest transaction in account:
|
||||
$start = $repository->firstUseDate($account);
|
||||
if ($start->year == 1900) {
|
||||
$start = new Carbon;
|
||||
}
|
||||
$start = $repository->oldestJournalDate($account);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $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'));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$spent = $this->spentInPeriod($account, $end, $currentEnd);
|
||||
$earned = $this->earnedInPeriod($account, $end, $currentEnd);
|
||||
$spent = $tasker->amountOutInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$earned = $tasker->amountInInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
||||
@@ -260,13 +275,13 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
* @param string $date
|
||||
* @param AccountTaskerInterface $tasker
|
||||
* @param Account $account
|
||||
* @param string $date
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function showWithDate(ARI $repository, Account $account, string $date)
|
||||
public function showWithDate(AccountTaskerInterface $tasker, Account $account, string $date)
|
||||
{
|
||||
$carbon = new Carbon($date);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
@@ -277,7 +292,7 @@ class AccountController extends Controller
|
||||
$page = $page === 0 ? 1 : $page;
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
$set = $repository->journalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end);
|
||||
$count = $set->count();
|
||||
$subSet = $set->splice($offset, $pageSize);
|
||||
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
|
||||
@@ -287,30 +302,16 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountFormRequest $request
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param AccountFormRequest $request
|
||||
* @param ARI $repository
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
*/
|
||||
public function store(AccountFormRequest $request, AccountCrudInterface $crud)
|
||||
public function store(AccountFormRequest $request, ARI $repository)
|
||||
{
|
||||
$accountData = [
|
||||
'name' => trim($request->input('name')),
|
||||
'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' => trim($request->input('iban')),
|
||||
'accountNumber' => trim($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);
|
||||
$data = $request->getAccountData();
|
||||
$account = $repository->store($data);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.stored_new_account', ['name' => $account->name])));
|
||||
Preferences::mark();
|
||||
@@ -334,30 +335,16 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountFormRequest $request
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param Account $account
|
||||
* @param AccountFormRequest $request
|
||||
* @param ARI $repository
|
||||
* @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)
|
||||
{
|
||||
|
||||
$accountData = [
|
||||
'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);
|
||||
$data = $request->getAccountData();
|
||||
$repository->update($account, $data);
|
||||
|
||||
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
||||
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 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 */
|
||||
$repository = app(ARI::class);
|
||||
$collection = new Collection([$account]);
|
||||
$type = $account->accountType->type;
|
||||
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';
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $account->transactions()->first();
|
||||
if (is_null($transaction)) {
|
||||
throw new FireflyException('Expected a transaction. This account has none. BEEP, error.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asset accounts actually spend money by being the source of a withdrawal or the source
|
||||
* of a transfer. The money moves away from them.
|
||||
*
|
||||
* An expense account doesn't really spend money itself. Money is spent "at" the expense account.
|
||||
* So, the call to find out how many money has been spent on/at an expense account is slightly different.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @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';
|
||||
$journal = $transaction->transactionJournal;
|
||||
/** @var Transaction $opposingTransaction */
|
||||
$opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first();
|
||||
|
||||
if (is_null($opposingTransaction)) {
|
||||
throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.');
|
||||
}
|
||||
}
|
||||
|
||||
return redirect(route('accounts.show', [$opposingTransaction->account_id]));
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,10 @@
|
||||
* ConfigurationController.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
* 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);
|
||||
@@ -35,8 +37,15 @@ class ConfigurationController extends Controller
|
||||
{
|
||||
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
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(ConfigurationRequest $request)
|
||||
{
|
||||
// get config values:
|
||||
$singleUserMode = intval($request->get('single_user_mode')) === 1 ? true : false;
|
||||
$data = $request->getConfigurationData();
|
||||
|
||||
// store config values
|
||||
FireflyConfig::set('single_user_mode', $singleUserMode);
|
||||
FireflyConfig::set('single_user_mode', $data['single_user_mode']);
|
||||
|
||||
// flash message
|
||||
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