mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.3.1'
This commit is contained in:
commit
600c3e75bb
@ -40,6 +40,7 @@ SHOW_INCOMPLETE_TRANSLATIONS=false
|
|||||||
|
|
||||||
CACHE_PREFIX=firefly
|
CACHE_PREFIX=firefly
|
||||||
|
|
||||||
|
GOOGLE_MAPS_API_KEY=
|
||||||
ANALYTICS_ID=
|
ANALYTICS_ID=
|
||||||
SITE_OWNER=mail@example.com
|
SITE_OWNER=mail@example.com
|
||||||
|
|
||||||
@ -49,3 +50,4 @@ PUSHER_APP_ID=
|
|||||||
|
|
||||||
DEMO_USERNAME=
|
DEMO_USERNAME=
|
||||||
DEMO_PASSWORD=
|
DEMO_PASSWORD=
|
||||||
|
|
||||||
|
1
.github/CONTRIBUTING
vendored
Normal file
1
.github/CONTRIBUTING
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.github.io/requested-features/) first. Thanks!
|
@ -2,7 +2,50 @@
|
|||||||
tools:
|
tools:
|
||||||
external_code_coverage: false
|
external_code_coverage: false
|
||||||
filter:
|
filter:
|
||||||
|
paths:
|
||||||
|
- app/*
|
||||||
|
- public/js/ff/*
|
||||||
excluded_paths:
|
excluded_paths:
|
||||||
- app/Support/Migration/*
|
- "database/migrations/*"
|
||||||
- app/database/migrations/*
|
- "bootstrap/*"
|
||||||
- database/migrations/*
|
- "config/*"
|
||||||
|
- "docker/*"
|
||||||
|
- "public/js/lib/*"
|
||||||
|
- "public/lib/adminlte/js/*"
|
||||||
|
- "public/lib/bootstrap/js/*"
|
||||||
|
- "resources/*"
|
||||||
|
- "routes/*"
|
||||||
|
- "storage/*"
|
||||||
|
checks:
|
||||||
|
php:
|
||||||
|
use_self_instead_of_fqcn: true
|
||||||
|
uppercase_constants: true
|
||||||
|
return_doc_comments: true
|
||||||
|
return_doc_comment_if_not_inferrable: true
|
||||||
|
remove_extra_empty_lines: true
|
||||||
|
parameter_doc_comments: true
|
||||||
|
optional_parameters_at_the_end: true
|
||||||
|
no_short_variable_names:
|
||||||
|
minimum: '3'
|
||||||
|
no_short_method_names:
|
||||||
|
minimum: '3'
|
||||||
|
no_long_variable_names:
|
||||||
|
maximum: '20'
|
||||||
|
no_goto: true
|
||||||
|
newline_at_end_of_file: true
|
||||||
|
encourage_single_quotes: true
|
||||||
|
avoid_todo_comments: true
|
||||||
|
avoid_perl_style_comments: true
|
||||||
|
avoid_fixme_comments: true
|
||||||
|
avoid_multiple_statements_on_same_line: true
|
||||||
|
align_assignments: true
|
||||||
|
duplication: false
|
||||||
|
javascript: true
|
||||||
|
|
||||||
|
coding_style:
|
||||||
|
php:
|
||||||
|
spaces:
|
||||||
|
around_operators:
|
||||||
|
concatenation: true
|
||||||
|
other:
|
||||||
|
after_type_cast: false
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file.
|
|||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
## [4.3.1] - 2017-01-04
|
||||||
|
### Added
|
||||||
|
- Support for Russian and Polish.
|
||||||
|
- Support for a proper demo website.
|
||||||
|
- Support for custom decimal places in currencies (#506, suggested by @xpfgsyb).
|
||||||
|
- Most amounts are now right-aligned (#511, suggested by @xpfgsyb).
|
||||||
|
- German is now a "complete" language, more than 75% translated!
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **[New Github repository!](github.com/firefly-iii/firefly-iii)**
|
||||||
|
- Better category overview.
|
||||||
|
- #502, thanks to @zjean
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed a lot of administration functions.
|
||||||
|
- Removed ability to activate users.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- #501, thanks to @zjean
|
||||||
|
- #513, thanks to @skibbipl
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- #519, thanks to @xpfgsyb
|
||||||
|
|
||||||
## [4.3.0] - 2015-12-26
|
## [4.3.0] - 2015-12-26
|
||||||
### Added
|
### Added
|
||||||
- New method of keeping track of available budget, see issue #489
|
- New method of keeping track of available budget, see issue #489
|
||||||
@ -279,7 +303,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Bug in the mass edit routines.
|
- Bug in the mass edit routines.
|
||||||
- Firefly III over a proxy will now work (see [issue #290](https://github.com/JC5/firefly-iii/issues/290)), thanks @dfiel for reporting.
|
- Firefly III over a proxy will now work (see [issue #290](https://github.com/firefly-iii/firefly-iii/issues/290)), thanks @dfiel for reporting.
|
||||||
- Sneaky bug in the import routine, fixed by @Bonno
|
- Sneaky bug in the import routine, fixed by @Bonno
|
||||||
|
|
||||||
## [3.10.1] - 2016-08-25
|
## [3.10.1] - 2016-08-25
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
# Firefly III: A personal finances manager
|
# Firefly III: A personal finances manager
|
||||||
|
|
||||||
[](https://secure.php.net/downloads.php#v7.0.4) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
|
[](https://secure.php.net/downloads.php#v7.0.4) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://scrutinizer-ci.com/g/firefly-iii/firefly-iii/?branch=master) [](https://travis-ci.org/firefly-iii/firefly-iii) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
|
||||||
|
|
||||||
[](https://travis-ci.org/JC5/firefly-iii) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
|
|
||||||
|
|
||||||
[](https://i.nder.be/h2b37243) [](https://i.nder.be/hv70pbwc)
|
[](https://i.nder.be/h2b37243) [](https://i.nder.be/hv70pbwc)
|
||||||
|
|
||||||
[](https://i.nder.be/ccn0u2mp) [](https://i.nder.be/gm8hbh7z)
|
[](https://i.nder.be/ccn0u2mp) [](https://i.nder.be/gm8hbh7z)
|
||||||
|
|
||||||
_(You can click on the images for a better view)_
|
|
||||||
|
|
||||||
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
|
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
|
||||||
|
|
||||||
## Try it out!
|
## Try it out!
|
||||||
|
@ -15,6 +15,8 @@ namespace FireflyIII\Console\Commands;
|
|||||||
|
|
||||||
|
|
||||||
use DB;
|
use DB;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Models\LimitRepetition;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
@ -57,8 +59,29 @@ class UpgradeDatabase extends Command
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->setTransactionIdentifier();
|
$this->setTransactionIdentifier();
|
||||||
|
$this->migrateRepetitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function migrateRepetitions()
|
||||||
|
{
|
||||||
|
if (!Schema::hasTable('budget_limits')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get all budget limits with end_date NULL
|
||||||
|
$set = BudgetLimit::whereNull('end_date')->get();
|
||||||
|
$this->line(sprintf('Found %d budget limit(s) to update', $set->count()));
|
||||||
|
/** @var BudgetLimit $budgetLimit */
|
||||||
|
foreach ($set as $budgetLimit) {
|
||||||
|
// get limit repetition (should be just one):
|
||||||
|
/** @var LimitRepetition $repetition */
|
||||||
|
$repetition = $budgetLimit->limitrepetitions()->first();
|
||||||
|
if (!is_null($repetition)) {
|
||||||
|
$budgetLimit->end_date = $repetition->enddate;
|
||||||
|
$budgetLimit->save();
|
||||||
|
$this->line(sprintf('Updated budget limit #%d', $budgetLimit->id));
|
||||||
|
$repetition->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,8 +108,18 @@ class UpgradeDatabase extends Command
|
|||||||
$journalIds = array_unique($result->pluck('id')->toArray());
|
$journalIds = array_unique($result->pluck('id')->toArray());
|
||||||
|
|
||||||
foreach ($journalIds as $journalId) {
|
foreach ($journalIds as $journalId) {
|
||||||
// grab all positive transactiosn from this journal that are not deleted.
|
$this->updateJournal(intval($journalId));
|
||||||
// for each one, grab the negative opposing one which has 0 as an identifier and give it the same identifier.
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param int $journalId
|
||||||
|
*/
|
||||||
|
private function updateJournal(int $journalId)
|
||||||
|
{
|
||||||
$identifier = 0;
|
$identifier = 0;
|
||||||
$processed = [];
|
$processed = [];
|
||||||
$transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get();
|
$transactions = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->get();
|
||||||
@ -107,7 +140,8 @@ class UpgradeDatabase extends Command
|
|||||||
$this->error(sprintf('This field is required for Firefly III version %s to run.', config('firefly.version')));
|
$this->error(sprintf('This field is required for Firefly III version %s to run.', config('firefly.version')));
|
||||||
$this->error('Please run "php artisan migrate" to add this field to the table.');
|
$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.');
|
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
|
||||||
break 2;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!is_null($opposing)) {
|
if (!is_null($opposing)) {
|
||||||
// give both a new identifier:
|
// give both a new identifier:
|
||||||
@ -123,4 +157,3 @@ class UpgradeDatabase extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -63,19 +63,20 @@ class UpgradeFireflyInstructions extends Command
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (is_null($text)) {
|
if (is_null($text)) {
|
||||||
$this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
|
$this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
|
||||||
$this->info('There are no extra upgrade instructions.');
|
$this->info('There are no extra upgrade instructions.');
|
||||||
$this->line('Firefly III should be ready for use.');
|
$this->line('Firefly III should be ready for use.');
|
||||||
} else {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->line('+------------------------------------------------------------------------------+');
|
$this->line('+------------------------------------------------------------------------------+');
|
||||||
$this->line('');
|
$this->line('');
|
||||||
$this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
|
$this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
|
||||||
$this->info(wordwrap($text));
|
$this->info(wordwrap($text));
|
||||||
$this->line('');
|
$this->line('');
|
||||||
$this->line('+------------------------------------------------------------------------------+');
|
$this->line('+------------------------------------------------------------------------------+');
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -130,10 +130,9 @@ class VerifyDatabase extends Command
|
|||||||
|
|
||||||
/** @var Budget $entry */
|
/** @var Budget $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$name = $entry->encrypted ? Crypt::decrypt($entry->name) : $entry->name;
|
|
||||||
$line = sprintf(
|
$line = sprintf(
|
||||||
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
||||||
$entry->user_id, $entry->email, $entry->id, $name
|
$entry->user_id, $entry->email, $entry->id, $entry->name
|
||||||
);
|
);
|
||||||
$this->line($line);
|
$this->line($line);
|
||||||
}
|
}
|
||||||
@ -174,10 +173,8 @@ class VerifyDatabase extends Command
|
|||||||
$configuration = [
|
$configuration = [
|
||||||
// a withdrawal can not have revenue account:
|
// a withdrawal can not have revenue account:
|
||||||
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
|
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
|
||||||
|
|
||||||
// deposit cannot have an expense account:
|
// deposit cannot have an expense account:
|
||||||
TransactionType::DEPOSIT => [AccountType::EXPENSE],
|
TransactionType::DEPOSIT => [AccountType::EXPENSE],
|
||||||
|
|
||||||
// transfer cannot have either:
|
// transfer cannot have either:
|
||||||
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
||||||
];
|
];
|
||||||
|
@ -21,7 +21,6 @@ use FireflyIII\Console\Commands\ScanAttachments;
|
|||||||
use FireflyIII\Console\Commands\UpgradeDatabase;
|
use FireflyIII\Console\Commands\UpgradeDatabase;
|
||||||
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
|
||||||
use FireflyIII\Console\Commands\VerifyDatabase;
|
use FireflyIII\Console\Commands\VerifyDatabase;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,15 +75,4 @@ class Kernel extends ConsoleKernel
|
|||||||
{
|
{
|
||||||
require base_path('routes/console.php');
|
require base_path('routes/console.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the application's command schedule.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function schedule(Schedule $schedule)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BlockedBadLogin.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\Events;
|
|
||||||
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class LockedOutUser
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class BlockedBadLogin extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $email;
|
|
||||||
public $ipAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a user gets themselves locked out.
|
|
||||||
*
|
|
||||||
* @param string $email
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(string $email, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BlockedUseOfDomain.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\Events;
|
|
||||||
|
|
||||||
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class BlockedUseOfDomain
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class BlockedUseOfDomain extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $email;
|
|
||||||
public $ipAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a user tries to register with a banned domain (on blocked domain list).
|
|
||||||
*
|
|
||||||
* @param string $email
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(string $email, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BlockedUseOfEmail.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\Events;
|
|
||||||
|
|
||||||
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class BlockedUseOfEmail
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class BlockedUseOfEmail extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $email;
|
|
||||||
public $ipAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a user tries to register with a banned email address (already used before).
|
|
||||||
*
|
|
||||||
* @param string $email
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(string $email, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BlockedUserLogin.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\Events;
|
|
||||||
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class BlockedUserLogin
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class BlockedUserLogin extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $ipAddress;
|
|
||||||
public $user;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a blocked user logs in.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(User $user, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ConfirmedUser.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\Events;
|
|
||||||
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConfirmedUser
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class ConfirmedUser extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $ipAddress;
|
|
||||||
public $user;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a user confirms their new account.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(User $user, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* DeletedUser.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\Events;
|
|
||||||
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class DeletedUser
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class DeletedUser extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $email;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a user deletes themselves.
|
|
||||||
*
|
|
||||||
* @param string $email
|
|
||||||
*/
|
|
||||||
public function __construct(string $email)
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* LockedOutUser.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\Events;
|
|
||||||
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class LockedOutUser
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class LockedOutUser extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $email;
|
|
||||||
public $ipAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a user gets themselves locked out.
|
|
||||||
*
|
|
||||||
* @param string $email
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(string $email, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ResentConfirmation.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\Events;
|
|
||||||
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ResentConfirmation
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class ResentConfirmation extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public $ipAddress;
|
|
||||||
public $user;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new event instance. This event is triggered when a users wants a new confirmation.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @param string $ipAddress
|
|
||||||
*/
|
|
||||||
public function __construct(User $user, string $ipAddress)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* StoredBudgetLimit.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\Events;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class StoredBudgetLimit
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class StoredBudgetLimit extends Event
|
|
||||||
{
|
|
||||||
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
/** @var BudgetLimit */
|
|
||||||
public $budgetLimit;
|
|
||||||
|
|
||||||
/** @var Carbon */
|
|
||||||
public $end; // the only variable we can't get from the budget limit (if necessary).
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BudgetLimitEvents constructor.
|
|
||||||
*
|
|
||||||
* @param BudgetLimit $budgetLimit
|
|
||||||
* @param Carbon $end
|
|
||||||
*/
|
|
||||||
public function __construct(BudgetLimit $budgetLimit, Carbon $end)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
$this->budgetLimit = $budgetLimit;
|
|
||||||
$this->end = $end;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* UpdatedBudgetLimit.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\Events;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UpdatedBudgetLimit
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Events
|
|
||||||
*/
|
|
||||||
class UpdatedBudgetLimit extends Event
|
|
||||||
{
|
|
||||||
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
/** @var BudgetLimit */
|
|
||||||
public $budgetLimit;
|
|
||||||
|
|
||||||
/** @var Carbon */
|
|
||||||
public $end; // the only variable we can't get from the budget limit (if necessary).
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BudgetLimitEvents constructor.
|
|
||||||
*
|
|
||||||
* @param BudgetLimit $budgetLimit
|
|
||||||
* @param Carbon $end
|
|
||||||
*/
|
|
||||||
public function __construct(BudgetLimit $budgetLimit, Carbon $end)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
$this->budgetLimit = $budgetLimit;
|
|
||||||
$this->end = $end;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -21,6 +21,7 @@ use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|||||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
use Illuminate\Session\TokenMismatchException;
|
use Illuminate\Session\TokenMismatchException;
|
||||||
use Illuminate\Validation\ValidationException as ValException;
|
use Illuminate\Validation\ValidationException as ValException;
|
||||||
|
use Request;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,6 +73,7 @@ class Handler extends ExceptionHandler
|
|||||||
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
|
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
|
||||||
*
|
*
|
||||||
* @param Exception $exception
|
* @param Exception $exception
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@ -98,8 +100,8 @@ class Handler extends ExceptionHandler
|
|||||||
];
|
];
|
||||||
|
|
||||||
// create job that will mail.
|
// create job that will mail.
|
||||||
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
$ipAddress = Request::ip() ?? '0.0.0.0';
|
||||||
$job = new MailError($userData, env('SITE_OWNER', ''), $ip, $data);
|
$job = new MailError($userData, env('SITE_OWNER', ''), $ipAddress, $data);
|
||||||
dispatch($job);
|
dispatch($job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ interface CollectorInterface
|
|||||||
/**
|
/**
|
||||||
* @param Collection $entries
|
* @param Collection $entries
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function setEntries(Collection $entries);
|
public function setEntries(Collection $entries);
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ class JournalExportCollector extends BasicCollector implements CollectorInterfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||||
*/
|
*/
|
||||||
private function getWorkSet()
|
private function getWorkSet()
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,7 @@ use Crypt;
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Class Entry
|
* Class Entry
|
||||||
|
* @SuppressWarnings(PHPMD.LongVariable)
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Export\Entry
|
* @package FireflyIII\Export\Entry
|
||||||
*/
|
*/
|
||||||
@ -72,33 +73,21 @@ final class Entry
|
|||||||
public static function fromObject($object): Entry
|
public static function fromObject($object): Entry
|
||||||
{
|
{
|
||||||
$entry = new self;
|
$entry = new self;
|
||||||
|
|
||||||
// journal information:
|
|
||||||
$entry->journal_id = $object->transaction_journal_id;
|
$entry->journal_id = $object->transaction_journal_id;
|
||||||
$entry->description = $object->journal_encrypted === 1 ? Crypt::decrypt($object->journal_description) : $object->journal_description;
|
$entry->description = self::decrypt($object->journal_encrypted, $object->journal_description);
|
||||||
$entry->amount = round($object->amount, 2); // always positive
|
$entry->amount = $object->amount;
|
||||||
$entry->date = $object->date;
|
$entry->date = $object->date;
|
||||||
$entry->transaction_type = $object->transaction_type;
|
$entry->transaction_type = $object->transaction_type;
|
||||||
$entry->currency_code = $object->transaction_currency_code;
|
$entry->currency_code = $object->transaction_currency_code;
|
||||||
|
|
||||||
// source information:
|
|
||||||
$entry->source_account_id = $object->account_id;
|
$entry->source_account_id = $object->account_id;
|
||||||
$entry->source_account_name = $object->account_name_encrypted === 1 ? Crypt::decrypt($object->account_name) : $object->account_name;
|
$entry->source_account_name = self::decrypt($object->account_name_encrypted, $object->account_name);
|
||||||
|
|
||||||
|
|
||||||
// destination information
|
|
||||||
$entry->destination_account_id = $object->opposing_account_id;
|
$entry->destination_account_id = $object->opposing_account_id;
|
||||||
$entry->destination_account_name = $object->opposing_account_encrypted === 1 ? Crypt::decrypt($object->opposing_account_name)
|
$entry->destination_account_name = self::decrypt($object->opposing_account_encrypted, $object->opposing_account_name);
|
||||||
: $object->opposing_account_name;
|
|
||||||
|
|
||||||
|
|
||||||
// category and budget
|
|
||||||
$entry->category_id = $object->category_id ?? '';
|
$entry->category_id = $object->category_id ?? '';
|
||||||
$entry->category_name = $object->category_name ?? '';
|
$entry->category_name = $object->category_name ?? '';
|
||||||
$entry->budget_id = $object->budget_id ?? '';
|
$entry->budget_id = $object->budget_id ?? '';
|
||||||
$entry->budget_name = $object->budget_name ?? '';
|
$entry->budget_name = $object->budget_name ?? '';
|
||||||
|
|
||||||
|
|
||||||
// update description when transaction description is different:
|
// update description when transaction description is different:
|
||||||
if (!is_null($object->description) && $object->description != $entry->description) {
|
if (!is_null($object->description) && $object->description != $entry->description) {
|
||||||
$entry->description = $entry->description . ' (' . $object->description . ')';
|
$entry->description = $entry->description . ' (' . $object->description . ')';
|
||||||
@ -107,4 +96,19 @@ final class Entry
|
|||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $isEncrypted
|
||||||
|
* @param $value
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function decrypt(int $isEncrypted, $value)
|
||||||
|
{
|
||||||
|
if ($isEncrypted === 1) {
|
||||||
|
return Crypt::decrypt($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ interface ExporterInterface
|
|||||||
/**
|
/**
|
||||||
* @param Collection $entries
|
* @param Collection $entries
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function setEntries(Collection $entries);
|
public function setEntries(Collection $entries);
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ class Processor implements ProcessorInterface
|
|||||||
$zip->close();
|
$zip->close();
|
||||||
|
|
||||||
// delete the files:
|
// delete the files:
|
||||||
$this->deleteFiles($disk);
|
$this->deleteFiles();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -183,10 +183,11 @@ class Processor implements ProcessorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param FilesystemAdapter $disk
|
*
|
||||||
*/
|
*/
|
||||||
private function deleteFiles(FilesystemAdapter $disk)
|
private function deleteFiles()
|
||||||
{
|
{
|
||||||
|
$disk = Storage::disk('export');
|
||||||
foreach ($this->getFiles() as $file) {
|
foreach ($this->getFiles() as $file) {
|
||||||
$disk->delete($file);
|
$disk->delete($file);
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ interface ProcessorInterface
|
|||||||
* Processor constructor.
|
* Processor constructor.
|
||||||
*
|
*
|
||||||
* @param array $settings
|
* @param array $settings
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function __construct(array $settings);
|
public function __construct(array $settings);
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ class ChartJsGenerator implements GeneratorInterface
|
|||||||
* ]
|
* ]
|
||||||
* ]
|
* ]
|
||||||
*
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
*
|
*
|
||||||
@ -58,7 +59,7 @@ class ChartJsGenerator implements GeneratorInterface
|
|||||||
{
|
{
|
||||||
reset($data);
|
reset($data);
|
||||||
$first = current($data);
|
$first = current($data);
|
||||||
$labels = array_keys($first['entries']);
|
$labels = is_array($first['entries']) ? array_keys($first['entries']) : [];
|
||||||
|
|
||||||
$chartData = [
|
$chartData = [
|
||||||
'count' => count($data),
|
'count' => count($data),
|
||||||
@ -111,7 +112,7 @@ class ChartJsGenerator implements GeneratorInterface
|
|||||||
$value = bcmul($value, '-1');
|
$value = bcmul($value, '-1');
|
||||||
}
|
}
|
||||||
|
|
||||||
$chartData['datasets'][0]['data'][] = round($value, 2);
|
$chartData['datasets'][0]['data'][] = $value;
|
||||||
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
|
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
|
||||||
$chartData['labels'][] = $key;
|
$chartData['labels'][] = $key;
|
||||||
$index++;
|
$index++;
|
||||||
|
@ -16,7 +16,7 @@ namespace FireflyIII\Generator\Report\Audit;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -50,32 +50,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
|||||||
foreach ($this->accounts as $account) {
|
foreach ($this->accounts as $account) {
|
||||||
// balance the day before:
|
// balance the day before:
|
||||||
$id = $account->id;
|
$id = $account->id;
|
||||||
$dayBeforeBalance = Steam::balance($account, $dayBefore);
|
$auditData[$id] = $this->getAuditReport($account, $dayBefore);
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$journals = $journals->reverse();
|
|
||||||
$startBalance = $dayBeforeBalance;
|
|
||||||
|
|
||||||
|
|
||||||
/** @var Transaction $journal */
|
|
||||||
foreach ($journals as $transaction) {
|
|
||||||
$transaction->before = $startBalance;
|
|
||||||
$transactionAmount = $transaction->transaction_amount;
|
|
||||||
$newBalance = bcadd($startBalance, $transactionAmount);
|
|
||||||
$transaction->after = $newBalance;
|
|
||||||
$startBalance = $newBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reverse set again.
|
|
||||||
*/
|
|
||||||
$auditData[$id]['journals'] = $journals->reverse();
|
|
||||||
$auditData[$id]['exists'] = $journals->count() > 0;
|
|
||||||
$auditData[$id]['end'] = $this->end->formatLocalized(strval(trans('config.month_and_day')));
|
|
||||||
$auditData[$id]['endBalance'] = Steam::balance($account, $this->end);
|
|
||||||
$auditData[$id]['dayBefore'] = $dayBefore->formatLocalized(strval(trans('config.month_and_day')));
|
|
||||||
$auditData[$id]['dayBeforeBalance'] = $dayBeforeBalance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultShow = ['icon', 'description', 'balance_before', 'amount', 'balance_after', 'date', 'to'];
|
$defaultShow = ['icon', 'description', 'balance_before', 'amount', 'balance_after', 'date', 'to'];
|
||||||
@ -153,4 +128,46 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Account $account
|
||||||
|
* @param Carbon $date
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getAuditReport(Account $account, Carbon $date): array
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end);
|
||||||
|
$journals = $collector->getJournals();
|
||||||
|
$journals = $journals->reverse();
|
||||||
|
$dayBeforeBalance = Steam::balance($account, $date);
|
||||||
|
$startBalance = $dayBeforeBalance;
|
||||||
|
|
||||||
|
|
||||||
|
/** @var Transaction $journal */
|
||||||
|
foreach ($journals as $transaction) {
|
||||||
|
$transaction->before = $startBalance;
|
||||||
|
$transactionAmount = $transaction->transaction_amount;
|
||||||
|
$newBalance = bcadd($startBalance, $transactionAmount);
|
||||||
|
$transaction->after = $newBalance;
|
||||||
|
$startBalance = $newBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reverse set again.
|
||||||
|
*/
|
||||||
|
$return = [
|
||||||
|
'journals' => $journals->reverse(),
|
||||||
|
'exists' => $journals->count() > 0,
|
||||||
|
'end' => $this->end->formatLocalized(strval(trans('config.month_and_day'))),
|
||||||
|
'endBalance' => Steam::balance($account, $this->end),
|
||||||
|
'dayBefore' => $date->formatLocalized(strval(trans('config.month_and_day'))),
|
||||||
|
'dayBeforeBalance' => $dayBeforeBalance,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace FireflyIII\Generator\Report\Budget;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
||||||
use FireflyIII\Generator\Report\Support;
|
use FireflyIII\Generator\Report\Support;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -184,7 +184,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
|||||||
return $this->expenses;
|
return $this->expenses;
|
||||||
}
|
}
|
||||||
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
|
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
|
||||||
->setTypes([TransactionType::WITHDRAWAL])
|
->setTypes([TransactionType::WITHDRAWAL])
|
||||||
->setBudgets($this->budgets)->withOpposingAccount()->disableFilter();
|
->setBudgets($this->budgets)->withOpposingAccount()->disableFilter();
|
||||||
|
@ -17,7 +17,7 @@ namespace FireflyIII\Generator\Report\Category;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
||||||
use FireflyIII\Generator\Report\Support;
|
use FireflyIII\Generator\Report\Support;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -194,7 +194,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
|||||||
return $this->expenses;
|
return $this->expenses;
|
||||||
}
|
}
|
||||||
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
|
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
|
||||||
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||||
->setCategories($this->categories)->withOpposingAccount()->disableFilter();
|
->setCategories($this->categories)->withOpposingAccount()->disableFilter();
|
||||||
@ -216,7 +217,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
|||||||
return $this->income;
|
return $this->income;
|
||||||
}
|
}
|
||||||
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
|
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
|
||||||
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||||
->setCategories($this->categories)->withOpposingAccount();
|
->setCategories($this->categories)->withOpposingAccount();
|
||||||
@ -229,6 +231,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
|
||||||
* @param array $spent
|
* @param array $spent
|
||||||
* @param array $earned
|
* @param array $earned
|
||||||
*
|
*
|
||||||
|
@ -34,27 +34,7 @@ class Support
|
|||||||
*/
|
*/
|
||||||
public static function filterExpenses(Collection $collection, array $accounts): Collection
|
public static function filterExpenses(Collection $collection, array $accounts): Collection
|
||||||
{
|
{
|
||||||
$result = $collection->filter(
|
return self::filterTransactions($collection, $accounts, 1);
|
||||||
function (Transaction $transaction) use ($accounts) {
|
|
||||||
$opposing = $transaction->opposing_account_id;
|
|
||||||
// remove internal transfer
|
|
||||||
if (in_array($opposing, $accounts)) {
|
|
||||||
Log::debug(sprintf('Filtered #%d because its opposite is in accounts.', $transaction->id));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// remove positive amount
|
|
||||||
if (bccomp($transaction->transaction_amount, '0') === 1) {
|
|
||||||
Log::debug(sprintf('Filtered #%d because amount is %f.', $transaction->id, $transaction->transaction_amount));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $transaction;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,9 +44,21 @@ class Support
|
|||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public static function filterIncome(Collection $collection, array $accounts): Collection
|
public static function filterIncome(Collection $collection, array $accounts): Collection
|
||||||
|
{
|
||||||
|
return self::filterTransactions($collection, $accounts, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $collection
|
||||||
|
* @param array $accounts
|
||||||
|
* @param int $modifier
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public static function filterTransactions(Collection $collection, array $accounts, int $modifier): Collection
|
||||||
{
|
{
|
||||||
$result = $collection->filter(
|
$result = $collection->filter(
|
||||||
function (Transaction $transaction) use ($accounts) {
|
function (Transaction $transaction) use ($accounts, $modifier) {
|
||||||
$opposing = $transaction->opposing_account_id;
|
$opposing = $transaction->opposing_account_id;
|
||||||
// remove internal transfer
|
// remove internal transfer
|
||||||
if (in_array($opposing, $accounts)) {
|
if (in_array($opposing, $accounts)) {
|
||||||
@ -75,7 +67,7 @@ class Support
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// remove positive amount
|
// remove positive amount
|
||||||
if (bccomp($transaction->transaction_amount, '0') === -1) {
|
if (bccomp($transaction->transaction_amount, '0') === $modifier) {
|
||||||
Log::debug(sprintf('Filtered #%d because amount is %f.', $transaction->id, $transaction->transaction_amount));
|
Log::debug(sprintf('Filtered #%d because amount is %f.', $transaction->id, $transaction->transaction_amount));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BudgetEventHandler.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 Carbon\Carbon;
|
|
||||||
use FireflyIII\Events\StoredBudgetLimit;
|
|
||||||
use FireflyIII\Events\UpdatedBudgetLimit;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use FireflyIII\Models\LimitRepetition;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles budget related events.
|
|
||||||
*
|
|
||||||
* Class BudgetEventHandler
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
|
||||||
*/
|
|
||||||
class BudgetEventHandler
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method creates a new budget limit repetition when a new budget limit has been created.
|
|
||||||
*
|
|
||||||
* @param StoredBudgetLimit $budgetLimitEvent
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function storeRepetition(StoredBudgetLimit $budgetLimitEvent): bool
|
|
||||||
{
|
|
||||||
return $this->processRepetitionChange($budgetLimitEvent->budgetLimit, $budgetLimitEvent->end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates, if present the budget limit repetition part of a budget limit.
|
|
||||||
*
|
|
||||||
* @param UpdatedBudgetLimit $budgetLimitEvent
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function updateRepetition(UpdatedBudgetLimit $budgetLimitEvent): bool
|
|
||||||
{
|
|
||||||
return $this->processRepetitionChange($budgetLimitEvent->budgetLimit, $budgetLimitEvent->end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BudgetLimit $budgetLimit
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function processRepetitionChange(BudgetLimit $budgetLimit, Carbon $date): bool
|
|
||||||
{
|
|
||||||
$set = $budgetLimit->limitrepetitions()
|
|
||||||
->where('startdate', $budgetLimit->startdate->format('Y-m-d 00:00:00'))
|
|
||||||
->where('enddate', $date->format('Y-m-d 00:00:00'))
|
|
||||||
->get();
|
|
||||||
if ($set->count() == 0) {
|
|
||||||
$repetition = new LimitRepetition;
|
|
||||||
$repetition->startdate = $budgetLimit->startdate;
|
|
||||||
$repetition->enddate = $date;
|
|
||||||
$repetition->amount = $budgetLimit->amount;
|
|
||||||
$repetition->budgetLimit()->associate($budgetLimit);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$repetition->save();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Log::error('Trying to save new LimitRepetition failed: ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($set->count() == 1) {
|
|
||||||
$repetition = $set->first();
|
|
||||||
$repetition->amount = $budgetLimit->amount;
|
|
||||||
$repetition->save();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,7 @@ namespace FireflyIII\Handlers\Events;
|
|||||||
use FireflyIII\Events\StoredTransactionJournal;
|
use FireflyIII\Events\StoredTransactionJournal;
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\PiggyBankEvent;
|
use FireflyIII\Models\PiggyBankEvent;
|
||||||
|
use FireflyIII\Models\PiggyBankRepetition;
|
||||||
use FireflyIII\Models\Rule;
|
use FireflyIII\Models\Rule;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
@ -33,79 +34,40 @@ class StoredJournalEventHandler
|
|||||||
/**
|
/**
|
||||||
* This method connects a new transfer to a piggy bank.
|
* This method connects a new transfer to a piggy bank.
|
||||||
*
|
*
|
||||||
* @param StoredTransactionJournal $storedJournalEvent
|
* @param StoredTransactionJournal $event
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function connectToPiggyBank(StoredTransactionJournal $storedJournalEvent): bool
|
public function connectToPiggyBank(StoredTransactionJournal $event): bool
|
||||||
{
|
{
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = $storedJournalEvent->journal;
|
$journal = $event->journal;
|
||||||
$piggyBankId = $storedJournalEvent->piggyBankId;
|
$piggyBankId = $event->piggyBankId;
|
||||||
|
|
||||||
Log::debug(sprintf('Trying to connect journal %d to piggy bank %d.', $journal->id, $piggyBankId));
|
Log::debug(sprintf('Trying to connect journal %d to piggy bank %d.', $journal->id, $piggyBankId));
|
||||||
|
|
||||||
/** @var PiggyBank $piggyBank */
|
/*
|
||||||
|
* Verify existence of piggy bank:
|
||||||
|
*/
|
||||||
|
if (!$this->verifyExistence($event)) {
|
||||||
|
Log::error(sprintf('No such piggy bank or no repetition on %s', $journal->date->format('Y-m-d')));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get relevant data:
|
||||||
|
*/
|
||||||
$piggyBank = $journal->user->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
$piggyBank = $journal->user->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||||
|
|
||||||
if (is_null($piggyBank)) {
|
|
||||||
Log::error('No such piggy bank!');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Log::debug(sprintf('Found piggy bank #%d: "%s"', $piggyBank->id, $piggyBank->name));
|
|
||||||
// update piggy bank rep for date of transaction journal.
|
|
||||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||||
if (is_null($repetition)) {
|
$amount = $this->getExactAmount($journal, $piggyBank, $repetition);
|
||||||
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$amount = TransactionJournal::amountPositive($journal);
|
|
||||||
Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
|
|
||||||
// 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');
|
|
||||||
Log::debug(sprintf('Account #%d is the source, so will remove amount from piggy bank.', $piggyBank->account_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the amount is positive:
|
|
||||||
// make sure it fits in piggy bank:
|
|
||||||
if (bccomp($amount, '0') === 1) {
|
|
||||||
// amount is positive
|
|
||||||
$room = bcsub(strval($piggyBank->targetamount), strval($repetition->currentamount));
|
|
||||||
Log::debug(sprintf('Room in piggy bank for extra money is %f', $room));
|
|
||||||
if (bccomp($room, $amount) === -1) {
|
|
||||||
// $room is smaller than $amount
|
|
||||||
Log::debug(sprintf('There is NO room to add %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
|
|
||||||
Log::debug(sprintf('New amount is %f', $room));
|
|
||||||
$amount = $room;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bccomp($amount, '0') === -1) {
|
|
||||||
// amount is negative
|
|
||||||
Log::debug(sprintf('Max amount to remove is %f', $repetition->currentamount));
|
|
||||||
$compare = bcmul($repetition->currentamount, '-1');
|
|
||||||
if (bccomp($compare, $amount) === 1) {
|
|
||||||
// $currentamount is smaller than $amount
|
|
||||||
Log::debug(sprintf('Cannot remove %f from piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
|
|
||||||
Log::debug(sprintf('New amount is %f', $compare));
|
|
||||||
$amount = $compare;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||||
$repetition->save();
|
$repetition->save();
|
||||||
|
|
||||||
/** @var PiggyBankEvent $storedJournalEvent */
|
/** @var PiggyBankEvent $event */
|
||||||
$storedJournalEvent = PiggyBankEvent::create(
|
$event = PiggyBankEvent::create(
|
||||||
['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]
|
['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]
|
||||||
);
|
);
|
||||||
Log::debug(sprintf('Created piggy bank event #%d', $storedJournalEvent->id));
|
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -161,4 +123,81 @@ class StoredJournalEventHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 6 but I can live with it.
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
* @param PiggyBank $piggyBank
|
||||||
|
* @param PiggyBankRepetition $repetition
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getExactAmount(TransactionJournal $journal, PiggyBank $piggyBank, PiggyBankRepetition $repetition): string
|
||||||
|
{
|
||||||
|
$amount = TransactionJournal::amountPositive($journal);
|
||||||
|
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
|
||||||
|
$room = bcsub(strval($piggyBank->targetamount), strval($repetition->currentamount));
|
||||||
|
$compare = bcmul($repetition->currentamount, '-1');
|
||||||
|
|
||||||
|
Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
|
||||||
|
|
||||||
|
// if piggy account matches source account, the amount is positive
|
||||||
|
if (in_array($piggyBank->account_id, $sources)) {
|
||||||
|
$amount = bcmul($amount, '-1');
|
||||||
|
Log::debug(sprintf('Account #%d is the source, so will remove amount from piggy bank.', $piggyBank->account_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if the amount is positive, make sure it fits in piggy bank:
|
||||||
|
if (bccomp($amount, '0') === 1 && bccomp($room, $amount) === -1) {
|
||||||
|
// amount is positive and $room is smaller than $amount
|
||||||
|
Log::debug(sprintf('Room in piggy bank for extra money is %f', $room));
|
||||||
|
Log::debug(sprintf('There is NO room to add %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
|
||||||
|
Log::debug(sprintf('New amount is %f', $room));
|
||||||
|
|
||||||
|
return $room;
|
||||||
|
}
|
||||||
|
|
||||||
|
// amount is negative and $currentamount is smaller than $amount
|
||||||
|
if (bccomp($amount, '0') === -1 && bccomp($compare, $amount) === 1) {
|
||||||
|
Log::debug(sprintf('Max amount to remove is %f', $repetition->currentamount));
|
||||||
|
Log::debug(sprintf('Cannot remove %f from piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
|
||||||
|
Log::debug(sprintf('New amount is %f', $compare));
|
||||||
|
|
||||||
|
return $compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param StoredTransactionJournal $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function verifyExistence(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)) {
|
||||||
|
Log::error('No such piggy bank!');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Found piggy bank #%d: "%s"', $piggyBank->id, $piggyBank->name));
|
||||||
|
// update piggy bank rep for date of transaction journal.
|
||||||
|
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||||
|
if (is_null($repetition)) {
|
||||||
|
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,25 +13,12 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use FireflyConfig;
|
|
||||||
use FireflyIII\Events\BlockedBadLogin;
|
|
||||||
use FireflyIII\Events\BlockedUseOfDomain;
|
|
||||||
use FireflyIII\Events\BlockedUseOfEmail;
|
|
||||||
use FireflyIII\Events\BlockedUserLogin;
|
|
||||||
use FireflyIII\Events\ConfirmedUser;
|
|
||||||
use FireflyIII\Events\DeletedUser;
|
|
||||||
use FireflyIII\Events\LockedOutUser;
|
|
||||||
use FireflyIII\Events\RegisteredUser;
|
use FireflyIII\Events\RegisteredUser;
|
||||||
use FireflyIII\Events\RequestedNewPassword;
|
use FireflyIII\Events\RequestedNewPassword;
|
||||||
use FireflyIII\Events\ResentConfirmation;
|
|
||||||
use FireflyIII\Models\Configuration;
|
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Mail\Message;
|
use Illuminate\Mail\Message;
|
||||||
use Log;
|
use Log;
|
||||||
use Mail;
|
use Mail;
|
||||||
use Preferences;
|
|
||||||
use Session;
|
use Session;
|
||||||
use Swift_TransportException;
|
use Swift_TransportException;
|
||||||
|
|
||||||
@ -42,7 +29,6 @@ use Swift_TransportException;
|
|||||||
*
|
*
|
||||||
* The method name reflects what is being done. This is in the present tense.
|
* The method name reflects what is being done. This is in the present tense.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @package FireflyIII\Handlers\Events
|
* @package FireflyIII\Handlers\Events
|
||||||
*/
|
*/
|
||||||
class UserEventHandler
|
class UserEventHandler
|
||||||
@ -82,237 +68,6 @@ class UserEventHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BlockedBadLogin $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function reportBadLogin(BlockedBadLogin $event)
|
|
||||||
{
|
|
||||||
$email = $event->email;
|
|
||||||
$owner = env('SITE_OWNER');
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
/** @var Configuration $sendmail */
|
|
||||||
$sendmail = FireflyConfig::get('mail_for_bad_login', config('firefly.configuration.mail_for_bad_login'));
|
|
||||||
Log::debug(sprintf('Now in reportBadLogin for email address %s', $email));
|
|
||||||
Log::error(sprintf('User %s tried to login with bad credentials.', $email));
|
|
||||||
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.blocked-bad-creds-html', 'emails.blocked-bad-creds-text'], ['email' => $email, 'ip' => $ipAddress],
|
|
||||||
function (Message $message) use ($owner) {
|
|
||||||
$message->to($owner, $owner)->subject('Blocked login attempt with bad credentials');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BlockedUserLogin $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function reportBlockedUser(BlockedUserLogin $event): bool
|
|
||||||
{
|
|
||||||
$user = $event->user;
|
|
||||||
$owner = env('SITE_OWNER');
|
|
||||||
$email = $user->email;
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
/** @var Configuration $sendmail */
|
|
||||||
$sendmail = FireflyConfig::get('mail_for_blocked_login', config('firefly.configuration.mail_for_blocked_login'));
|
|
||||||
Log::debug(sprintf('Now in reportBlockedUser for email address %s', $email));
|
|
||||||
Log::error(sprintf('User #%d (%s) has their accout blocked (blocked_code is "%s") but tried to login.', $user->id, $email, $user->blocked_code));
|
|
||||||
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send email message:
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.blocked-login-html', 'emails.blocked-login-text'],
|
|
||||||
[
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'user_address' => $email,
|
|
||||||
'ip' => $ipAddress,
|
|
||||||
'code' => $user->blocked_code,
|
|
||||||
], function (Message $message) use ($owner, $user) {
|
|
||||||
$message->to($owner, $owner)->subject('Blocked login attempt of blocked user');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param LockedOutUser $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function reportLockout(LockedOutUser $event): bool
|
|
||||||
{
|
|
||||||
$email = $event->email;
|
|
||||||
$owner = env('SITE_OWNER');
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
/** @var Configuration $sendmail */
|
|
||||||
$sendmail = FireflyConfig::get('mail_for_lockout', config('firefly.configuration.mail_for_lockout'));
|
|
||||||
Log::debug(sprintf('Now in respondToLockout for email address %s', $email));
|
|
||||||
Log::error(sprintf('User %s was locked out after too many invalid login attempts.', $email));
|
|
||||||
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send email message:
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.locked-out-html', 'emails.locked-out-text'], ['email' => $email, 'ip' => $ipAddress], function (Message $message) use ($owner) {
|
|
||||||
$message->to($owner, $owner)->subject('User was locked out');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BlockedUseOfDomain $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function reportUseBlockedDomain(BlockedUseOfDomain $event): bool
|
|
||||||
{
|
|
||||||
$email = $event->email;
|
|
||||||
$owner = env('SITE_OWNER');
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
$parts = explode('@', $email);
|
|
||||||
/** @var Configuration $sendmail */
|
|
||||||
$sendmail = FireflyConfig::get('mail_for_blocked_domain', config('firefly.configuration.mail_for_blocked_domain'));
|
|
||||||
Log::debug(sprintf('Now in reportUseBlockedDomain for email address %s', $email));
|
|
||||||
Log::error(sprintf('Somebody tried to register using an email address (%s) connected to a banned domain (%s).', $email, $parts[1]));
|
|
||||||
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send email message:
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.blocked-registration-html', 'emails.blocked-registration-text'],
|
|
||||||
[
|
|
||||||
'email_address' => $email,
|
|
||||||
'blocked_domain' => $parts[1],
|
|
||||||
'ip' => $ipAddress,
|
|
||||||
], function (Message $message) use ($owner) {
|
|
||||||
$message->to($owner, $owner)->subject('Blocked registration attempt with blocked domain');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BlockedUseOfEmail $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function reportUseOfBlockedEmail(BlockedUseOfEmail $event): bool
|
|
||||||
{
|
|
||||||
$email = $event->email;
|
|
||||||
$owner = env('SITE_OWNER');
|
|
||||||
$ipAddress = $event->ipAddress;
|
|
||||||
/** @var Configuration $sendmail */
|
|
||||||
$sendmail = FireflyConfig::get('mail_for_blocked_email', config('firefly.configuration.mail_for_blocked_email'));
|
|
||||||
Log::debug(sprintf('Now in reportUseOfBlockedEmail for email address %s', $email));
|
|
||||||
Log::error(sprintf('Somebody tried to register using email address %s which is blocked (SHA2 hash).', $email));
|
|
||||||
if (is_null($sendmail) || (!is_null($sendmail) && $sendmail->data === false)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send email message:
|
|
||||||
try {
|
|
||||||
Mail::send(
|
|
||||||
['emails.blocked-email-html', 'emails.blocked-email-text'],
|
|
||||||
[
|
|
||||||
'user_address' => $email,
|
|
||||||
'ip' => $ipAddress,
|
|
||||||
], function (Message $message) use ($owner) {
|
|
||||||
$message->to($owner, $owner)->subject('Blocked registration attempt with blocked email address');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Swift_TransportException $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DeletedUser $event
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function saveEmailAddress(DeletedUser $event): bool
|
|
||||||
{
|
|
||||||
Preferences::mark();
|
|
||||||
$email = hash('sha256', $event->email);
|
|
||||||
Log::debug(sprintf('Hash of email is %s', $email));
|
|
||||||
/** @var Configuration $configuration */
|
|
||||||
$configuration = FireflyConfig::get('deleted_users', []);
|
|
||||||
$content = $configuration->data;
|
|
||||||
if (!is_array($content)) {
|
|
||||||
$content = [];
|
|
||||||
}
|
|
||||||
$content[] = $email;
|
|
||||||
$configuration->data = $content;
|
|
||||||
Log::debug('New content of deleted_users is ', $content);
|
|
||||||
FireflyConfig::set('deleted_users', $content);
|
|
||||||
|
|
||||||
Preferences::mark();
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return $this->sendConfirmation($event->user, $event->ipAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
{
|
|
||||||
return $this->sendConfirmation($event->user, $event->ipAddress);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RequestedNewPassword $event
|
* @param RequestedNewPassword $event
|
||||||
*
|
*
|
||||||
@ -372,75 +127,4 @@ class UserEventHandler
|
|||||||
|
|
||||||
return true;
|
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param User $user
|
|
||||||
* @param string $ipAddress
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function sendConfirmation(User $user, string $ipAddress): bool
|
|
||||||
{
|
|
||||||
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'))->data;
|
|
||||||
if ($mustConfirmAccount === 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-text'], ['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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ use Crypt;
|
|||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\MessageBag;
|
use Illuminate\Support\MessageBag;
|
||||||
use Input;
|
|
||||||
use Storage;
|
use Storage;
|
||||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
|
||||||
@ -82,19 +81,18 @@ class AttachmentHelper implements AttachmentHelperInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Model $model
|
* @param Model $model
|
||||||
|
* @param array|null $files
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function saveAttachmentsForModel(Model $model): bool
|
public function saveAttachmentsForModel(Model $model, array $files = null): bool
|
||||||
{
|
{
|
||||||
$files = $this->getFiles();
|
|
||||||
|
|
||||||
if (!is_null($files) && !is_array($files)) {
|
|
||||||
$this->processFile($files, $model);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($files)) {
|
if (is_array($files)) {
|
||||||
$this->processFiles($files, $model);
|
foreach ($files as $entry) {
|
||||||
|
if (!is_null($entry)) {
|
||||||
|
$this->processFile($entry, $model);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -227,37 +225,4 @@ class AttachmentHelper implements AttachmentHelperInterface
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array|null|UploadedFile
|
|
||||||
*/
|
|
||||||
private function getFiles()
|
|
||||||
{
|
|
||||||
$files = null;
|
|
||||||
if (Input::hasFile('attachments')) {
|
|
||||||
$files = Input::file('attachments');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $files;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $files
|
|
||||||
*
|
|
||||||
* @param Model $model
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function processFiles(array $files, Model $model): bool
|
|
||||||
{
|
|
||||||
foreach ($files as $entry) {
|
|
||||||
if (!is_null($entry)) {
|
|
||||||
$this->processFile($entry, $model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,6 @@ interface AttachmentHelperInterface
|
|||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function saveAttachmentsForModel(Model $model): bool;
|
public function saveAttachmentsForModel(Model $model, array $files = null): bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
278
app/Helpers/Chart/MetaPieChart.php
Normal file
278
app/Helpers/Chart/MetaPieChart.php
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* MetaPieChart.php
|
||||||
|
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||||
|
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Helpers\Chart;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Generator\Report\Support;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MetaPieChart
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Helpers\Chart
|
||||||
|
*/
|
||||||
|
class MetaPieChart implements MetaPieChartInterface
|
||||||
|
{
|
||||||
|
/** @var Collection */
|
||||||
|
protected $accounts;
|
||||||
|
/** @var Collection */
|
||||||
|
protected $budgets;
|
||||||
|
/** @var Collection */
|
||||||
|
protected $categories;
|
||||||
|
/** @var bool */
|
||||||
|
protected $collectOtherObjects = false;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $end;
|
||||||
|
/** @var array */
|
||||||
|
protected $grouping
|
||||||
|
= [
|
||||||
|
'account' => ['opposing_account_id'],
|
||||||
|
'budget' => ['transaction_journal_budget_id', 'transaction_budget_id'],
|
||||||
|
'category' => ['transaction_journal_category_id', 'transaction_category_id'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
protected $repositories
|
||||||
|
= [
|
||||||
|
'account' => AccountRepositoryInterface::class,
|
||||||
|
'budget' => BudgetRepositoryInterface::class,
|
||||||
|
'category' => CategoryRepositoryInterface::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $start;
|
||||||
|
/** @var string */
|
||||||
|
protected $total = '0';
|
||||||
|
/** @var User */
|
||||||
|
protected $user;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->accounts = new Collection;
|
||||||
|
$this->budgets = new Collection;
|
||||||
|
$this->categories = new Collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $direction
|
||||||
|
* @param string $group
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function generate(string $direction, string $group): array
|
||||||
|
{
|
||||||
|
$transactions = $this->getTransactions($direction);
|
||||||
|
$grouped = $this->groupByFields($transactions, $this->grouping[$group]);
|
||||||
|
$chartData = $this->organizeByType($group, $grouped);
|
||||||
|
|
||||||
|
// also collect all other transactions
|
||||||
|
if ($this->collectOtherObjects && $direction === 'expense') {
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [$this->user]);
|
||||||
|
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
|
$journals = $collector->getJournals();
|
||||||
|
$sum = strval($journals->sum('transaction_amount'));
|
||||||
|
$sum = bcmul($sum, '-1');
|
||||||
|
$sum = bcsub($sum, $this->total);
|
||||||
|
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->collectOtherObjects && $direction === 'income') {
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::DEPOSIT]);
|
||||||
|
$journals = $collector->getJournals();
|
||||||
|
$sum = strval($journals->sum('transaction_amount'));
|
||||||
|
$sum = bcsub($sum, $this->total);
|
||||||
|
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $chartData;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setAccounts(Collection $accounts): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->accounts = $accounts;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->budgets = $budgets;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $categories
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setCategories(Collection $categories): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->categories = $categories;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $collectOtherObjects
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setCollectOtherObjects(bool $collectOtherObjects): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->collectOtherObjects = $collectOtherObjects;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setEnd(Carbon $end): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->end = $end;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setStart(Carbon $start): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->start = $start;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setUser(User $user): MetaPieChartInterface
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTransactions(string $direction)
|
||||||
|
{
|
||||||
|
$types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
|
||||||
|
$modifier = -1;
|
||||||
|
if ($direction === 'expense') {
|
||||||
|
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
|
||||||
|
$modifier = 1;
|
||||||
|
}
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
$collector->setAccounts($this->accounts);
|
||||||
|
$collector->setRange($this->start, $this->end);
|
||||||
|
$collector->setTypes($types);
|
||||||
|
$collector->withOpposingAccount();
|
||||||
|
|
||||||
|
if ($direction === 'income') {
|
||||||
|
$collector->disableFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->budgets->count() > 0) {
|
||||||
|
$collector->setBudgets($this->budgets);
|
||||||
|
}
|
||||||
|
if ($this->categories->count() > 0) {
|
||||||
|
$collector->setCategories($this->categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
$accountIds = $this->accounts->pluck('id')->toArray();
|
||||||
|
$transactions = $collector->getJournals();
|
||||||
|
$set = Support::filterTransactions($transactions, $accountIds, $modifier);
|
||||||
|
|
||||||
|
return $set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $set
|
||||||
|
* @param array $fields
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function groupByFields(Collection $set, array $fields)
|
||||||
|
{
|
||||||
|
$grouped = [];
|
||||||
|
/** @var Transaction $transaction */
|
||||||
|
foreach ($set as $transaction) {
|
||||||
|
$values = [];
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$values[] = intval($transaction->$field);
|
||||||
|
}
|
||||||
|
$value = max($values);
|
||||||
|
$grouped[$value] = $grouped[$value] ?? '0';
|
||||||
|
$grouped[$value] = bcadd($transaction->transaction_amount, $grouped[$value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $grouped;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
* @param array $array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function organizeByType(string $type, array $array): array
|
||||||
|
{
|
||||||
|
$chartData = [];
|
||||||
|
$names = [];
|
||||||
|
$repository = app($this->repositories[$type], [$this->user]);
|
||||||
|
foreach ($array as $objectId => $amount) {
|
||||||
|
if (!isset($names[$objectId])) {
|
||||||
|
$object = $repository->find(intval($objectId));
|
||||||
|
$names[$objectId] = $object->name;
|
||||||
|
}
|
||||||
|
if (bccomp($amount, '0') === -1) {
|
||||||
|
$amount = bcmul($amount, '-1');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->total = bcadd($this->total, $amount);
|
||||||
|
$chartData[$names[$objectId]] = $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $chartData;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
82
app/Helpers/Chart/MetaPieChartInterface.php
Normal file
82
app/Helpers/Chart/MetaPieChartInterface.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* MetaPieChartInterface.php
|
||||||
|
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||||
|
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Helpers\Chart;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface MetaPieChartInterface
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Helpers\Chart
|
||||||
|
*/
|
||||||
|
interface MetaPieChartInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $direction
|
||||||
|
* @param string $group
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function generate(string $direction, string $group): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setAccounts(Collection $accounts): MetaPieChartInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): MetaPieChartInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $categories
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setCategories(Collection $categories): MetaPieChartInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $collectOtherObjects
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setCollectOtherObjects(bool $collectOtherObjects): MetaPieChartInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setEnd(Carbon $end): MetaPieChartInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setStart(Carbon $start): MetaPieChartInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return MetaPieChartInterface
|
||||||
|
*/
|
||||||
|
public function setUser(User $user): MetaPieChartInterface;
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,7 @@ namespace FireflyIII\Helpers\Collection;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\Budget as BudgetModel;
|
use FireflyIII\Models\Budget as BudgetModel;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,12 +35,10 @@ class BalanceLine
|
|||||||
|
|
||||||
/** @var BudgetModel */
|
/** @var BudgetModel */
|
||||||
protected $budget;
|
protected $budget;
|
||||||
/** @var Carbon */
|
/** @var BudgetLimit */
|
||||||
protected $endDate;
|
protected $budgetLimit;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $role = self::ROLE_DEFAULTROLE;
|
protected $role = self::ROLE_DEFAULTROLE;
|
||||||
/** @var Carbon */
|
|
||||||
protected $startDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -90,20 +89,28 @@ class BalanceLine
|
|||||||
$this->budget = $budget;
|
$this->budget = $budget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BudgetLimit
|
||||||
|
*/
|
||||||
|
public function getBudgetLimit(): BudgetLimit
|
||||||
|
{
|
||||||
|
return $this->budgetLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*/
|
||||||
|
public function setBudgetLimit(BudgetLimit $budgetLimit)
|
||||||
|
{
|
||||||
|
$this->budgetLimit = $budgetLimit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Carbon
|
* @return Carbon
|
||||||
*/
|
*/
|
||||||
public function getEndDate()
|
public function getEndDate()
|
||||||
{
|
{
|
||||||
return $this->endDate;
|
return $this->budgetLimit->end_date ?? new Carbon;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Carbon $endDate
|
|
||||||
*/
|
|
||||||
public function setEndDate($endDate)
|
|
||||||
{
|
|
||||||
$this->endDate = $endDate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,18 +134,11 @@ class BalanceLine
|
|||||||
*/
|
*/
|
||||||
public function getStartDate()
|
public function getStartDate()
|
||||||
{
|
{
|
||||||
return $this->startDate;
|
return $this->budgetLimit->start_date ?? new Carbon;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Carbon $startDate
|
|
||||||
*/
|
|
||||||
public function setStartDate($startDate)
|
|
||||||
{
|
|
||||||
$this->startDate = $startDate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getTitle(): string
|
public function getTitle(): string
|
||||||
@ -147,13 +147,13 @@ class BalanceLine
|
|||||||
return $this->getBudget()->name;
|
return $this->getBudget()->name;
|
||||||
}
|
}
|
||||||
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
|
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
|
||||||
return trans('firefly.no_budget');
|
return strval(trans('firefly.no_budget'));
|
||||||
}
|
}
|
||||||
if ($this->getRole() == self::ROLE_TAGROLE) {
|
if ($this->getRole() == self::ROLE_TAGROLE) {
|
||||||
return trans('firefly.coveredWithTags');
|
return strval(trans('firefly.coveredWithTags'));
|
||||||
}
|
}
|
||||||
if ($this->getRole() == self::ROLE_DIFFROLE) {
|
if ($this->getRole() == self::ROLE_DIFFROLE) {
|
||||||
return trans('firefly.leftUnbalanced');
|
return strval(trans('firefly.leftUnbalanced'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
@ -169,7 +169,7 @@ class BalanceLine
|
|||||||
*/
|
*/
|
||||||
public function leftOfRepetition(): string
|
public function leftOfRepetition(): string
|
||||||
{
|
{
|
||||||
$start = $this->budget->amount ?? '0';
|
$start = $this->budgetLimit->amount ?? '0';
|
||||||
/** @var BalanceEntry $balanceEntry */
|
/** @var BalanceEntry $balanceEntry */
|
||||||
foreach ($this->getBalanceEntries() as $balanceEntry) {
|
foreach ($this->getBalanceEntries() as $balanceEntry) {
|
||||||
$start = bcadd($balanceEntry->getSpent(), $start);
|
$start = bcadd($balanceEntry->getSpent(), $start);
|
||||||
|
@ -60,7 +60,6 @@ class Budget
|
|||||||
*/
|
*/
|
||||||
public function addBudgeted(string $add): Budget
|
public function addBudgeted(string $add): Budget
|
||||||
{
|
{
|
||||||
$add = strval(round($add, 2));
|
|
||||||
$this->budgeted = bcadd($this->budgeted, $add);
|
$this->budgeted = bcadd($this->budgeted, $add);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -73,7 +72,6 @@ class Budget
|
|||||||
*/
|
*/
|
||||||
public function addLeft(string $add): Budget
|
public function addLeft(string $add): Budget
|
||||||
{
|
{
|
||||||
$add = strval(round($add, 2));
|
|
||||||
$this->left = bcadd($this->left, $add);
|
$this->left = bcadd($this->left, $add);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -86,7 +84,6 @@ class Budget
|
|||||||
*/
|
*/
|
||||||
public function addOverspent(string $add): Budget
|
public function addOverspent(string $add): Budget
|
||||||
{
|
{
|
||||||
$add = strval(round($add, 2));
|
|
||||||
$this->overspent = bcadd($this->overspent, $add);
|
$this->overspent = bcadd($this->overspent, $add);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -99,7 +96,6 @@ class Budget
|
|||||||
*/
|
*/
|
||||||
public function addSpent(string $add): Budget
|
public function addSpent(string $add): Budget
|
||||||
{
|
{
|
||||||
$add = strval(round($add, 2));
|
|
||||||
$this->spent = bcadd($this->spent, $add);
|
$this->spent = bcadd($this->spent, $add);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -168,7 +164,7 @@ class Budget
|
|||||||
*/
|
*/
|
||||||
public function setOverspent(string $overspent): Budget
|
public function setOverspent(string $overspent): Budget
|
||||||
{
|
{
|
||||||
$this->overspent = strval(round($overspent, 2));
|
$this->overspent = $overspent;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -188,7 +184,7 @@ class Budget
|
|||||||
*/
|
*/
|
||||||
public function setSpent(string $spent): Budget
|
public function setSpent(string $spent): Budget
|
||||||
{
|
{
|
||||||
$this->spent = strval(round($spent, 2));
|
$this->spent = $spent;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Helpers\Collection;
|
namespace FireflyIII\Helpers\Collection;
|
||||||
|
|
||||||
use FireflyIII\Models\Budget as BudgetModel;
|
use FireflyIII\Models\Budget as BudgetModel;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -26,14 +26,14 @@ class BudgetLine
|
|||||||
|
|
||||||
/** @var BudgetModel */
|
/** @var BudgetModel */
|
||||||
protected $budget;
|
protected $budget;
|
||||||
|
/** @var BudgetLimit */
|
||||||
|
protected $budgetLimit;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $budgeted = '0';
|
protected $budgeted = '0';
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $left = '0';
|
protected $left = '0';
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $overspent = '0';
|
protected $overspent = '0';
|
||||||
/** @var LimitRepetition */
|
|
||||||
protected $repetition;
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $spent = '0';
|
protected $spent = '0';
|
||||||
|
|
||||||
@ -57,6 +57,26 @@ class BudgetLine
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BudgetLimit
|
||||||
|
*/
|
||||||
|
public function getBudgetLimit(): BudgetLimit
|
||||||
|
{
|
||||||
|
return $this->budgetLimit ?? new BudgetLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return BudgetLimit
|
||||||
|
*/
|
||||||
|
public function setBudgetLimit(BudgetLimit $budgetLimit): BudgetLine
|
||||||
|
{
|
||||||
|
$this->budgetLimit = $budgetLimit;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -117,26 +137,6 @@ class BudgetLine
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return LimitRepetition
|
|
||||||
*/
|
|
||||||
public function getRepetition(): LimitRepetition
|
|
||||||
{
|
|
||||||
return $this->repetition ?? new LimitRepetition;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param LimitRepetition $repetition
|
|
||||||
*
|
|
||||||
* @return BudgetLine
|
|
||||||
*/
|
|
||||||
public function setRepetition(LimitRepetition $repetition): BudgetLine
|
|
||||||
{
|
|
||||||
$this->repetition = $repetition;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -55,7 +55,6 @@ class Category
|
|||||||
*/
|
*/
|
||||||
public function addTotal(string $add)
|
public function addTotal(string $add)
|
||||||
{
|
{
|
||||||
$add = strval(round($add, 2));
|
|
||||||
$this->total = bcadd($this->total, $add);
|
$this->total = bcadd($this->total, $add);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +78,7 @@ class Category
|
|||||||
*/
|
*/
|
||||||
public function getTotal(): string
|
public function getTotal(): string
|
||||||
{
|
{
|
||||||
return strval(round($this->total, 2));
|
return $this->total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -563,7 +563,7 @@ class JournalCollector implements JournalCollectorInterface
|
|||||||
return $set;
|
return $set;
|
||||||
}
|
}
|
||||||
if ($this->joinedOpposing === false) {
|
if ($this->joinedOpposing === false) {
|
||||||
Log::error('Cannot filter internal transfers because no opposing information is present.');
|
Log::info('Cannot filter internal transfers because no opposing information is present.');
|
||||||
|
|
||||||
return $set;
|
return $set;
|
||||||
}
|
}
|
||||||
@ -649,9 +649,17 @@ class JournalCollector implements JournalCollectorInterface
|
|||||||
// join some extra tables:
|
// join some extra tables:
|
||||||
$this->joinedBudget = true;
|
$this->joinedBudget = true;
|
||||||
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||||
|
$this->query->leftJoin('budgets as transaction_journal_budgets', 'transaction_journal_budgets.id', '=', 'budget_transaction_journal.budget_id');
|
||||||
$this->query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
|
$this->query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
|
||||||
|
$this->query->leftJoin('budgets as transaction_budgets', 'transaction_budgets.id', '=', 'budget_transaction.budget_id');
|
||||||
|
|
||||||
$this->fields[] = 'budget_transaction_journal.budget_id as transaction_journal_budget_id';
|
$this->fields[] = 'budget_transaction_journal.budget_id as transaction_journal_budget_id';
|
||||||
|
$this->fields[] = 'transaction_journal_budgets.encrypted as transaction_journal_budget_encrypted';
|
||||||
|
$this->fields[] = 'transaction_journal_budgets.name as transaction_journal_budget_name';
|
||||||
|
|
||||||
$this->fields[] = 'budget_transaction.budget_id as transaction_budget_id';
|
$this->fields[] = 'budget_transaction.budget_id as transaction_budget_id';
|
||||||
|
$this->fields[] = 'transaction_budgets.encrypted as transaction_budget_encrypted';
|
||||||
|
$this->fields[] = 'transaction_budgets.name as transaction_budget_name';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,12 +672,26 @@ class JournalCollector implements JournalCollectorInterface
|
|||||||
// join some extra tables:
|
// join some extra tables:
|
||||||
$this->joinedCategory = true;
|
$this->joinedCategory = true;
|
||||||
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||||
|
$this->query->leftJoin(
|
||||||
|
'categories as transaction_journal_categories', 'transaction_journal_categories.id', '=', 'category_transaction_journal.category_id'
|
||||||
|
);
|
||||||
|
|
||||||
$this->query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id');
|
$this->query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id');
|
||||||
|
$this->query->leftJoin('categories as transaction_categories', 'transaction_categories.id', '=', 'category_transaction.category_id');
|
||||||
|
|
||||||
$this->fields[] = 'category_transaction_journal.category_id as transaction_journal_category_id';
|
$this->fields[] = 'category_transaction_journal.category_id as transaction_journal_category_id';
|
||||||
|
$this->fields[] = 'transaction_journal_categories.encrypted as transaction_journal_category_encrypted';
|
||||||
|
$this->fields[] = 'transaction_journal_categories.name as transaction_journal_category_name';
|
||||||
|
|
||||||
$this->fields[] = 'category_transaction.category_id as transaction_category_id';
|
$this->fields[] = 'category_transaction.category_id as transaction_category_id';
|
||||||
|
$this->fields[] = 'transaction_categories.encrypted as transaction_category_encrypted';
|
||||||
|
$this->fields[] = 'transaction_categories.name as transaction_category_name';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
private function joinOpposingTables()
|
private function joinOpposingTables()
|
||||||
{
|
{
|
||||||
if (!$this->joinedOpposing) {
|
if (!$this->joinedOpposing) {
|
||||||
|
@ -74,12 +74,8 @@ class Help implements HelpInterface
|
|||||||
$converter = new CommonMarkConverter();
|
$converter = new CommonMarkConverter();
|
||||||
$content = $converter->convertToHtml($content);
|
$content = $converter->convertToHtml($content);
|
||||||
}
|
}
|
||||||
if (strlen($content) === 0) {
|
|
||||||
Log::warning('Raw content length is zero.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,7 @@ use FireflyIII\Helpers\Collection\Balance;
|
|||||||
use FireflyIII\Helpers\Collection\BalanceEntry;
|
use FireflyIII\Helpers\Collection\BalanceEntry;
|
||||||
use FireflyIII\Helpers\Collection\BalanceHeader;
|
use FireflyIII\Helpers\Collection\BalanceHeader;
|
||||||
use FireflyIII\Helpers\Collection\BalanceLine;
|
use FireflyIII\Helpers\Collection\BalanceLine;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
@ -31,6 +30,7 @@ use Log;
|
|||||||
/**
|
/**
|
||||||
* Class BalanceReportHelper
|
* Class BalanceReportHelper
|
||||||
*
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // I can't really help it.
|
||||||
* @package FireflyIII\Helpers\Report
|
* @package FireflyIII\Helpers\Report
|
||||||
*/
|
*/
|
||||||
class BalanceReportHelper implements BalanceReportHelperInterface
|
class BalanceReportHelper implements BalanceReportHelperInterface
|
||||||
@ -63,17 +63,15 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
|||||||
Log::debug('Start of balance report');
|
Log::debug('Start of balance report');
|
||||||
$balance = new Balance;
|
$balance = new Balance;
|
||||||
$header = new BalanceHeader;
|
$header = new BalanceHeader;
|
||||||
$limitRepetitions = $this->budgetRepository->getAllBudgetLimitRepetitions($start, $end);
|
$budgetLimits = $this->budgetRepository->getAllBudgetLimits($start, $end);
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
Log::debug(sprintf('Add account %s to headers.', $account->name));
|
Log::debug(sprintf('Add account %s to headers.', $account->name));
|
||||||
$header->addAccount($account);
|
$header->addAccount($account);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var LimitRepetition $repetition */
|
/** @var BudgetLimit $budgetLimit */
|
||||||
foreach ($limitRepetitions as $repetition) {
|
foreach ($budgetLimits as $budgetLimit) {
|
||||||
$budget = $this->budgetRepository->find($repetition->budget_id);
|
$line = $this->createBalanceLine($budgetLimit, $accounts);
|
||||||
Log::debug(sprintf('Create balance line for budget #%d ("%s") and repetition #%d', $budget->id, $budget->name, $repetition->id));
|
|
||||||
$line = $this->createBalanceLine($budget, $repetition, $accounts);
|
|
||||||
$balance->addBalanceLine($line);
|
$balance->addBalanceLine($line);
|
||||||
}
|
}
|
||||||
Log::debug('Create rest of the things.');
|
Log::debug('Create rest of the things.');
|
||||||
@ -145,26 +143,23 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param BudgetLimit $budgetLimit
|
||||||
* @param LimitRepetition $repetition
|
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
*
|
*
|
||||||
* @return BalanceLine
|
* @return BalanceLine
|
||||||
*/
|
*/
|
||||||
private function createBalanceLine(Budget $budget, LimitRepetition $repetition, Collection $accounts): BalanceLine
|
private function createBalanceLine(BudgetLimit $budgetLimit, Collection $accounts): BalanceLine
|
||||||
{
|
{
|
||||||
$line = new BalanceLine;
|
$line = new BalanceLine;
|
||||||
$budget->amount = $repetition->amount;
|
$line->setBudget($budgetLimit->budget);
|
||||||
$line->setBudget($budget);
|
$line->setBudgetLimit($budgetLimit);
|
||||||
$line->setStartDate($repetition->startdate);
|
|
||||||
$line->setEndDate($repetition->enddate);
|
|
||||||
|
|
||||||
// loop accounts:
|
// loop accounts:
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$balanceEntry = new BalanceEntry;
|
$balanceEntry = new BalanceEntry;
|
||||||
$balanceEntry->setAccount($account);
|
$balanceEntry->setAccount($account);
|
||||||
$spent = $this->budgetRepository->spentInPeriod(
|
$spent = $this->budgetRepository->spentInPeriod(
|
||||||
new Collection([$budget]), new Collection([$account]), $repetition->startdate, $repetition->enddate
|
new Collection([$budgetLimit->budget]), new Collection([$account]), $budgetLimit->start_date, $budgetLimit->end_date
|
||||||
);
|
);
|
||||||
$balanceEntry->setSpent($spent);
|
$balanceEntry->setSpent($spent);
|
||||||
$line->addBalanceEntry($balanceEntry);
|
$line->addBalanceEntry($balanceEntry);
|
||||||
|
@ -18,7 +18,7 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
|
use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
|
||||||
use FireflyIII\Helpers\Collection\BudgetLine;
|
use FireflyIII\Helpers\Collection\BudgetLine;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
@ -56,13 +57,9 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
|||||||
|
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($set as $budget) {
|
foreach ($set as $budget) {
|
||||||
$repetitions = $budget->limitrepetitions()->before($end)->after($start)->get();
|
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
|
if ($budgetLimits->count() == 0) { // no budget limit(s) for this budget
|
||||||
// no repetition(s) for this budget:
|
$spent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);// spent for budget in time range
|
||||||
if ($repetitions->count() == 0) {
|
|
||||||
// spent for budget in time range:
|
|
||||||
$spent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);
|
|
||||||
|
|
||||||
if ($spent > 0) {
|
if ($spent > 0) {
|
||||||
$budgetLine = new BudgetLine;
|
$budgetLine = new BudgetLine;
|
||||||
$budgetLine->setBudget($budget)->setOverspent($spent);
|
$budgetLine->setBudget($budget)->setOverspent($spent);
|
||||||
@ -70,26 +67,20 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// one or more repetitions for budget:
|
/** @var BudgetLimit $budgetLimit */
|
||||||
/** @var LimitRepetition $repetition */
|
foreach ($budgetLimits as $budgetLimit) { // one or more repetitions for budget
|
||||||
foreach ($repetitions as $repetition) {
|
$data = $this->calculateExpenses($budget, $budgetLimit, $accounts);
|
||||||
$data = $this->calculateExpenses($budget, $repetition, $accounts);
|
|
||||||
|
|
||||||
$budgetLine = new BudgetLine;
|
$budgetLine = new BudgetLine;
|
||||||
$budgetLine->setBudget($budget)->setRepetition($repetition)
|
$budgetLine->setBudget($budget)->setBudgetLimit($budgetLimit)
|
||||||
->setLeft($data['left'])->setSpent($data['expenses'])->setOverspent($data['overspent'])
|
->setLeft($data['left'])->setSpent($data['expenses'])->setOverspent($data['overspent'])
|
||||||
->setBudgeted(strval($repetition->amount));
|
->setBudgeted(strval($budgetLimit->amount));
|
||||||
|
|
||||||
$object->addBudgeted(strval($repetition->amount))->addSpent($data['spent'])
|
$object->addBudgeted(strval($budgetLimit->amount))->addSpent($data['spent'])
|
||||||
->addLeft($data['left'])->addOverspent($data['overspent'])->addBudgetLine($budgetLine);
|
->addLeft($data['left'])->addOverspent($data['overspent'])->addBudgetLine($budgetLine);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
$noBudget = $this->repository->spentInPeriodWithoutBudget($accounts, $start, $end); // stuff outside of budgets
|
||||||
// stuff outside of budgets:
|
|
||||||
|
|
||||||
$noBudget = $this->repository->spentInPeriodWithoutBudget($accounts, $start, $end);
|
|
||||||
$budgetLine = new BudgetLine;
|
$budgetLine = new BudgetLine;
|
||||||
$budgetLine->setOverspent($noBudget)->setSpent($noBudget);
|
$budgetLine->setOverspent($noBudget)->setSpent($noBudget);
|
||||||
$object->addOverspent($noBudget)->addBudgetLine($budgetLine);
|
$object->addOverspent($noBudget)->addBudgetLine($budgetLine);
|
||||||
@ -129,18 +120,18 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param LimitRepetition $repetition
|
* @param BudgetLimit $budgetLimit
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function calculateExpenses(Budget $budget, LimitRepetition $repetition, Collection $accounts): array
|
private function calculateExpenses(Budget $budget, BudgetLimit $budgetLimit, Collection $accounts): array
|
||||||
{
|
{
|
||||||
$array = [];
|
$array = [];
|
||||||
$expenses = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $repetition->startdate, $repetition->enddate);
|
$expenses = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $budgetLimit->start_date, $budgetLimit->end_date);
|
||||||
$array['left'] = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? bcadd($repetition->amount, $expenses) : '0';
|
$array['left'] = bccomp(bcadd($budgetLimit->amount, $expenses), '0') === 1 ? bcadd($budgetLimit->amount, $expenses) : '0';
|
||||||
$array['spent'] = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? $expenses : '0';
|
$array['spent'] = bccomp(bcadd($budgetLimit->amount, $expenses), '0') === 1 ? $expenses : '0';
|
||||||
$array['overspent'] = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? '0' : bcadd($expenses, $repetition->amount);
|
$array['overspent'] = bccomp(bcadd($budgetLimit->amount, $expenses), '0') === 1 ? '0' : bcadd($expenses, $budgetLimit->amount);
|
||||||
$array['expenses'] = $expenses;
|
$array['expenses'] = $expenses;
|
||||||
|
|
||||||
return $array;
|
return $array;
|
||||||
|
@ -53,6 +53,8 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
* This method generates a full report for the given period on all
|
* This method generates a full report for the given period on all
|
||||||
* the users bills and their payments.
|
* the users bills and their payments.
|
||||||
*
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||||
|
*
|
||||||
* Excludes bills which have not had a payment on the mentioned accounts.
|
* Excludes bills which have not had a payment on the mentioned accounts.
|
||||||
*
|
*
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
@ -80,8 +82,6 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
$billLine->setMin(strval($bill->amount_min));
|
$billLine->setMin(strval($bill->amount_min));
|
||||||
$billLine->setMax(strval($bill->amount_max));
|
$billLine->setMax(strval($bill->amount_max));
|
||||||
$billLine->setHit(false);
|
$billLine->setHit(false);
|
||||||
// is hit in period?
|
|
||||||
|
|
||||||
$entry = $journals->filter(
|
$entry = $journals->filter(
|
||||||
function (Transaction $transaction) use ($bill) {
|
function (Transaction $transaction) use ($bill) {
|
||||||
return $transaction->bill_id === $bill->id;
|
return $transaction->bill_id === $bill->id;
|
||||||
@ -94,14 +94,10 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
$billLine->setLastHitDate($first->date);
|
$billLine->setLastHitDate($first->date);
|
||||||
$billLine->setHit(true);
|
$billLine->setHit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bill is active, or bill is hit:
|
|
||||||
if ($billLine->isActive() || $billLine->isHit()) {
|
if ($billLine->isActive() || $billLine->isHit()) {
|
||||||
$collection->addBill($billLine);
|
$collection->addBill($billLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do some extra filtering.
|
|
||||||
$collection->filterBills();
|
$collection->filterBills();
|
||||||
|
|
||||||
return $collection;
|
return $collection;
|
||||||
|
@ -17,7 +17,6 @@ use Amount;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use ExpandedForm;
|
use ExpandedForm;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Requests\AccountFormRequest;
|
use FireflyIII\Http\Requests\AccountFormRequest;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
@ -28,8 +27,8 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
|||||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
|
||||||
use Log;
|
use Log;
|
||||||
use Navigation;
|
use Navigation;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
@ -117,18 +116,19 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param ARI $repository
|
* @param ARI $repository
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function destroy(ARI $repository, Account $account)
|
public function destroy(Request $request, ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
$type = $account->accountType->type;
|
$type = $account->accountType->type;
|
||||||
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
$typeName = config('firefly.shortNamesByFullName.' . $type);
|
||||||
$name = $account->name;
|
$name = $account->name;
|
||||||
$accountId = $account->id;
|
$accountId = $account->id;
|
||||||
$moveTo = $repository->find(intval(Input::get('move_account_before_delete')));
|
$moveTo = $repository->find(intval($request->get('move_account_before_delete')));
|
||||||
|
|
||||||
$repository->destroy($account, $moveTo);
|
$repository->destroy($account, $moveTo);
|
||||||
|
|
||||||
@ -228,12 +228,13 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param JournalCollectorInterface $collector
|
* @param JournalCollectorInterface $collector
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return View
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||||
*/
|
*/
|
||||||
public function show(JournalCollectorInterface $collector, Account $account)
|
public function show(Request $request, JournalCollectorInterface $collector, Account $account)
|
||||||
{
|
{
|
||||||
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
||||||
return $this->redirectToOriginalAccount($account);
|
return $this->redirectToOriginalAccount($account);
|
||||||
@ -244,7 +245,7 @@ class AccountController extends Controller
|
|||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$chartUri = route('chart.account.single', [$account->id]);
|
$chartUri = route('chart.account.single', [$account->id]);
|
||||||
|
|
||||||
@ -260,20 +261,22 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param ARI $repository
|
* @param ARI $repository
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function showAll(AccountRepositoryInterface $repository, Account $account)
|
public function showAll(Request $request, AccountRepositoryInterface $repository, Account $account)
|
||||||
{
|
{
|
||||||
$subTitle = sprintf('%s (%s)', $account->name, strtolower(trans('firefly.everything')));
|
$subTitle = sprintf('%s (%s)', $account->name, strtolower(trans('firefly.everything')));
|
||||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$chartUri = route('chart.account.all', [$account->id]);
|
$chartUri = route('chart.account.all', [$account->id]);
|
||||||
|
|
||||||
// replace with journal collector:
|
// replace with journal collector:
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page);
|
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page);
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('accounts/show/' . $account->id . '/all');
|
$journals->setPath('accounts/show/' . $account->id . '/all');
|
||||||
@ -287,24 +290,26 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param string $date
|
* @param string $date
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function showByDate(Account $account, string $date)
|
public function showByDate(Request $request, Account $account, string $date)
|
||||||
{
|
{
|
||||||
$carbon = new Carbon($date);
|
$carbon = new Carbon($date);
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = Navigation::startOfPeriod($carbon, $range);
|
$start = Navigation::startOfPeriod($carbon, $range);
|
||||||
$end = Navigation::endOfPeriod($carbon, $range);
|
$end = Navigation::endOfPeriod($carbon, $range);
|
||||||
$subTitle = $account->name . ' (' . Navigation::periodShow($start, $range) . ')';
|
$subTitle = $account->name . ' (' . Navigation::periodShow($start, $range) . ')';
|
||||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$chartUri = route('chart.account.period', [$account->id, $carbon->format('Y-m-d')]);
|
$chartUri = route('chart.account.period', [$account->id, $carbon->format('Y-m-d')]);
|
||||||
|
|
||||||
// replace with journal collector:
|
// replace with journal collector:
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
|
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('accounts/show/' . $account->id . '/' . $date);
|
$journals->setPath('accounts/show/' . $account->id . '/' . $date);
|
||||||
@ -335,7 +340,7 @@ class AccountController extends Controller
|
|||||||
Preferences::set('frontPageAccounts', $frontPage);
|
Preferences::set('frontPageAccounts', $frontPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
// set value so create routine will not overwrite URL:
|
// set value so create routine will not overwrite URL:
|
||||||
Session::put('accounts.create.fromStore', true);
|
Session::put('accounts.create.fromStore', true);
|
||||||
|
|
||||||
@ -361,7 +366,7 @@ class AccountController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('accounts.edit.fromUpdate', true);
|
Session::put('accounts.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
@ -59,22 +59,12 @@ class ConfigurationController extends Controller
|
|||||||
// all available configuration and their default value in case
|
// all available configuration and their default value in case
|
||||||
// they don't exist yet.
|
// they don't exist yet.
|
||||||
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
|
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
|
||||||
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'))->data;
|
|
||||||
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
|
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
|
||||||
$siteOwner = env('SITE_OWNER');
|
$siteOwner = env('SITE_OWNER');
|
||||||
|
|
||||||
// email settings:
|
|
||||||
$sendErrorMessage = [
|
|
||||||
'mail_for_lockout' => FireflyConfig::get('mail_for_lockout', config('firefly.configuration.mail_for_lockout'))->data,
|
|
||||||
'mail_for_blocked_domain' => FireflyConfig::get('mail_for_blocked_domain', config('firefly.configuration.mail_for_blocked_domain'))->data,
|
|
||||||
'mail_for_blocked_email' => FireflyConfig::get('mail_for_blocked_email', config('firefly.configuration.mail_for_blocked_email'))->data,
|
|
||||||
'mail_for_bad_login' => FireflyConfig::get('mail_for_bad_login', config('firefly.configuration.mail_for_bad_login'))->data,
|
|
||||||
'mail_for_blocked_login' => FireflyConfig::get('mail_for_blocked_login', config('firefly.configuration.mail_for_blocked_login'))->data,
|
|
||||||
];
|
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'admin.configuration.index',
|
'admin.configuration.index',
|
||||||
compact('subTitle', 'subTitleIcon', 'singleUserMode', 'mustConfirmAccount', 'isDemoSite', 'sendErrorMessage', 'siteOwner')
|
compact('subTitle', 'subTitleIcon', 'singleUserMode', 'isDemoSite', 'siteOwner')
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -91,16 +81,8 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
// store config values
|
// store config values
|
||||||
FireflyConfig::set('single_user_mode', $data['single_user_mode']);
|
FireflyConfig::set('single_user_mode', $data['single_user_mode']);
|
||||||
FireflyConfig::set('must_confirm_account', $data['must_confirm_account']);
|
|
||||||
FireflyConfig::set('is_demo_site', $data['is_demo_site']);
|
FireflyConfig::set('is_demo_site', $data['is_demo_site']);
|
||||||
|
|
||||||
// email settings
|
|
||||||
FireflyConfig::set('mail_for_lockout', $data['mail_for_lockout']);
|
|
||||||
FireflyConfig::set('mail_for_blocked_domain', $data['mail_for_blocked_domain']);
|
|
||||||
FireflyConfig::set('mail_for_blocked_email', $data['mail_for_blocked_email']);
|
|
||||||
FireflyConfig::set('mail_for_bad_login', $data['mail_for_bad_login']);
|
|
||||||
FireflyConfig::set('mail_for_blocked_login', $data['mail_for_blocked_login']);
|
|
||||||
|
|
||||||
// flash message
|
// flash message
|
||||||
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* DomainController.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\Http\Controllers\Admin;
|
|
||||||
|
|
||||||
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
|
||||||
use FireflyIII\Support\Facades\FireflyConfig;
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Session;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class DomainController
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Http\Controllers\Admin
|
|
||||||
*/
|
|
||||||
class DomainController extends Controller
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function domains()
|
|
||||||
{
|
|
||||||
|
|
||||||
$title = strval(trans('firefly.administration'));
|
|
||||||
$mainTitleIcon = 'fa-hand-spock-o';
|
|
||||||
$subTitle = strval(trans('firefly.blocked_domains'));
|
|
||||||
$subTitleIcon = 'fa-exclamation-circle';
|
|
||||||
$domains = FireflyConfig::get('blocked-domains', [])->data;
|
|
||||||
|
|
||||||
// known domains
|
|
||||||
$knownDomains = $this->getKnownDomains();
|
|
||||||
|
|
||||||
return view('admin.domains.index', compact('title', 'mainTitleIcon', 'knownDomains', 'subTitle', 'subTitleIcon', 'domains'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
||||||
*/
|
|
||||||
public function manual(Request $request)
|
|
||||||
{
|
|
||||||
if (strlen($request->get('domain')) === 0) {
|
|
||||||
Session::flash('error', trans('firefly.no_domain_filled_in'));
|
|
||||||
|
|
||||||
return redirect(route('admin.users.domains'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$domain = strtolower($request->get('domain'));
|
|
||||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
|
||||||
|
|
||||||
if (in_array($domain, $blocked)) {
|
|
||||||
Session::flash('error', trans('firefly.domain_already_blocked', ['domain' => $domain]));
|
|
||||||
|
|
||||||
return redirect(route('admin.users.domains'));
|
|
||||||
}
|
|
||||||
$blocked[] = $domain;
|
|
||||||
FireflyConfig::set('blocked-domains', $blocked);
|
|
||||||
|
|
||||||
Session::flash('success', trans('firefly.domain_is_now_blocked', ['domain' => $domain]));
|
|
||||||
|
|
||||||
return redirect(route('admin.users.domains'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $domain
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
||||||
*/
|
|
||||||
public function toggleDomain(string $domain)
|
|
||||||
{
|
|
||||||
$domain = strtolower($domain);
|
|
||||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
|
||||||
|
|
||||||
if (in_array($domain, $blocked)) {
|
|
||||||
$key = array_search($domain, $blocked);
|
|
||||||
unset($blocked[$key]);
|
|
||||||
sort($blocked);
|
|
||||||
|
|
||||||
FireflyConfig::set('blocked-domains', $blocked);
|
|
||||||
Session::flash('message', trans('firefly.domain_now_unblocked', ['domain' => $domain]));
|
|
||||||
|
|
||||||
|
|
||||||
return redirect(route('admin.users.domains'));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$blocked[] = $domain;
|
|
||||||
|
|
||||||
FireflyConfig::set('blocked-domains', $blocked);
|
|
||||||
Session::flash('message', trans('firefly.domain_now_blocked', ['domain' => $domain]));
|
|
||||||
|
|
||||||
return redirect(route('admin.users.domains'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getKnownDomains(): array
|
|
||||||
{
|
|
||||||
/** @var UserRepositoryInterface $repository */
|
|
||||||
$repository = app(UserRepositoryInterface::class);
|
|
||||||
$users = $repository->all();
|
|
||||||
$set = [];
|
|
||||||
$filtered = [];
|
|
||||||
/** @var User $user */
|
|
||||||
foreach ($users as $user) {
|
|
||||||
$email = $user->email;
|
|
||||||
$parts = explode('@', $email);
|
|
||||||
$set[] = strtolower($parts[1]);
|
|
||||||
}
|
|
||||||
$set = array_unique($set);
|
|
||||||
// filter for already banned domains:
|
|
||||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
|
||||||
|
|
||||||
foreach ($set as $domain) {
|
|
||||||
// in the block array? ignore it.
|
|
||||||
if (!in_array($domain, $blocked)) {
|
|
||||||
$filtered[] = $domain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $filtered;
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,6 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Controllers\Admin;
|
namespace FireflyIII\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
|
||||||
use FireflyConfig;
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Http\Requests\UserFormRequest;
|
use FireflyIII\Http\Requests\UserFormRequest;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
@ -83,27 +82,17 @@ class UserController extends Controller
|
|||||||
{
|
{
|
||||||
$subTitle = strval(trans('firefly.user_administration'));
|
$subTitle = strval(trans('firefly.user_administration'));
|
||||||
$subTitleIcon = 'fa-users';
|
$subTitleIcon = 'fa-users';
|
||||||
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'))->data;
|
|
||||||
$users = $repository->all();
|
$users = $repository->all();
|
||||||
|
|
||||||
// add meta stuff.
|
// add meta stuff.
|
||||||
$users->each(
|
$users->each(
|
||||||
function (User $user) use ($mustConfirmAccount) {
|
function (User $user) {
|
||||||
$list = ['user_confirmed', 'twoFactorAuthEnabled', 'twoFactorAuthSecret', 'registration_ip_address', 'confirmation_ip_address'];
|
$list = ['twoFactorAuthEnabled', 'twoFactorAuthSecret'];
|
||||||
$preferences = Preferences::getArrayForUser($user, $list);
|
$preferences = Preferences::getArrayForUser($user, $list);
|
||||||
|
|
||||||
$user->activated = true;
|
|
||||||
if (!($preferences['user_confirmed'] === true) && $mustConfirmAccount === true) {
|
|
||||||
$user->activated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$user->isAdmin = $user->hasRole('owner');
|
$user->isAdmin = $user->hasRole('owner');
|
||||||
$is2faEnabled = $preferences['twoFactorAuthEnabled'] === true;
|
$is2faEnabled = $preferences['twoFactorAuthEnabled'] === true;
|
||||||
$has2faSecret = !is_null($preferences['twoFactorAuthSecret']);
|
$has2faSecret = !is_null($preferences['twoFactorAuthSecret']);
|
||||||
$user->has2FA = false;
|
$user->has2FA = ($is2faEnabled && $has2faSecret) ? true : false;
|
||||||
if ($is2faEnabled && $has2faSecret) {
|
|
||||||
$user->has2FA = true;
|
|
||||||
}
|
|
||||||
$user->prefs = $preferences;
|
$user->prefs = $preferences;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -125,37 +114,12 @@ class UserController extends Controller
|
|||||||
$mainTitleIcon = 'fa-hand-spock-o';
|
$mainTitleIcon = 'fa-hand-spock-o';
|
||||||
$subTitle = strval(trans('firefly.single_user_administration', ['email' => $user->email]));
|
$subTitle = strval(trans('firefly.single_user_administration', ['email' => $user->email]));
|
||||||
$subTitleIcon = 'fa-user';
|
$subTitleIcon = 'fa-user';
|
||||||
|
|
||||||
// get IP info:
|
|
||||||
$defaultIp = '0.0.0.0';
|
|
||||||
$regPref = Preferences::getForUser($user, 'registration_ip_address');
|
|
||||||
$registration = $defaultIp;
|
|
||||||
$conPref = Preferences::getForUser($user, 'confirmation_ip_address');
|
|
||||||
$confirmation = $defaultIp;
|
|
||||||
if (!is_null($regPref)) {
|
|
||||||
$registration = $regPref->data;
|
|
||||||
}
|
|
||||||
if (!is_null($conPref)) {
|
|
||||||
$confirmation = $conPref->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
$registrationHost = '';
|
|
||||||
$confirmationHost = '';
|
|
||||||
|
|
||||||
if ($registration != $defaultIp) {
|
|
||||||
$registrationHost = gethostbyaddr($registration);
|
|
||||||
}
|
|
||||||
if ($confirmation != $defaultIp) {
|
|
||||||
$confirmationHost = gethostbyaddr($confirmation);
|
|
||||||
}
|
|
||||||
|
|
||||||
$information = $repository->getUserData($user);
|
$information = $repository->getUserData($user);
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'admin.users.show',
|
'admin.users.show',
|
||||||
compact(
|
compact(
|
||||||
'title', 'mainTitleIcon', 'subTitle', 'subTitleIcon', 'information',
|
'title', 'mainTitleIcon', 'subTitle', 'subTitleIcon', 'information', 'user'
|
||||||
'user', 'registration', 'confirmation', 'registrationHost', 'confirmationHost'
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,24 +13,22 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
use Crypt;
|
|
||||||
use File;
|
use File;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Http\Requests\AttachmentFormRequest;
|
use FireflyIII\Http\Requests\AttachmentFormRequest;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||||
use Input;
|
|
||||||
use Log;
|
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
use Session;
|
use Session;
|
||||||
use Storage;
|
|
||||||
use URL;
|
use URL;
|
||||||
use View;
|
use View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AttachmentController
|
* Class AttachmentController
|
||||||
*
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it's 13.
|
||||||
|
*
|
||||||
* @package FireflyIII\Http\Controllers
|
* @package FireflyIII\Http\Controllers
|
||||||
*/
|
*/
|
||||||
class AttachmentController extends Controller
|
class AttachmentController extends Controller
|
||||||
@ -57,7 +55,7 @@ class AttachmentController extends Controller
|
|||||||
/**
|
/**
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
*
|
*
|
||||||
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function delete(Attachment $attachment)
|
public function delete(Attachment $attachment)
|
||||||
{
|
{
|
||||||
@ -101,9 +99,6 @@ class AttachmentController extends Controller
|
|||||||
$content = $repository->getContent($attachment);
|
$content = $repository->getContent($attachment);
|
||||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||||
|
|
||||||
|
|
||||||
Log::debug('Send file to user', ['file' => $quoted, 'size' => strlen($content)]);
|
|
||||||
|
|
||||||
return response($content, 200)
|
return response($content, 200)
|
||||||
->header('Content-Description', 'File Transfer')
|
->header('Content-Description', 'File Transfer')
|
||||||
->header('Content-Type', 'application/octet-stream')
|
->header('Content-Type', 'application/octet-stream')
|
||||||
@ -115,7 +110,6 @@ class AttachmentController extends Controller
|
|||||||
->header('Pragma', 'public')
|
->header('Pragma', 'public')
|
||||||
->header('Content-Length', strlen($content));
|
->header('Content-Length', strlen($content));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
|
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +141,6 @@ class AttachmentController extends Controller
|
|||||||
{
|
{
|
||||||
$image = 'images/page_green.png';
|
$image = 'images/page_green.png';
|
||||||
|
|
||||||
|
|
||||||
if ($attachment->mime == 'application/pdf') {
|
if ($attachment->mime == 'application/pdf') {
|
||||||
$image = 'images/page_white_acrobat.png';
|
$image = 'images/page_white_acrobat.png';
|
||||||
}
|
}
|
||||||
@ -174,7 +167,7 @@ class AttachmentController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.attachment_updated', ['name' => $attachment->filename])));
|
Session::flash('success', strval(trans('firefly.attachment_updated', ['name' => $attachment->filename])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('attachments.edit.fromUpdate', true);
|
Session::put('attachments.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ConfirmationController.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\Http\Controllers\Auth;
|
|
||||||
|
|
||||||
use FireflyIII\Events\ConfirmedUser;
|
|
||||||
use FireflyIII\Events\ResentConfirmation;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Preferences;
|
|
||||||
use Session;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConfirmationController
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Http\Controllers\Auth
|
|
||||||
*/
|
|
||||||
class ConfirmationController extends Controller
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function confirmationError()
|
|
||||||
{
|
|
||||||
return view('auth.confirmation.error');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param string $code
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public function doConfirmation(Request $request, string $code)
|
|
||||||
{
|
|
||||||
// check user_confirmed_last_mail
|
|
||||||
|
|
||||||
$database = Preferences::get('user_confirmed_code')->data;
|
|
||||||
$time = Preferences::get('user_confirmed_last_mail', 0)->data;
|
|
||||||
$now = time();
|
|
||||||
$maxDiff = config('firefly.confirmation_age');
|
|
||||||
|
|
||||||
if ($database === $code && ($now - $time <= $maxDiff)) {
|
|
||||||
|
|
||||||
// trigger user registration event:
|
|
||||||
event(new ConfirmedUser(auth()->user(), $request->ip()));
|
|
||||||
|
|
||||||
Preferences::setForUser(auth()->user(), 'user_confirmed', true);
|
|
||||||
Preferences::setForUser(auth()->user(), 'user_confirmed_confirmed', time());
|
|
||||||
Session::flash('success', strval(trans('firefly.account_is_confirmed')));
|
|
||||||
|
|
||||||
return redirect(route('home'));
|
|
||||||
}
|
|
||||||
throw new FireflyException(trans('firefly.invalid_activation_code'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function resendConfirmation(Request $request)
|
|
||||||
{
|
|
||||||
$time = Preferences::get('user_confirmed_last_mail', 0)->data;
|
|
||||||
$now = time();
|
|
||||||
$maxDiff = config('firefly.resend_confirmation');
|
|
||||||
$owner = env('SITE_OWNER', 'mail@example.com');
|
|
||||||
$view = 'auth.confirmation.no-resent';
|
|
||||||
if ($now - $time > $maxDiff) {
|
|
||||||
event(new ResentConfirmation(auth()->user(), $request->ip()));
|
|
||||||
$view = 'auth.confirmation.resent';
|
|
||||||
}
|
|
||||||
|
|
||||||
return view($view, ['owner' => $owner]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -14,9 +14,6 @@ namespace FireflyIII\Http\Controllers\Auth;
|
|||||||
|
|
||||||
use Config;
|
use Config;
|
||||||
use FireflyConfig;
|
use FireflyConfig;
|
||||||
use FireflyIII\Events\BlockedBadLogin;
|
|
||||||
use FireflyIII\Events\BlockedUserLogin;
|
|
||||||
use FireflyIII\Events\LockedOutUser;
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
@ -64,8 +61,6 @@ class LoginController extends Controller
|
|||||||
if ($lockedOut) {
|
if ($lockedOut) {
|
||||||
$this->fireLockoutEvent($request);
|
$this->fireLockoutEvent($request);
|
||||||
|
|
||||||
event(new LockedOutUser($request->get('email'), $request->ip()));
|
|
||||||
|
|
||||||
return $this->sendLockoutResponse($request);
|
return $this->sendLockoutResponse($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,25 +71,8 @@ class LoginController extends Controller
|
|||||||
return $this->sendLoginResponse($request);
|
return $this->sendLoginResponse($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if user is blocked:
|
$errorMessage = $this->getBlockedError($credentials['email']);
|
||||||
$errorMessage = '';
|
|
||||||
/** @var User $foundUser */
|
|
||||||
$foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first();
|
|
||||||
if (!is_null($foundUser)) {
|
|
||||||
// user exists, but is blocked:
|
|
||||||
$code = strlen(strval($foundUser->blocked_code)) > 0 ? $foundUser->blocked_code : 'general_blocked';
|
|
||||||
$errorMessage = strval(trans('firefly.' . $code . '_error', ['email' => $credentials['email']]));
|
|
||||||
event(new BlockedUserLogin($foundUser, $request->ip()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// simply a bad login.
|
|
||||||
if (is_null($foundUser)) {
|
|
||||||
event(new BlockedBadLogin($credentials['email'], $request->ip()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the login attempt was unsuccessful we will increment the number of attempts
|
|
||||||
// to login and redirect the user back to the login form. Of course, when this
|
|
||||||
// user surpasses their maximum number of attempts they will get locked out.
|
|
||||||
if (!$lockedOut) {
|
if (!$lockedOut) {
|
||||||
$this->incrementLoginAttempts($request);
|
$this->incrementLoginAttempts($request);
|
||||||
}
|
}
|
||||||
@ -159,4 +137,24 @@ class LoginController extends Controller
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $email
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getBlockedError(string $email): string
|
||||||
|
{
|
||||||
|
// check if user is blocked:
|
||||||
|
$errorMessage = '';
|
||||||
|
/** @var User $foundUser */
|
||||||
|
$foundUser = User::where('email', $email)->where('blocked', 1)->first();
|
||||||
|
if (!is_null($foundUser)) {
|
||||||
|
// user exists, but is blocked:
|
||||||
|
$code = strlen(strval($foundUser->blocked_code)) > 0 ? $foundUser->blocked_code : 'general_blocked';
|
||||||
|
$errorMessage = strval(trans('firefly.' . $code . '_error', ['email' => $email]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errorMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ class PasswordController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reset link to the given user.
|
* Send a reset link to the given user.
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 7 but ok
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
*
|
*
|
||||||
|
@ -15,14 +15,11 @@ namespace FireflyIII\Http\Controllers\Auth;
|
|||||||
use Auth;
|
use Auth;
|
||||||
use Config;
|
use Config;
|
||||||
use FireflyConfig;
|
use FireflyConfig;
|
||||||
use FireflyIII\Events\BlockedUseOfDomain;
|
|
||||||
use FireflyIII\Events\BlockedUseOfEmail;
|
|
||||||
use FireflyIII\Events\RegisteredUser;
|
use FireflyIII\Events\RegisteredUser;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Log;
|
|
||||||
use Session;
|
use Session;
|
||||||
use Validator;
|
use Validator;
|
||||||
|
|
||||||
@ -75,30 +72,6 @@ class RegisterController extends Controller
|
|||||||
$this->throwValidationException($request, $validator);
|
$this->throwValidationException($request, $validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $request->all();
|
|
||||||
$data['password'] = bcrypt($data['password']);
|
|
||||||
|
|
||||||
// is user email domain blocked?
|
|
||||||
if ($this->isBlockedDomain($data['email'])) {
|
|
||||||
$validator->getMessageBag()->add('email', (string)trans('validation.invalid_domain'));
|
|
||||||
|
|
||||||
event(new BlockedUseOfDomain($data['email'], $request->ip()));
|
|
||||||
$this->throwValidationException($request, $validator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// is user a deleted user?
|
|
||||||
$hash = hash('sha256', $data['email']);
|
|
||||||
$configuration = FireflyConfig::get('deleted_users', []);
|
|
||||||
$set = $configuration->data;
|
|
||||||
Log::debug(sprintf('Hash of email is %s', $hash));
|
|
||||||
Log::debug('Hashes of deleted users: ', $set);
|
|
||||||
if (in_array($hash, $set)) {
|
|
||||||
$validator->getMessageBag()->add('email', (string)trans('validation.deleted_user'));
|
|
||||||
event(new BlockedUseOfEmail($data['email'], $request->ip()));
|
|
||||||
$this->throwValidationException($request, $validator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$user = $this->create($request->all());
|
$user = $this->create($request->all());
|
||||||
|
|
||||||
// trigger user registration event:
|
// trigger user registration event:
|
||||||
@ -126,9 +99,6 @@ class RegisterController extends Controller
|
|||||||
// is demo site?
|
// is demo site?
|
||||||
$isDemoSite = FireflyConfig::get('is_demo_site', Config::get('firefly.configuration.is_demo_site'))->data;
|
$isDemoSite = FireflyConfig::get('is_demo_site', Config::get('firefly.configuration.is_demo_site'))->data;
|
||||||
|
|
||||||
// activate account?
|
|
||||||
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', Config::get('firefly.configuration.must_confirm_account'))->data;
|
|
||||||
|
|
||||||
// is allowed to?
|
// is allowed to?
|
||||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||||
$userCount = User::count();
|
$userCount = User::count();
|
||||||
@ -140,7 +110,7 @@ class RegisterController extends Controller
|
|||||||
|
|
||||||
$email = $request->old('email');
|
$email = $request->old('email');
|
||||||
|
|
||||||
return view('auth.register', compact('isDemoSite', 'email', 'mustConfirmAccount'));
|
return view('auth.register', compact('isDemoSite', 'email'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -176,30 +146,4 @@ class RegisterController extends Controller
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getBlockedDomains()
|
|
||||||
{
|
|
||||||
return FireflyConfig::get('blocked-domains', [])->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $email
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function isBlockedDomain(string $email)
|
|
||||||
{
|
|
||||||
$parts = explode('@', $email);
|
|
||||||
$blocked = $this->getBlockedDomains();
|
|
||||||
|
|
||||||
if (isset($parts[1]) && in_array($parts[1], $blocked)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ class TwoFactorController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TokenFormRequest $request
|
* @param TokenFormRequest $request
|
||||||
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter) // it's unused but the class does some validation.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -14,13 +14,13 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Requests\BillFormRequest;
|
use FireflyIII\Http\Requests\BillFormRequest;
|
||||||
use FireflyIII\Models\Bill;
|
use FireflyIII\Models\Bill;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
use URL;
|
use URL;
|
||||||
@ -197,24 +197,27 @@ class BillController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param BillRepositoryInterface $repository
|
* @param BillRepositoryInterface $repository
|
||||||
* @param Bill $bill
|
* @param Bill $bill
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function show(BillRepositoryInterface $repository, Bill $bill)
|
public function show(Request $request, BillRepositoryInterface $repository, Bill $bill)
|
||||||
{
|
{
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
$date = session('start');
|
$date = session('start');
|
||||||
$year = $date->year;
|
$year = $date->year;
|
||||||
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$yearAverage = $repository->getYearAverage($bill, $date);
|
$yearAverage = $repository->getYearAverage($bill, $date);
|
||||||
$overallAverage = $repository->getOverallAverage($bill);
|
$overallAverage = $repository->getOverallAverage($bill);
|
||||||
|
|
||||||
// use collector:
|
// use collector:
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector->setAllAssetAccounts()->setBills(new Collection([$bill]))->setPage($page)->setLimit($pageSize);
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
$collector->setAllAssetAccounts()->setBills(new Collection([$bill]))->setLimit($pageSize)->setPage($page)->withBudgetInformation()
|
||||||
|
->withCategoryInformation();
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('/bills/show/' . $bill->id);
|
$journals->setPath('/bills/show/' . $bill->id);
|
||||||
|
|
||||||
@ -238,7 +241,7 @@ class BillController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.stored_new_bill', ['name' => e($bill->name)])));
|
Session::flash('success', strval(trans('firefly.stored_new_bill', ['name' => e($bill->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
// set value so create routine will not overwrite URL:
|
// set value so create routine will not overwrite URL:
|
||||||
Session::put('bills.create.fromStore', true);
|
Session::put('bills.create.fromStore', true);
|
||||||
|
|
||||||
@ -265,7 +268,7 @@ class BillController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_bill', ['name' => e($bill->name)])));
|
Session::flash('success', strval(trans('firefly.updated_bill', ['name' => e($bill->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('bills.edit.fromUpdate', true);
|
Session::put('bills.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
@ -16,16 +16,16 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
use Amount;
|
use Amount;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Requests\BudgetFormRequest;
|
use FireflyIII\Http\Requests\BudgetFormRequest;
|
||||||
use FireflyIII\Http\Requests\BudgetIncomeRequest;
|
use FireflyIII\Http\Requests\BudgetIncomeRequest;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
use Session;
|
use Session;
|
||||||
@ -64,26 +64,26 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function amount(BudgetRepositoryInterface $repository, Budget $budget)
|
public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget)
|
||||||
{
|
{
|
||||||
$amount = intval(Input::get('amount'));
|
$amount = intval($request->get('amount'));
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = session('start', Carbon::now()->startOfMonth());
|
$start = session('start', Carbon::now()->startOfMonth());
|
||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = session('end', Carbon::now()->endOfMonth());
|
$end = session('end', Carbon::now()->endOfMonth());
|
||||||
$viewRange = Preferences::get('viewRange', '1M')->data;
|
$budgetLimit = $repository->updateLimitAmount($budget, $start, $end, $amount);
|
||||||
$limitRepetition = $repository->updateLimitAmount($budget, $start, $end, $viewRange, $amount);
|
|
||||||
if ($amount == 0) {
|
if ($amount == 0) {
|
||||||
$limitRepetition = null;
|
$budgetLimit = null;
|
||||||
}
|
}
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0, 'amount' => $amount]);
|
return Response::json(['name' => $budget->name, 'limit' => $budgetLimit ? $budgetLimit->id : 0, 'amount' => $amount]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,20 +189,22 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
return view(
|
return view(
|
||||||
'budgets.index',
|
'budgets.index',
|
||||||
compact('available', 'periodStart', 'periodEnd', 'budgetInformation', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
|
compact('available', 'periodStart', 'periodEnd', 'budgetInformation', 'inactive', 'budgets', 'spent', 'budgeted')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function noBudget()
|
public function noBudget(Request $request)
|
||||||
{
|
{
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = session('start', Carbon::now()->startOfMonth());
|
$start = session('start', Carbon::now()->startOfMonth());
|
||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = session('end', Carbon::now()->endOfMonth());
|
$end = session('end', Carbon::now()->endOfMonth());
|
||||||
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.without_budget_between',
|
'firefly.without_budget_between',
|
||||||
@ -210,7 +212,8 @@ class BudgetController extends Controller
|
|||||||
);
|
);
|
||||||
|
|
||||||
// collector
|
// collector
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutBudget();
|
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutBudget();
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('/budgets/list/noBudget');
|
$journals->setPath('/budgets/list/noBudget');
|
||||||
@ -235,35 +238,37 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param AccountRepositoryInterface $accountRepository
|
* @param AccountRepositoryInterface $accountRepository
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function show(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Budget $budget)
|
public function show(Request $request, BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Budget $budget)
|
||||||
{
|
{
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = session('first', Carbon::create()->startOfYear());
|
$start = session('first', Carbon::create()->startOfYear());
|
||||||
$end = new Carbon;
|
$end = new Carbon;
|
||||||
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||||
$repetition = null;
|
$repetition = null;
|
||||||
// collector:
|
// collector:
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page);
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page)->withCategoryInformation();
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('/budgets/show/' . $budget->id);
|
$journals->setPath('/budgets/show/' . $budget->id);
|
||||||
|
|
||||||
|
|
||||||
$set = $budget->limitrepetitions()->orderBy('startdate', 'DESC')->get();
|
$set = $repository->getBudgetLimits($budget, $start, $end);
|
||||||
$subTitle = e($budget->name);
|
$subTitle = e($budget->name);
|
||||||
$limits = new Collection();
|
$limits = new Collection();
|
||||||
|
|
||||||
/** @var LimitRepetition $entry */
|
/** @var BudgetLimit $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$entry->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $entry->startdate, $entry->enddate);
|
$entry->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $entry->start_date, $entry->end_date);
|
||||||
$limits->push($entry);
|
$limits->push($entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,15 +276,16 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param LimitRepetition $repetition
|
* @param BudgetLimit $budgetLimit
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function showByRepetition(Budget $budget, LimitRepetition $repetition)
|
public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit)
|
||||||
{
|
{
|
||||||
if ($repetition->budgetLimit->budget->id != $budget->id) {
|
if ($budgetLimit->budget->id != $budget->id) {
|
||||||
throw new FireflyException('This budget limit is not part of this budget.');
|
throw new FireflyException('This budget limit is not part of this budget.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,27 +293,30 @@ class BudgetController extends Controller
|
|||||||
$repository = app(BudgetRepositoryInterface::class);
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
/** @var AccountRepositoryInterface $accountRepository */
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
$accountRepository = app(AccountRepositoryInterface::class);
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
$start = $repetition->startdate;
|
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
|
||||||
$end = $repetition->enddate;
|
|
||||||
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
|
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]
|
'firefly.budget_in_period', [
|
||||||
|
'name' => $budget->name,
|
||||||
|
'start' => $budgetLimit->start_date->formatLocalized($this->monthAndDayFormat),
|
||||||
|
'end' => $budgetLimit->end_date->formatLocalized($this->monthAndDayFormat),
|
||||||
|
]
|
||||||
);
|
);
|
||||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||||
|
|
||||||
|
|
||||||
// collector:
|
// collector:
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page);
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($budgetLimit->start_date, $budgetLimit->end_date)
|
||||||
|
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withCategoryInformation();
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id);
|
$journals->setPath('/budgets/show/' . $budget->id . '/' . $budgetLimit->id);
|
||||||
|
|
||||||
|
|
||||||
$repetition->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $repetition->startdate, $repetition->enddate);
|
$budgetLimit->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $budgetLimit->start_date, $budgetLimit->end_date);
|
||||||
$limits = new Collection([$repetition]);
|
$limits = new Collection([$budgetLimit]);
|
||||||
|
|
||||||
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
|
return view('budgets.show', compact('limits', 'budget', 'budgetLimit', 'journals', 'subTitle'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +334,7 @@ class BudgetController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.stored_new_budget', ['name' => e($budget->name)])));
|
Session::flash('success', strval(trans('firefly.stored_new_budget', ['name' => e($budget->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
// set value so create routine will not overwrite URL:
|
// set value so create routine will not overwrite URL:
|
||||||
Session::put('budgets.create.fromStore', true);
|
Session::put('budgets.create.fromStore', true);
|
||||||
|
|
||||||
@ -352,7 +361,7 @@ class BudgetController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_budget', ['name' => e($budget->name)])));
|
Session::flash('success', strval(trans('firefly.updated_budget', ['name' => e($budget->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('budgets.edit.fromUpdate', true);
|
Session::put('budgets.edit.fromUpdate', true);
|
||||||
|
|
||||||
@ -399,24 +408,22 @@ class BudgetController extends Controller
|
|||||||
'budgeted' => '0',
|
'budgeted' => '0',
|
||||||
'currentRep' => false,
|
'currentRep' => false,
|
||||||
];
|
];
|
||||||
$allRepetitions = $this->repository->getAllBudgetLimitRepetitions($start, $end);
|
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
$otherRepetitions = new Collection;
|
$otherLimits = new Collection;
|
||||||
|
|
||||||
// get all the limit repetitions relevant between start and end and examine them:
|
// get all the budget limits relevant between start and end and examine them:
|
||||||
/** @var LimitRepetition $repetition */
|
/** @var BudgetLimit $limit */
|
||||||
foreach ($allRepetitions as $repetition) {
|
foreach ($budgetLimits as $limit) {
|
||||||
if ($repetition->budget_id == $budget->id) {
|
if ($limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)
|
||||||
if ($repetition->startdate->isSameDay($start) && $repetition->enddate->isSameDay($end)
|
|
||||||
) {
|
) {
|
||||||
$return[$budgetId]['currentRep'] = $repetition;
|
$return[$budgetId]['currentLimit'] = $limit;
|
||||||
$return[$budgetId]['budgeted'] = $repetition->amount;
|
$return[$budgetId]['budgeted'] = $limit->amount;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// otherwise it's just one of the many relevant repetitions:
|
// otherwise it's just one of the many relevant repetitions:
|
||||||
$otherRepetitions->push($repetition);
|
$otherLimits->push($limit);
|
||||||
}
|
}
|
||||||
}
|
$return[$budgetId]['otherLimits'] = $otherLimits;
|
||||||
$return[$budgetId]['otherRepetitions'] = $otherRepetitions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
|
@ -14,16 +14,15 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Requests\CategoryFormRequest;
|
use FireflyIII\Http\Requests\CategoryFormRequest;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
|
||||||
use Navigation;
|
use Navigation;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
@ -89,13 +88,14 @@ class CategoryController extends Controller
|
|||||||
return view('categories.delete', compact('category', 'subTitle'));
|
return view('categories.delete', compact('category', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CRI $repository
|
* @param CategoryRepositoryInterface $repository
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function destroy(CRI $repository, Category $category)
|
public function destroy(CategoryRepositoryInterface $repository, Category $category)
|
||||||
{
|
{
|
||||||
|
|
||||||
$name = $category->name;
|
$name = $category->name;
|
||||||
@ -136,11 +136,11 @@ class CategoryController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CRI $repository
|
* @param CategoryRepositoryInterface $repository
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function index(CRI $repository)
|
public function index(CategoryRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$categories = $repository->getCategories();
|
$categories = $repository->getCategories();
|
||||||
|
|
||||||
@ -164,7 +164,8 @@ class CategoryController extends Controller
|
|||||||
$end = session('end', Carbon::now()->startOfMonth());
|
$end = session('end', Carbon::now()->startOfMonth());
|
||||||
|
|
||||||
// new collector:
|
// new collector:
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAllAssetAccounts()->setRange($start, $end)->withoutCategory();//->groupJournals();
|
$collector->setAllAssetAccounts()->setRange($start, $end)->withoutCategory();//->groupJournals();
|
||||||
$journals = $collector->getJournals();
|
$journals = $collector->getJournals();
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
@ -176,109 +177,98 @@ class CategoryController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CRI $repository
|
* @param Request $request
|
||||||
* @param AccountRepositoryInterface $accountRepository
|
* @param JournalCollectorInterface $collector
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function show(CRI $repository, AccountRepositoryInterface $accountRepository, Category $category)
|
public function show(Request $request, JournalCollectorInterface $collector, Category $category)
|
||||||
{
|
{
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
/** @var Carbon $start */
|
|
||||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||||
/** @var Carbon $end */
|
|
||||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
|
||||||
$hideCategory = true; // used in list.
|
$hideCategory = true; // used in list.
|
||||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
$subTitle = $category->name;
|
$subTitle = $category->name;
|
||||||
$subTitleIcon = 'fa-bar-chart';
|
$subTitleIcon = 'fa-bar-chart';
|
||||||
|
|
||||||
// use journal collector
|
$collector->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category)->withBudgetInformation();
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setPage($page)->setLimit($pageSize)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category);
|
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('categories/show/' . $category->id);
|
$journals->setPath('categories/show/' . $category->id);
|
||||||
|
|
||||||
// oldest transaction in category:
|
$entries = $this->getGroupedEntries($category);
|
||||||
|
|
||||||
|
return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param CategoryRepositoryInterface $repository
|
||||||
|
* @param Category $category
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function showAll(Request $request, CategoryRepositoryInterface $repository, Category $category)
|
||||||
|
{
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = $repository->firstUseDate($category);
|
$start = $repository->firstUseDate($category);
|
||||||
if ($start->year == 1900) {
|
if ($start->year == 1900) {
|
||||||
$start = new Carbon;
|
$start = new Carbon;
|
||||||
}
|
}
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$end = Navigation::endOfPeriod(new Carbon, $range);
|
||||||
$start = Navigation::startOfPeriod($start, $range);
|
$subTitle = $category->name;
|
||||||
$end = Navigation::endOfX(new Carbon, $range);
|
$subTitleIcon = 'fa-bar-chart';
|
||||||
$entries = new Collection;
|
$hideCategory = true; // used in list.
|
||||||
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
|
$showAll = true;
|
||||||
|
|
||||||
// chart properties for cache:
|
/** @var JournalCollectorInterface $collector */
|
||||||
$cache = new CacheProperties();
|
$collector = app(JournalCollectorInterface::class);
|
||||||
$cache->addProperty($start);
|
$collector->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->setCategory($category)->withBudgetInformation();
|
||||||
$cache->addProperty($end);
|
$journals = $collector->getPaginatedJournals();
|
||||||
$cache->addProperty('category-show');
|
$journals->setPath('categories/show/' . $category->id . '/all');
|
||||||
$cache->addProperty($category->id);
|
|
||||||
|
|
||||||
|
return view('categories.show', compact('category', 'journals', 'hideCategory', 'subTitle', 'subTitleIcon', 'start', 'end', 'showAll'));
|
||||||
if ($cache->has()) {
|
|
||||||
$entries = $cache->get();
|
|
||||||
|
|
||||||
return view('categories.show', compact('category', 'journals', 'entries', 'subTitleIcon', 'hideCategory', 'subTitle'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$categoryCollection = new Collection([$category]);
|
|
||||||
|
|
||||||
while ($end >= $start) {
|
|
||||||
$end = Navigation::startOfPeriod($end, $range);
|
|
||||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
|
||||||
$spent = $repository->spentInPeriod($categoryCollection, $accounts, $end, $currentEnd);
|
|
||||||
$earned = $repository->earnedInPeriod($categoryCollection, $accounts, $end, $currentEnd);
|
|
||||||
$dateStr = $end->format('Y-m-d');
|
|
||||||
$dateName = Navigation::periodShow($end, $range);
|
|
||||||
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
|
||||||
|
|
||||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
$cache->store($entries);
|
|
||||||
|
|
||||||
return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle', 'subTitleIcon'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
* @param $date
|
* @param string $date
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function showByDate(Category $category, string $date)
|
public function showByDate(Request $request, Category $category, string $date)
|
||||||
{
|
{
|
||||||
$carbon = new Carbon($date);
|
$carbon = new Carbon($date);
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = Navigation::startOfPeriod($carbon, $range);
|
$start = Navigation::startOfPeriod($carbon, $range);
|
||||||
$end = Navigation::endOfPeriod($carbon, $range);
|
$end = Navigation::endOfPeriod($carbon, $range);
|
||||||
$subTitle = $category->name;
|
$subTitle = $category->name;
|
||||||
|
$subTitleIcon = 'fa-bar-chart';
|
||||||
$hideCategory = true; // used in list.
|
$hideCategory = true; // used in list.
|
||||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
|
|
||||||
// new collector:
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = app(JournalCollectorInterface::class);
|
$collector = app(JournalCollectorInterface::class);
|
||||||
$collector->setPage($page)->setLimit($pageSize)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category);
|
$collector->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category)->withBudgetInformation();
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('categories/show/' . $category->id . '/' . $date);
|
$journals->setPath('categories/show/' . $category->id . '/' . $date);
|
||||||
|
|
||||||
return view('categories.show-by-date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon'));
|
return view('categories.show', compact('category', 'journals', 'hideCategory', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CategoryFormRequest $request
|
* @param CategoryFormRequest $request
|
||||||
* @param CRI $repository
|
* @param CategoryRepositoryInterface $repository
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function store(CategoryFormRequest $request, CRI $repository)
|
public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$data = $request->getCategoryData();
|
$data = $request->getCategoryData();
|
||||||
$category = $repository->store($data);
|
$category = $repository->store($data);
|
||||||
@ -286,7 +276,7 @@ class CategoryController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.stored_category', ['name' => e($category->name)])));
|
Session::flash('success', strval(trans('firefly.stored_category', ['name' => e($category->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
Session::put('categories.create.fromStore', true);
|
Session::put('categories.create.fromStore', true);
|
||||||
|
|
||||||
return redirect(route('categories.create'))->withInput();
|
return redirect(route('categories.create'))->withInput();
|
||||||
@ -298,12 +288,12 @@ class CategoryController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CategoryFormRequest $request
|
* @param CategoryFormRequest $request
|
||||||
* @param CRI $repository
|
* @param CategoryRepositoryInterface $repository
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function update(CategoryFormRequest $request, CRI $repository, Category $category)
|
public function update(CategoryFormRequest $request, CategoryRepositoryInterface $repository, Category $category)
|
||||||
{
|
{
|
||||||
$data = $request->getCategoryData();
|
$data = $request->getCategoryData();
|
||||||
$repository->update($category, $data);
|
$repository->update($category, $data);
|
||||||
@ -311,7 +301,7 @@ class CategoryController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_category', ['name' => e($category->name)])));
|
Session::flash('success', strval(trans('firefly.updated_category', ['name' => e($category->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
Session::put('categories.edit.fromUpdate', true);
|
Session::put('categories.edit.fromUpdate', true);
|
||||||
|
|
||||||
return redirect(route('categories.edit', [$category->id]));
|
return redirect(route('categories.edit', [$category->id]));
|
||||||
@ -322,4 +312,48 @@ class CategoryController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Category $category
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
private function getGroupedEntries(Category $category): Collection
|
||||||
|
{
|
||||||
|
$repository = app(CategoryRepositoryInterface::class);
|
||||||
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||||
|
$first = $repository->firstUseDate($category);
|
||||||
|
if ($first->year == 1900) {
|
||||||
|
$first = new Carbon;
|
||||||
|
}
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$first = Navigation::startOfPeriod($first, $range);
|
||||||
|
$end = Navigation::endOfX(new Carbon, $range);
|
||||||
|
$entries = new Collection;
|
||||||
|
|
||||||
|
// properties for entries with their amounts.
|
||||||
|
$cache = new CacheProperties();
|
||||||
|
$cache->addProperty($first);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('categories.entries');
|
||||||
|
$cache->addProperty($category->id);
|
||||||
|
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get();
|
||||||
|
}
|
||||||
|
while ($end >= $first) {
|
||||||
|
$end = Navigation::startOfPeriod($end, $range);
|
||||||
|
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||||
|
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $end, $currentEnd);
|
||||||
|
$earned = $repository->earnedInPeriod(new Collection([$category]), $accounts, $end, $currentEnd);
|
||||||
|
$dateStr = $end->format('Y-m-d');
|
||||||
|
$dateName = Navigation::periodShow($end, $range);
|
||||||
|
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
||||||
|
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||||
|
}
|
||||||
|
$cache->store($entries);
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ class AccountController extends Controller
|
|||||||
$endBalance = $endBalances[$id] ?? '0';
|
$endBalance = $endBalances[$id] ?? '0';
|
||||||
$diff = bcsub($endBalance, $startBalance);
|
$diff = bcsub($endBalance, $startBalance);
|
||||||
if (bccomp($diff, '0') !== 0) {
|
if (bccomp($diff, '0') !== 0) {
|
||||||
$chartData[$account->name] = round($diff, 2);
|
$chartData[$account->name] = $diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arsort($chartData);
|
arsort($chartData);
|
||||||
@ -391,7 +391,7 @@ class AccountController extends Controller
|
|||||||
$diff = bcsub($endBalance, $startBalance);
|
$diff = bcsub($endBalance, $startBalance);
|
||||||
$diff = bcmul($diff, '-1');
|
$diff = bcmul($diff, '-1');
|
||||||
if (bccomp($diff, '0') !== 0) {
|
if (bccomp($diff, '0') !== 0) {
|
||||||
$chartData[$account->name] = round($diff, 2);
|
$chartData[$account->name] = $diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,11 +475,11 @@ class AccountController extends Controller
|
|||||||
];
|
];
|
||||||
$currentStart = clone $start;
|
$currentStart = clone $start;
|
||||||
$range = Steam::balanceInRange($account, $start, clone $end);
|
$range = Steam::balanceInRange($account, $start, clone $end);
|
||||||
$previous = round(array_values($range)[0], 2);
|
$previous = array_values($range)[0];
|
||||||
while ($currentStart <= $end) {
|
while ($currentStart <= $end) {
|
||||||
$format = $currentStart->format('Y-m-d');
|
$format = $currentStart->format('Y-m-d');
|
||||||
$label = $currentStart->formatLocalized(strval(trans('config.month_and_day')));
|
$label = $currentStart->formatLocalized(strval(trans('config.month_and_day')));
|
||||||
$balance = isset($range[$format]) ? round($range[$format], 2) : $previous;
|
$balance = isset($range[$format]) ? round($range[$format], 12) : $previous;
|
||||||
$previous = $balance;
|
$previous = $balance;
|
||||||
$currentStart->addDay();
|
$currentStart->addDay();
|
||||||
$currentSet['entries'][$label] = $balance;
|
$currentSet['entries'][$label] = $balance;
|
||||||
|
@ -97,34 +97,18 @@ class BillController extends Controller
|
|||||||
return $transaction->date->format('U');
|
return $transaction->date->format('U');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$chartData = [
|
$chartData = [
|
||||||
[
|
['type' => 'bar', 'label' => trans('firefly.min-amount'), 'entries' => [],],
|
||||||
'type' => 'bar',
|
['type' => 'bar', 'label' => trans('firefly.max-amount'), 'entries' => [],],
|
||||||
'label' => trans('firefly.min-amount'),
|
['type' => 'line', 'label' => trans('firefly.journal-amount'), 'entries' => [],],
|
||||||
'entries' => [],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'type' => 'bar',
|
|
||||||
'label' => trans('firefly.max-amount'),
|
|
||||||
'entries' => [],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'type' => 'line',
|
|
||||||
'label' => trans('firefly.journal-amount'),
|
|
||||||
'entries' => [],
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var Transaction $entry */
|
/** @var Transaction $entry */
|
||||||
foreach ($results as $entry) {
|
foreach ($results as $entry) {
|
||||||
$date = $entry->date->formatLocalized(strval(trans('config.month_and_day')));
|
$date = $entry->date->formatLocalized(strval(trans('config.month_and_day')));
|
||||||
// minimum amount of bill:
|
$chartData[0]['entries'][$date] = $bill->amount_min; // minimum amount of bill
|
||||||
$chartData[0]['entries'][$date] = $bill->amount_min;
|
$chartData[1]['entries'][$date] = $bill->amount_max; // maximum amount of bill
|
||||||
// maximum amount of bill:
|
$chartData[2]['entries'][$date] = bcmul($entry->transaction_amount, '-1'); // amount of journal
|
||||||
$chartData[1]['entries'][$date] = $bill->amount_max;
|
|
||||||
// amount of journal:
|
|
||||||
$chartData[2]['entries'][$date] = bcmul($entry->transaction_amount, '-1');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->generator->multiSet($chartData);
|
$data = $this->generator->multiSet($chartData);
|
||||||
|
@ -14,11 +14,12 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Controllers\Chart;
|
namespace FireflyIII\Http\Controllers\Chart;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
@ -31,6 +32,8 @@ use Response;
|
|||||||
/**
|
/**
|
||||||
* Class BudgetController
|
* Class BudgetController
|
||||||
*
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // can't realy be helped.
|
||||||
|
*
|
||||||
* @package FireflyIII\Http\Controllers\Chart
|
* @package FireflyIII\Http\Controllers\Chart
|
||||||
*/
|
*/
|
||||||
class BudgetController extends Controller
|
class BudgetController extends Controller
|
||||||
@ -39,26 +42,35 @@ class BudgetController extends Controller
|
|||||||
/** @var GeneratorInterface */
|
/** @var GeneratorInterface */
|
||||||
protected $generator;
|
protected $generator;
|
||||||
|
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
protected $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BudgetController constructor.
|
* BudgetController constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
$this->generator = app(GeneratorInterface::class);
|
$this->generator = app(GeneratorInterface::class);
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checked
|
|
||||||
*
|
*
|
||||||
* @param BudgetRepositoryInterface $repository
|
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function budget(BudgetRepositoryInterface $repository, Budget $budget)
|
public function budget(Budget $budget)
|
||||||
{
|
{
|
||||||
$first = $repository->firstUseDate($budget);
|
$first = $this->repository->firstUseDate($budget);
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$last = session('end', new Carbon);
|
$last = session('end', new Carbon);
|
||||||
|
|
||||||
@ -73,7 +85,6 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
$final = clone $last;
|
$final = clone $last;
|
||||||
$final->addYears(2);
|
$final->addYears(2);
|
||||||
|
|
||||||
$budgetCollection = new Collection([$budget]);
|
$budgetCollection = new Collection([$budget]);
|
||||||
$last = Navigation::endOfX($last, $range, $final); // not to overshoot.
|
$last = Navigation::endOfX($last, $range, $final); // not to overshoot.
|
||||||
$entries = [];
|
$entries = [];
|
||||||
@ -84,7 +95,7 @@ class BudgetController extends Controller
|
|||||||
$currentEnd = Navigation::endOfPeriod($first, $range);
|
$currentEnd = Navigation::endOfPeriod($first, $range);
|
||||||
// sub another day because reasons.
|
// sub another day because reasons.
|
||||||
$currentEnd->subDay();
|
$currentEnd->subDay();
|
||||||
$spent = $repository->spentInPeriod($budgetCollection, new Collection, $currentStart, $currentEnd);
|
$spent = $this->repository->spentInPeriod($budgetCollection, new Collection, $currentStart, $currentEnd);
|
||||||
$format = Navigation::periodShow($first, $range);
|
$format = Navigation::periodShow($first, $range);
|
||||||
$entries[$format] = bcmul($spent, '-1');
|
$entries[$format] = bcmul($spent, '-1');
|
||||||
$first = Navigation::addPeriod($first, $range, 0);
|
$first = Navigation::addPeriod($first, $range, 0);
|
||||||
@ -100,31 +111,36 @@ class BudgetController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Shows the amount left in a specific budget limit.
|
* Shows the amount left in a specific budget limit.
|
||||||
*
|
*
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param LimitRepetition $repetition
|
* @param BudgetLimit $budgetLimit
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
|
public function budgetLimit(Budget $budget, BudgetLimit $budgetLimit)
|
||||||
{
|
{
|
||||||
$start = clone $repetition->startdate;
|
if ($budgetLimit->budget->id != $budget->id) {
|
||||||
$end = $repetition->enddate;
|
throw new FireflyException('This budget limit is not part of this budget.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = clone $budgetLimit->start_date;
|
||||||
|
$end = clone $budgetLimit->end_date;
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('chart.budget.budget.limit');
|
$cache->addProperty('chart.budget.budget.limit');
|
||||||
$cache->addProperty($repetition->id);
|
$cache->addProperty($budgetLimit->id);
|
||||||
|
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return Response::json($cache->get());
|
return Response::json($cache->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
$entries = [];
|
$entries = [];
|
||||||
$amount = $repetition->amount;
|
$amount = $budgetLimit->amount;
|
||||||
$budgetCollection = new Collection([$budget]);
|
$budgetCollection = new Collection([$budget]);
|
||||||
while ($start <= $end) {
|
while ($start <= $end) {
|
||||||
$spent = $repository->spentInPeriod($budgetCollection, new Collection, $start, $start);
|
$spent = $this->repository->spentInPeriod($budgetCollection, new Collection, $start, $start);
|
||||||
$amount = bcadd($amount, $spent);
|
$amount = bcadd($amount, $spent);
|
||||||
$format = $start->formatLocalized(strval(trans('config.month_and_day')));
|
$format = $start->formatLocalized(strval(trans('config.month_and_day')));
|
||||||
$entries[$format] = $amount;
|
$entries[$format] = $amount;
|
||||||
@ -139,12 +155,12 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows a budget list with spent/left/overspent.
|
* Shows a budget list with spent/left/overspent.
|
||||||
*
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // 46 lines, I'm fine with this.
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function frontpage(BudgetRepositoryInterface $repository)
|
public function frontpage()
|
||||||
{
|
{
|
||||||
$start = session('start', Carbon::now()->startOfMonth());
|
$start = session('start', Carbon::now()->startOfMonth());
|
||||||
$end = session('end', Carbon::now()->endOfMonth());
|
$end = session('end', Carbon::now()->endOfMonth());
|
||||||
@ -156,58 +172,32 @@ class BudgetController extends Controller
|
|||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return Response::json($cache->get());
|
return Response::json($cache->get());
|
||||||
}
|
}
|
||||||
$budgets = $repository->getActiveBudgets();
|
$budgets = $this->repository->getActiveBudgets();
|
||||||
$repetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
|
|
||||||
$chartData = [
|
$chartData = [
|
||||||
[
|
['label' => strval(trans('firefly.spent_in_budget')), 'entries' => [], 'type' => 'bar',],
|
||||||
'label' => strval(trans('firefly.spent_in_budget')),
|
['label' => strval(trans('firefly.left_to_spend')), 'entries' => [], 'type' => 'bar',],
|
||||||
'entries' => [],
|
['label' => strval(trans('firefly.overspent')), 'entries' => [], 'type' => 'bar',],
|
||||||
'type' => 'bar',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'label' => strval(trans('firefly.left_to_spend')),
|
|
||||||
'entries' => [],
|
|
||||||
'type' => 'bar',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'label' => strval(trans('firefly.overspent')),
|
|
||||||
'entries' => [],
|
|
||||||
'type' => 'bar',
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
// get relevant repetitions:
|
// get relevant repetitions:
|
||||||
$reps = $this->filterRepetitions($repetitions, $budget, $start, $end);
|
$limits = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
|
$expenses = $this->getExpensesForBudget($limits, $budget, $start, $end);
|
||||||
if ($reps->count() === 0) {
|
foreach ($expenses as $name => $row) {
|
||||||
$row = $this->spentInPeriodSingle($repository, $budget, $start, $end);
|
$chartData[0]['entries'][$name] = $row['spent'];
|
||||||
if (bccomp($row['spent'], '0') !== 0 || bccomp($row['repetition_left'], '0') !== 0) {
|
$chartData[1]['entries'][$name] = $row['left'];
|
||||||
$chartData[0]['entries'][$row['name']] = bcmul($row['spent'], '-1');
|
$chartData[2]['entries'][$name] = $row['overspent'];
|
||||||
$chartData[1]['entries'][$row['name']] = $row['repetition_left'];
|
|
||||||
$chartData[2]['entries'][$row['name']] = bcmul($row['repetition_overspent'], '-1');
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$rows = $this->spentInPeriodMulti($repository, $budget, $reps);
|
|
||||||
foreach ($rows as $row) {
|
|
||||||
if (bccomp($row['spent'], '0') !== 0 || bccomp($row['repetition_left'], '0') !== 0) {
|
|
||||||
$chartData[0]['entries'][$row['name']] = bcmul($row['spent'], '-1');
|
|
||||||
$chartData[1]['entries'][$row['name']] = $row['repetition_left'];
|
|
||||||
$chartData[2]['entries'][$row['name']] = bcmul($row['repetition_overspent'], '-1');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($rows, $row);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// for no budget:
|
// for no budget:
|
||||||
$row = $this->spentInPeriodWithout($start, $end);
|
$spent = $this->spentInPeriodWithout($start, $end);
|
||||||
if (bccomp($row['repetition_overspent'], '0') !== 0) {
|
$name = strval(trans('firefly.no_budget'));
|
||||||
$chartData[0]['entries'][$row['name']] = bcmul($row['spent'], '-1');
|
if (bccomp($spent, '0') !== 0) {
|
||||||
$chartData[1]['entries'][$row['name']] = $row['repetition_left'];
|
$chartData[0]['entries'][$name] = bcmul($spent, '-1');
|
||||||
$chartData[2]['entries'][$row['name']] = bcmul($row['repetition_overspent'], '-1');
|
$chartData[1]['entries'][$name] = '0';
|
||||||
|
$chartData[2]['entries'][$name] = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->generator->multiSet($chartData);
|
$data = $this->generator->multiSet($chartData);
|
||||||
@ -218,7 +208,8 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
|
||||||
|
*
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
@ -226,7 +217,7 @@ class BudgetController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function period(BudgetRepositoryInterface $repository, Budget $budget, Collection $accounts, Carbon $start, Carbon $end)
|
public function period(Budget $budget, Collection $accounts, Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
// chart properties for cache:
|
// chart properties for cache:
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
@ -238,56 +229,22 @@ class BudgetController extends Controller
|
|||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return Response::json($cache->get());
|
return Response::json($cache->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the expenses
|
|
||||||
$budgeted = [];
|
|
||||||
$periods = Navigation::listOfPeriods($start, $end);
|
$periods = Navigation::listOfPeriods($start, $end);
|
||||||
$entries = $repository->getBudgetPeriodReport(new Collection([$budget]), $accounts, $start, $end);
|
$entries = $this->repository->getBudgetPeriodReport(new Collection([$budget]), $accounts, $start, $end); // get the expenses
|
||||||
$key = Navigation::preferredCarbonFormat($start, $end);
|
$budgeted = $this->getBudgetedInPeriod($budget, $start, $end);
|
||||||
$range = Navigation::preferredRangeFormat($start, $end);
|
|
||||||
|
|
||||||
// get the budget limits (if any)
|
|
||||||
$repetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
|
|
||||||
$current = clone $start;
|
|
||||||
while ($current < $end) {
|
|
||||||
$currentStart = Navigation::startOfPeriod($current, $range);
|
|
||||||
$currentEnd = Navigation::endOfPeriod($current, $range);
|
|
||||||
$reps = $repetitions->filter(
|
|
||||||
function (LimitRepetition $repetition) use ($budget, $currentStart, $currentEnd) {
|
|
||||||
if ($repetition->budget_id === $budget->id && $repetition->startdate >= $currentStart && $repetition->enddate <= $currentEnd) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$index = $currentStart->format($key);
|
|
||||||
$budgeted[$index] = $reps->sum('amount');
|
|
||||||
$currentEnd->addDay();
|
|
||||||
$current = clone $currentEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// join them into one set of data:
|
// join them into one set of data:
|
||||||
$chartData = [
|
$chartData = [
|
||||||
[
|
['label' => strval(trans('firefly.spent')), 'type' => 'bar', 'entries' => [],],
|
||||||
'label' => strval(trans('firefly.spent')),
|
['label' => strval(trans('firefly.budgeted')), 'type' => 'bar', 'entries' => [],],
|
||||||
'type' => 'bar',
|
|
||||||
'entries' => [],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'label' => strval(trans('firefly.budgeted')),
|
|
||||||
'type' => 'bar',
|
|
||||||
'entries' => [],
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach (array_keys($periods) as $period) {
|
foreach (array_keys($periods) as $period) {
|
||||||
$label = $periods[$period];
|
$label = $periods[$period];
|
||||||
$spent = isset($entries[$budget->id]['entries'][$period]) ? $entries[$budget->id]['entries'][$period] : '0';
|
$spent = isset($entries[$budget->id]['entries'][$period]) ? $entries[$budget->id]['entries'][$period] : '0';
|
||||||
$limit = isset($budgeted[$period]) ? $budgeted[$period] : 0;
|
$limit = isset($budgeted[$period]) ? $budgeted[$period] : 0;
|
||||||
$chartData[0]['entries'][$label] = round(bcmul($spent, '-1'), 2);
|
$chartData[0]['entries'][$label] = round(bcmul($spent, '-1'), 12);
|
||||||
$chartData[1]['entries'][$label] = $limit;
|
$chartData[1]['entries'][$label] = $limit;
|
||||||
|
|
||||||
}
|
}
|
||||||
$data = $this->generator->multiSet($chartData);
|
$data = $this->generator->multiSet($chartData);
|
||||||
$cache->store($data);
|
$cache->store($data);
|
||||||
@ -296,14 +253,13 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BudgetRepositoryInterface $repository
|
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function periodNoBudget(BudgetRepositoryInterface $repository, Collection $accounts, Carbon $start, Carbon $end)
|
public function periodNoBudget(Collection $accounts, Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
// chart properties for cache:
|
// chart properties for cache:
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
@ -317,7 +273,7 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
// the expenses:
|
// the expenses:
|
||||||
$periods = Navigation::listOfPeriods($start, $end);
|
$periods = Navigation::listOfPeriods($start, $end);
|
||||||
$entries = $repository->getNoBudgetPeriodReport($accounts, $start, $end);
|
$entries = $this->repository->getNoBudgetPeriodReport($accounts, $start, $end);
|
||||||
$chartData = [];
|
$chartData = [];
|
||||||
|
|
||||||
// join them:
|
// join them:
|
||||||
@ -333,98 +289,115 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $repetitions
|
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return Collection
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function filterRepetitions(Collection $repetitions, Budget $budget, Carbon $start, Carbon $end): Collection
|
private function getBudgetedInPeriod(Budget $budget, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
|
$key = Navigation::preferredCarbonFormat($start, $end);
|
||||||
return $repetitions->filter(
|
$range = Navigation::preferredRangeFormat($start, $end);
|
||||||
function (LimitRepetition $repetition) use ($budget, $start, $end) {
|
$current = clone $start;
|
||||||
if ($repetition->startdate < $end && $repetition->enddate > $start && $repetition->budget_id === $budget->id) {
|
$budgeted = [];
|
||||||
return true;
|
while ($current < $end) {
|
||||||
|
$currentStart = Navigation::startOfPeriod($current, $range);
|
||||||
|
$currentEnd = Navigation::endOfPeriod($current, $range);
|
||||||
|
$budgetLimits = $this->repository->getBudgetLimits($budget, $currentStart, $currentEnd);
|
||||||
|
$index = $currentStart->format($key);
|
||||||
|
$budgeted[$index] = $budgetLimits->sum('amount');
|
||||||
|
$currentEnd->addDay();
|
||||||
|
$current = clone $currentEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return $budgeted;
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array with the following values:
|
|
||||||
* 0 =>
|
|
||||||
* 'name' => name of budget + repetition
|
|
||||||
* 'repetition_left' => left in budget repetition (always zero)
|
|
||||||
* 'repetition_overspent' => spent more than budget repetition? (always zero)
|
|
||||||
* 'spent' => actually spent in period for budget
|
|
||||||
* 1 => (etc)
|
|
||||||
*
|
*
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 6 but ok.
|
||||||
|
*
|
||||||
|
* @param Collection $limits
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Collection $repetitions
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function spentInPeriodMulti(BudgetRepositoryInterface $repository, Budget $budget, Collection $repetitions): array
|
private function getExpensesForBudget(Collection $limits, Budget $budget, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$format = strval(trans('config.month_and_day'));
|
if ($limits->count() === 0) {
|
||||||
$name = $budget->name;
|
$spent = $this->repository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end);
|
||||||
/** @var LimitRepetition $repetition */
|
if (bccomp($spent, '0') !== 0) {
|
||||||
foreach ($repetitions as $repetition) {
|
$return[$budget->name]['spent'] = bcmul($spent, '-1');
|
||||||
$expenses = $repository->spentInPeriod(new Collection([$budget]), new Collection, $repetition->startdate, $repetition->enddate);
|
$return[$budget->name]['left'] = 0;
|
||||||
|
$return[$budget->name]['overspent'] = 0;
|
||||||
if ($repetitions->count() > 1) {
|
|
||||||
$name = $budget->name . ' ' . trans(
|
|
||||||
'firefly.between_dates',
|
|
||||||
['start' => $repetition->startdate->formatLocalized($format), 'end' => $repetition->enddate->formatLocalized($format)]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$amount = $repetition->amount;
|
|
||||||
$left = bccomp(bcadd($amount, $expenses), '0') < 1 ? '0' : bcadd($amount, $expenses);
|
|
||||||
$spent = $expenses;
|
|
||||||
$overspent = bccomp(bcadd($amount, $expenses), '0') < 1 ? bcadd($amount, $expenses) : '0';
|
|
||||||
$return[] = [
|
|
||||||
'name' => $name,
|
|
||||||
'repetition_left' => $left,
|
|
||||||
'repetition_overspent' => $overspent,
|
|
||||||
'spent' => $spent,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$rows = $this->spentInPeriodMulti($budget, $limits);
|
||||||
|
foreach ($rows as $name => $row) {
|
||||||
|
if (bccomp($row['spent'], '0') !== 0 || bccomp($row['left'], '0') !== 0) {
|
||||||
|
$return[$name]['spent'] = bcmul($row['spent'], '-1');
|
||||||
|
$return[$name]['left'] = $row['left'];
|
||||||
|
$return[$name]['overspent'] = bcmul($row['overspent'], '-1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($rows, $row);
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
|
||||||
|
*
|
||||||
* Returns an array with the following values:
|
* Returns an array with the following values:
|
||||||
* 'name' => name of budget
|
* 0 =>
|
||||||
* 'repetition_left' => left in budget repetition (always zero)
|
* 'name' => name of budget + repetition
|
||||||
* 'repetition_overspent' => spent more than budget repetition? (always zero)
|
* 'left' => left in budget repetition (always zero)
|
||||||
|
* 'overspent' => spent more than budget repetition? (always zero)
|
||||||
* 'spent' => actually spent in period for budget
|
* 'spent' => actually spent in period for budget
|
||||||
|
* 1 => (etc)
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @param BudgetRepositoryInterface $repository
|
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Collection $limits
|
||||||
* @param Carbon $end
|
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function spentInPeriodSingle(BudgetRepositoryInterface $repository, Budget $budget, Carbon $start, Carbon $end): array
|
private function spentInPeriodMulti(Budget $budget, Collection $limits): array
|
||||||
{
|
{
|
||||||
$spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end);
|
$return = [];
|
||||||
$array = [
|
$format = strval(trans('config.month_and_day'));
|
||||||
'name' => $budget->name,
|
$name = $budget->name;
|
||||||
'repetition_left' => '0',
|
/** @var BudgetLimit $budgetLimit */
|
||||||
'repetition_overspent' => '0',
|
foreach ($limits as $budgetLimit) {
|
||||||
|
$expenses = $this->repository->spentInPeriod(new Collection([$budget]), new Collection, $budgetLimit->start_date, $budgetLimit->end_date);
|
||||||
|
|
||||||
|
if ($limits->count() > 1) {
|
||||||
|
$name = $budget->name . ' ' . trans(
|
||||||
|
'firefly.between_dates',
|
||||||
|
[
|
||||||
|
'start' => $budgetLimit->start_date->formatLocalized($format),
|
||||||
|
'end' => $budgetLimit->end_date->formatLocalized($format),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$amount = $budgetLimit->amount;
|
||||||
|
$left = bccomp(bcadd($amount, $expenses), '0') < 1 ? '0' : bcadd($amount, $expenses);
|
||||||
|
$spent = $expenses;
|
||||||
|
$overspent = bccomp(bcadd($amount, $expenses), '0') < 1 ? bcadd($amount, $expenses) : '0';
|
||||||
|
$return[$name] = [
|
||||||
|
'left' => $left,
|
||||||
|
'overspent' => $overspent,
|
||||||
'spent' => $spent,
|
'spent' => $spent,
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return $array;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -437,12 +410,13 @@ class BudgetController extends Controller
|
|||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function spentInPeriodWithout(Carbon $start, Carbon $end): array
|
private function spentInPeriodWithout(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
// collector
|
// collector
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$types = [TransactionType::WITHDRAWAL];
|
$types = [TransactionType::WITHDRAWAL];
|
||||||
$collector->setAllAssetAccounts()->setTypes($types)->setRange($start, $end)->withoutBudget();
|
$collector->setAllAssetAccounts()->setTypes($types)->setRange($start, $end)->withoutBudget();
|
||||||
$journals = $collector->getJournals();
|
$journals = $collector->getJournals();
|
||||||
@ -451,13 +425,7 @@ class BudgetController extends Controller
|
|||||||
foreach ($journals as $entry) {
|
foreach ($journals as $entry) {
|
||||||
$sum = bcadd($entry->transaction_amount, $sum);
|
$sum = bcadd($entry->transaction_amount, $sum);
|
||||||
}
|
}
|
||||||
$array = [
|
|
||||||
'name' => strval(trans('firefly.no_budget')),
|
|
||||||
'repetition_left' => '0',
|
|
||||||
'repetition_overspent' => $sum,
|
|
||||||
'spent' => '0',
|
|
||||||
];
|
|
||||||
|
|
||||||
return $array;
|
return $sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,17 @@ namespace FireflyIII\Http\Controllers\Chart;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
||||||
use FireflyIII\Generator\Report\Category\MonthReportGenerator;
|
use FireflyIII\Generator\Report\Category\MonthReportGenerator;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Chart\MetaPieChartInterface;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
|
||||||
use Navigation;
|
use Navigation;
|
||||||
use Response;
|
use Response;
|
||||||
|
|
||||||
@ -76,50 +76,19 @@ class BudgetReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function accountExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others)
|
public function accountExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others)
|
||||||
{
|
{
|
||||||
/** @var bool $others */
|
/** @var MetaPieChartInterface $helper */
|
||||||
$others = intval($others) === 1;
|
$helper = app(MetaPieChartInterface::class);
|
||||||
$cache = new CacheProperties;
|
$helper->setAccounts($accounts);
|
||||||
$cache->addProperty('chart.budget.report.account-expense');
|
$helper->setBudgets($budgets);
|
||||||
$cache->addProperty($accounts);
|
$helper->setUser(auth()->user());
|
||||||
$cache->addProperty($budgets);
|
$helper->setStart($start);
|
||||||
$cache->addProperty($start);
|
$helper->setEnd($end);
|
||||||
$cache->addProperty($end);
|
$helper->setCollectOtherObjects(intval($others) === 1);
|
||||||
$cache->addProperty($others);
|
$chartData = $helper->generate('expense', 'account');
|
||||||
if ($cache->has()) {
|
|
||||||
return Response::json($cache->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
$names = [];
|
|
||||||
$set = $this->getExpenses($accounts, $budgets, $start, $end);
|
|
||||||
$grouped = $this->groupByOpposingAccount($set);
|
|
||||||
$chartData = [];
|
|
||||||
$total = '0';
|
|
||||||
|
|
||||||
foreach ($grouped as $accountId => $amount) {
|
|
||||||
if (!isset($names[$accountId])) {
|
|
||||||
$account = $this->accountRepository->find(intval($accountId));
|
|
||||||
$names[$accountId] = $account->name;
|
|
||||||
}
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
$total = bcadd($total, $amount);
|
|
||||||
$chartData[$names[$accountId]] = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// also collect all transactions NOT in these budgets.
|
|
||||||
if ($others) {
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$sum = strval($journals->sum('transaction_amount'));
|
|
||||||
$sum = bcmul($sum, '-1');
|
|
||||||
$sum = bcsub($sum, $total);
|
|
||||||
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $this->generator->pieChart($chartData);
|
$data = $this->generator->pieChart($chartData);
|
||||||
$cache->store($data);
|
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,48 +102,16 @@ class BudgetReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function budgetExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others)
|
public function budgetExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others)
|
||||||
{
|
{
|
||||||
/** @var bool $others */
|
/** @var MetaPieChartInterface $helper */
|
||||||
$others = intval($others) === 1;
|
$helper = app(MetaPieChartInterface::class);
|
||||||
$cache = new CacheProperties;
|
$helper->setAccounts($accounts);
|
||||||
$cache->addProperty('chart.budget.report.budget-expense');
|
$helper->setBudgets($budgets);
|
||||||
$cache->addProperty($accounts);
|
$helper->setUser(auth()->user());
|
||||||
$cache->addProperty($budgets);
|
$helper->setStart($start);
|
||||||
$cache->addProperty($start);
|
$helper->setEnd($end);
|
||||||
$cache->addProperty($end);
|
$helper->setCollectOtherObjects(intval($others) === 1);
|
||||||
$cache->addProperty($others);
|
$chartData = $helper->generate('expense', 'budget');
|
||||||
if ($cache->has()) {
|
|
||||||
return Response::json($cache->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
$names = [];
|
|
||||||
$set = $this->getExpenses($accounts, $budgets, $start, $end);
|
|
||||||
$grouped = $this->groupByBudget($set);
|
|
||||||
$total = '0';
|
|
||||||
$chartData = [];
|
|
||||||
|
|
||||||
foreach ($grouped as $budgetId => $amount) {
|
|
||||||
if (!isset($names[$budgetId])) {
|
|
||||||
$budget = $this->budgetRepository->find(intval($budgetId));
|
|
||||||
$names[$budgetId] = $budget->name;
|
|
||||||
}
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
$total = bcadd($total, $amount);
|
|
||||||
$chartData[$names[$budgetId]] = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// also collect all transactions NOT in these budgets.
|
|
||||||
if ($others) {
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$sum = strval($journals->sum('transaction_amount'));
|
|
||||||
$sum = bcmul($sum, '-1');
|
|
||||||
$sum = bcsub($sum, $total);
|
|
||||||
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $this->generator->pieChart($chartData);
|
$data = $this->generator->pieChart($chartData);
|
||||||
$cache->store($data);
|
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
}
|
}
|
||||||
@ -204,7 +141,6 @@ class BudgetReportController extends Controller
|
|||||||
$function = Navigation::preferredEndOfPeriod($start, $end);
|
$function = Navigation::preferredEndOfPeriod($start, $end);
|
||||||
$chartData = [];
|
$chartData = [];
|
||||||
$currentStart = clone $start;
|
$currentStart = clone $start;
|
||||||
$limits = $repository->getAllBudgetLimitRepetitions($start, $end); // also for ALL budgets.
|
|
||||||
|
|
||||||
// prep chart data:
|
// prep chart data:
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
@ -229,6 +165,7 @@ class BudgetReportController extends Controller
|
|||||||
'entries' => [],
|
'entries' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
$allBudgetLimits = $repository->getAllBudgetLimits($start, $end);
|
||||||
$sumOfExpenses = [];
|
$sumOfExpenses = [];
|
||||||
$leftOfLimits = [];
|
$leftOfLimits = [];
|
||||||
while ($currentStart < $end) {
|
while ($currentStart < $end) {
|
||||||
@ -239,20 +176,20 @@ class BudgetReportController extends Controller
|
|||||||
|
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
|
// get budget limit(s) for this period):
|
||||||
|
$budgetLimits = $this->filterBudgetLimits($allBudgetLimits, $budget, $currentStart, $currentEnd);
|
||||||
$currentExpenses = $expenses[$budget->id] ?? '0';
|
$currentExpenses = $expenses[$budget->id] ?? '0';
|
||||||
$sumOfExpenses[$budget->id] = $sumOfExpenses[$budget->id] ?? '0';
|
$sumOfExpenses[$budget->id] = $sumOfExpenses[$budget->id] ?? '0';
|
||||||
$sumOfExpenses[$budget->id] = bcadd($currentExpenses, $sumOfExpenses[$budget->id]);
|
$sumOfExpenses[$budget->id] = bcadd($currentExpenses, $sumOfExpenses[$budget->id]);
|
||||||
$chartData[$budget->id]['entries'][$label] = round(bcmul($currentExpenses, '-1'), 2);
|
$chartData[$budget->id]['entries'][$label] = bcmul($currentExpenses, '-1');
|
||||||
$chartData[$budget->id . '-sum']['entries'][$label] = round(bcmul($sumOfExpenses[$budget->id], '-1'), 2);
|
$chartData[$budget->id . '-sum']['entries'][$label] = bcmul($sumOfExpenses[$budget->id], '-1');
|
||||||
|
|
||||||
$limit = $this->filterLimits($limits, $budget, $currentStart);
|
if (count($budgetLimits) > 0) {
|
||||||
if (!is_null($limit->id)) {
|
$budgetLimitId = $budgetLimits->first()->id;
|
||||||
$leftOfLimits[$limit->id] = $leftOfLimits[$limit->id] ?? strval($limit->amount);
|
$leftOfLimits[$budgetLimitId] = $leftOfLimits[$budgetLimitId] ?? strval($budgetLimits->sum('amount'));
|
||||||
$leftOfLimits[$limit->id] = bcadd($leftOfLimits[$limit->id], $currentExpenses);
|
$leftOfLimits[$budgetLimitId] = bcadd($leftOfLimits[$budgetLimitId], $currentExpenses);
|
||||||
$chartData[$budget->id . '-left']['entries'][$label] = round($leftOfLimits[$limit->id], 2);
|
$chartData[$budget->id . '-left']['entries'][$label] = $leftOfLimits[$budgetLimitId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
$currentStart = clone $currentEnd;
|
$currentStart = clone $currentEnd;
|
||||||
$currentStart->addDay();
|
$currentStart->addDay();
|
||||||
@ -265,44 +202,32 @@ class BudgetReportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $limits
|
* Returns the budget limits belonging to the given budget and valid on the given day.
|
||||||
* @param $budget
|
|
||||||
* @param $currentStart
|
|
||||||
*
|
*
|
||||||
* @return LimitRepetition
|
* @param Collection $budgetLimits
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
private function filterLimits(Collection $limits, Budget $budget, Carbon $date): LimitRepetition
|
private function filterBudgetLimits(Collection $budgetLimits, Budget $budget, Carbon $start, Carbon $end): Collection
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Start of filterLimits with %d limits.', $limits->count()));
|
$set = $budgetLimits->filter(
|
||||||
$filtered = $limits->filter(
|
function (BudgetLimit $budgetLimit) use ($budget, $start, $end) {
|
||||||
function (LimitRepetition $limit) use ($budget, $date) {
|
if ($budgetLimit->budget_id === $budget->id
|
||||||
if ($limit->budget_id !== $budget->id) {
|
&& $budgetLimit->start_date->lte($start) // start of budget limit is on or before start
|
||||||
Log::debug(sprintf('LimitRepetition has budget #%d but expecting #%d', $limit->budget_id, $budget->id));
|
&& $budgetLimit->end_date->gte($end) // end of budget limit is on or after end
|
||||||
|
) {
|
||||||
|
return $budgetLimit;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($date < $limit->startdate || $date > $limit->enddate) {
|
|
||||||
Log::debug(
|
|
||||||
sprintf(
|
|
||||||
'Date %s is not between %s and %s',
|
|
||||||
$date->format('Y-m-d'), $limit->startdate->format('Y-m-d'), $limit->enddate->format('Y-m-d')
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return false;
|
return $set;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $limit;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if ($filtered->count() === 1) {
|
|
||||||
return $filtered->first();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LimitRepetition;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
* @param Collection $budgets
|
* @param Collection $budgets
|
||||||
@ -313,7 +238,8 @@ class BudgetReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function getExpenses(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end): Collection
|
private function getExpenses(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end): Collection
|
||||||
{
|
{
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||||
->setBudgets($budgets)->withOpposingAccount()->disableFilter();
|
->setBudgets($budgets)->withOpposingAccount()->disableFilter();
|
||||||
$accountIds = $accounts->pluck('id')->toArray();
|
$accountIds = $accounts->pluck('id')->toArray();
|
||||||
|
@ -66,6 +66,11 @@ class CategoryController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$start = $repository->firstUseDate($category);
|
$start = $repository->firstUseDate($category);
|
||||||
|
|
||||||
|
if ($start->year == 1900) {
|
||||||
|
$start = new Carbon;
|
||||||
|
}
|
||||||
|
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = Navigation::startOfPeriod($start, $range);
|
$start = Navigation::startOfPeriod($start, $range);
|
||||||
$end = new Carbon;
|
$end = new Carbon;
|
||||||
|
@ -17,7 +17,8 @@ namespace FireflyIII\Http\Controllers\Chart;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
||||||
use FireflyIII\Generator\Report\Category\MonthReportGenerator;
|
use FireflyIII\Generator\Report\Category\MonthReportGenerator;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Chart\MetaPieChartInterface;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
@ -75,48 +76,16 @@ class CategoryReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function accountExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
public function accountExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
||||||
{
|
{
|
||||||
/** @var bool $others */
|
/** @var MetaPieChartInterface $helper */
|
||||||
$others = intval($others) === 1;
|
$helper = app(MetaPieChartInterface::class);
|
||||||
$cache = new CacheProperties;
|
$helper->setAccounts($accounts);
|
||||||
$cache->addProperty('chart.category.report.account-expense');
|
$helper->setCategories($categories);
|
||||||
$cache->addProperty($accounts);
|
$helper->setUser(auth()->user());
|
||||||
$cache->addProperty($categories);
|
$helper->setStart($start);
|
||||||
$cache->addProperty($start);
|
$helper->setEnd($end);
|
||||||
$cache->addProperty($end);
|
$helper->setCollectOtherObjects(intval($others) === 1);
|
||||||
$cache->addProperty($others);
|
$chartData = $helper->generate('expense', 'account');
|
||||||
if ($cache->has()) {
|
|
||||||
return Response::json($cache->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
$names = [];
|
|
||||||
$set = $this->getExpenses($accounts, $categories, $start, $end);
|
|
||||||
$grouped = $this->groupByOpposingAccount($set);
|
|
||||||
$chartData = [];
|
|
||||||
$total = '0';
|
|
||||||
|
|
||||||
foreach ($grouped as $accountId => $amount) {
|
|
||||||
if (!isset($names[$accountId])) {
|
|
||||||
$account = $this->accountRepository->find(intval($accountId));
|
|
||||||
$names[$accountId] = $account->name;
|
|
||||||
}
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
$total = bcadd($total, $amount);
|
|
||||||
$chartData[$names[$accountId]] = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// also collect all transactions NOT in these categories.
|
|
||||||
if ($others) {
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$sum = strval($journals->sum('transaction_amount'));
|
|
||||||
$sum = bcmul($sum, '-1');
|
|
||||||
$sum = bcsub($sum, $total);
|
|
||||||
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $this->generator->pieChart($chartData);
|
$data = $this->generator->pieChart($chartData);
|
||||||
$cache->store($data);
|
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
}
|
}
|
||||||
@ -132,47 +101,16 @@ class CategoryReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function accountIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
public function accountIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
||||||
{
|
{
|
||||||
/** @var bool $others */
|
/** @var MetaPieChartInterface $helper */
|
||||||
$others = intval($others) === 1;
|
$helper = app(MetaPieChartInterface::class);
|
||||||
$cache = new CacheProperties;
|
$helper->setAccounts($accounts);
|
||||||
$cache->addProperty('chart.category.report.account-income');
|
$helper->setCategories($categories);
|
||||||
$cache->addProperty($accounts);
|
$helper->setUser(auth()->user());
|
||||||
$cache->addProperty($categories);
|
$helper->setStart($start);
|
||||||
$cache->addProperty($start);
|
$helper->setEnd($end);
|
||||||
$cache->addProperty($others);
|
$helper->setCollectOtherObjects(intval($others) === 1);
|
||||||
$cache->addProperty($end);
|
$chartData = $helper->generate('income', 'account');
|
||||||
if ($cache->has()) {
|
|
||||||
return Response::json($cache->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$names = [];
|
|
||||||
$set = $this->getIncome($accounts, $categories, $start, $end);
|
|
||||||
$grouped = $this->groupByOpposingAccount($set);
|
|
||||||
$chartData = [];
|
|
||||||
$total = '0';
|
|
||||||
|
|
||||||
foreach ($grouped as $accountId => $amount) {
|
|
||||||
if (!isset($names[$accountId])) {
|
|
||||||
$account = $this->accountRepository->find(intval($accountId));
|
|
||||||
$names[$accountId] = $account->name;
|
|
||||||
}
|
|
||||||
$total = bcadd($total, $amount);
|
|
||||||
$chartData[$names[$accountId]] = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// also collect others?
|
|
||||||
if ($others) {
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$sum = strval($journals->sum('transaction_amount'));
|
|
||||||
$sum = bcsub($sum, $total);
|
|
||||||
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $this->generator->pieChart($chartData);
|
$data = $this->generator->pieChart($chartData);
|
||||||
$cache->store($data);
|
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
}
|
}
|
||||||
@ -188,48 +126,16 @@ class CategoryReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function categoryExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
public function categoryExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
||||||
{
|
{
|
||||||
/** @var bool $others */
|
/** @var MetaPieChartInterface $helper */
|
||||||
$others = intval($others) === 1;
|
$helper = app(MetaPieChartInterface::class);
|
||||||
$cache = new CacheProperties;
|
$helper->setAccounts($accounts);
|
||||||
$cache->addProperty('chart.category.report.category-expense');
|
$helper->setCategories($categories);
|
||||||
$cache->addProperty($accounts);
|
$helper->setUser(auth()->user());
|
||||||
$cache->addProperty($categories);
|
$helper->setStart($start);
|
||||||
$cache->addProperty($start);
|
$helper->setEnd($end);
|
||||||
$cache->addProperty($end);
|
$helper->setCollectOtherObjects(intval($others) === 1);
|
||||||
$cache->addProperty($others);
|
$chartData = $helper->generate('expense', 'category');
|
||||||
if ($cache->has()) {
|
|
||||||
return Response::json($cache->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
$names = [];
|
|
||||||
$set = $this->getExpenses($accounts, $categories, $start, $end);
|
|
||||||
$grouped = $this->groupByCategory($set);
|
|
||||||
$total = '0';
|
|
||||||
$chartData = [];
|
|
||||||
|
|
||||||
foreach ($grouped as $categoryId => $amount) {
|
|
||||||
if (!isset($names[$categoryId])) {
|
|
||||||
$category = $this->categoryRepository->find(intval($categoryId));
|
|
||||||
$names[$categoryId] = $category->name;
|
|
||||||
}
|
|
||||||
$amount = bcmul($amount, '-1');
|
|
||||||
$total = bcadd($total, $amount);
|
|
||||||
$chartData[$names[$categoryId]] = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// also collect all transactions NOT in these categories.
|
|
||||||
if ($others) {
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$sum = strval($journals->sum('transaction_amount'));
|
|
||||||
$sum = bcmul($sum, '-1');
|
|
||||||
$sum = bcsub($sum, $total);
|
|
||||||
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $this->generator->pieChart($chartData);
|
$data = $this->generator->pieChart($chartData);
|
||||||
$cache->store($data);
|
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
}
|
}
|
||||||
@ -245,45 +151,17 @@ class CategoryReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function categoryIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
public function categoryIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others)
|
||||||
{
|
{
|
||||||
/** @var bool $others */
|
|
||||||
$others = intval($others) === 1;
|
|
||||||
$cache = new CacheProperties;
|
|
||||||
$cache->addProperty('chart.category.report.category-income');
|
|
||||||
$cache->addProperty($accounts);
|
|
||||||
$cache->addProperty($categories);
|
|
||||||
$cache->addProperty($start);
|
|
||||||
$cache->addProperty($end);
|
|
||||||
$cache->addProperty($others);
|
|
||||||
if ($cache->has()) {
|
|
||||||
return Response::json($cache->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
$names = [];
|
|
||||||
$set = $this->getIncome($accounts, $categories, $start, $end);
|
|
||||||
$grouped = $this->groupByCategory($set);
|
|
||||||
$total = '0';
|
|
||||||
$chartData = [];
|
|
||||||
|
|
||||||
foreach ($grouped as $categoryId => $amount) {
|
|
||||||
if (!isset($names[$categoryId])) {
|
|
||||||
$category = $this->categoryRepository->find(intval($categoryId));
|
|
||||||
$names[$categoryId] = $category->name;
|
|
||||||
}
|
|
||||||
$total = bcadd($total, $amount);
|
|
||||||
$chartData[$names[$categoryId]] = $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($others) {
|
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]);
|
|
||||||
$journals = $collector->getJournals();
|
|
||||||
$sum = strval($journals->sum('transaction_amount'));
|
|
||||||
$sum = bcsub($sum, $total);
|
|
||||||
$chartData[strval(trans('firefly.everything_else'))] = $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/** @var MetaPieChartInterface $helper */
|
||||||
|
$helper = app(MetaPieChartInterface::class);
|
||||||
|
$helper->setAccounts($accounts);
|
||||||
|
$helper->setCategories($categories);
|
||||||
|
$helper->setUser(auth()->user());
|
||||||
|
$helper->setStart($start);
|
||||||
|
$helper->setEnd($end);
|
||||||
|
$helper->setCollectOtherObjects(intval($others) === 1);
|
||||||
|
$chartData = $helper->generate('income', 'category');
|
||||||
$data = $this->generator->pieChart($chartData);
|
$data = $this->generator->pieChart($chartData);
|
||||||
$cache->store($data);
|
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
}
|
}
|
||||||
@ -405,7 +283,8 @@ class CategoryReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function getExpenses(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): Collection
|
private function getExpenses(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): Collection
|
||||||
{
|
{
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||||
->setCategories($categories)->withOpposingAccount()->disableFilter();
|
->setCategories($categories)->withOpposingAccount()->disableFilter();
|
||||||
$accountIds = $accounts->pluck('id')->toArray();
|
$accountIds = $accounts->pluck('id')->toArray();
|
||||||
@ -425,7 +304,8 @@ class CategoryReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function getIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): Collection
|
private function getIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): Collection
|
||||||
{
|
{
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||||
->setCategories($categories)->withOpposingAccount();
|
->setCategories($categories)->withOpposingAccount();
|
||||||
$accountIds = $accounts->pluck('id')->toArray();
|
$accountIds = $accounts->pluck('id')->toArray();
|
||||||
|
@ -13,6 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
|
use FireflyConfig;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
@ -23,7 +24,6 @@ use Illuminate\Foundation\Validation\ValidatesRequests;
|
|||||||
use Illuminate\Routing\Controller as BaseController;
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
use Session;
|
use Session;
|
||||||
use View;
|
use View;
|
||||||
use FireflyConfig;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Controller
|
* Class Controller
|
||||||
|
@ -17,7 +17,6 @@ use Cache;
|
|||||||
use FireflyIII\Http\Requests\CurrencyFormRequest;
|
use FireflyIII\Http\Requests\CurrencyFormRequest;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
use Input;
|
|
||||||
use Log;
|
use Log;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
@ -170,7 +169,7 @@ class CurrencyController extends Controller
|
|||||||
|
|
||||||
|
|
||||||
if (!auth()->user()->hasRole('owner')) {
|
if (!auth()->user()->hasRole('owner')) {
|
||||||
Session::flash('warning', trans('firefly.ask_site_owner', ['site_owner' => env('SITE_OWNER')]));
|
Session::flash('info', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -196,7 +195,7 @@ class CurrencyController extends Controller
|
|||||||
$currency = $repository->store($data);
|
$currency = $repository->store($data);
|
||||||
Session::flash('success', trans('firefly.created_currency', ['name' => $currency->name]));
|
Session::flash('success', trans('firefly.created_currency', ['name' => $currency->name]));
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
Session::put('currencies.create.fromStore', true);
|
Session::put('currencies.create.fromStore', true);
|
||||||
|
|
||||||
return redirect(route('currencies.create'))->withInput();
|
return redirect(route('currencies.create'))->withInput();
|
||||||
@ -225,7 +224,7 @@ class CurrencyController extends Controller
|
|||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
Session::put('currencies.edit.fromUpdate', true);
|
Session::put('currencies.edit.fromUpdate', true);
|
||||||
|
|
||||||
return redirect(route('currencies.edit', [$currency->id]));
|
return redirect(route('currencies.edit', [$currency->id]));
|
||||||
|
@ -26,7 +26,6 @@ use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface as EJRI;
|
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface as EJRI;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
use Storage;
|
|
||||||
use View;
|
use View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +144,7 @@ class ExportController extends Controller
|
|||||||
'job' => $job,
|
'job' => $job,
|
||||||
];
|
];
|
||||||
|
|
||||||
$job->change('export_status_make_exporter');
|
$jobs->changeStatus($job, 'export_status_make_exporter');
|
||||||
|
|
||||||
/** @var ProcessorInterface $processor */
|
/** @var ProcessorInterface $processor */
|
||||||
$processor = app(ProcessorInterface::class, [$settings]);
|
$processor = app(ProcessorInterface::class, [$settings]);
|
||||||
@ -153,47 +152,46 @@ class ExportController extends Controller
|
|||||||
/*
|
/*
|
||||||
* Collect journals:
|
* Collect journals:
|
||||||
*/
|
*/
|
||||||
$job->change('export_status_collecting_journals');
|
$jobs->changeStatus($job, 'export_status_collecting_journals');
|
||||||
$processor->collectJournals();
|
$processor->collectJournals();
|
||||||
$job->change('export_status_collected_journals');
|
$jobs->changeStatus($job, 'export_status_collected_journals');
|
||||||
/*
|
/*
|
||||||
* Transform to exportable entries:
|
* Transform to exportable entries:
|
||||||
*/
|
*/
|
||||||
$job->change('export_status_converting_to_export_format');
|
$jobs->changeStatus($job, 'export_status_converting_to_export_format');
|
||||||
$processor->convertJournals();
|
$processor->convertJournals();
|
||||||
$job->change('export_status_converted_to_export_format');
|
$jobs->changeStatus($job, 'export_status_converted_to_export_format');
|
||||||
/*
|
/*
|
||||||
* Transform to (temporary) file:
|
* Transform to (temporary) file:
|
||||||
*/
|
*/
|
||||||
$job->change('export_status_creating_journal_file');
|
$jobs->changeStatus($job, 'export_status_creating_journal_file');
|
||||||
$processor->exportJournals();
|
$processor->exportJournals();
|
||||||
$job->change('export_status_created_journal_file');
|
$jobs->changeStatus($job, 'export_status_created_journal_file');
|
||||||
/*
|
/*
|
||||||
* Collect attachments, if applicable.
|
* Collect attachments, if applicable.
|
||||||
*/
|
*/
|
||||||
if ($settings['includeAttachments']) {
|
if ($settings['includeAttachments']) {
|
||||||
$job->change('export_status_collecting_attachments');
|
$jobs->changeStatus($job, 'export_status_collecting_attachments');
|
||||||
$processor->collectAttachments();
|
$processor->collectAttachments();
|
||||||
$job->change('export_status_collected_attachments');
|
$jobs->changeStatus($job, 'export_status_collected_attachments');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Collect old uploads
|
* Collect old uploads
|
||||||
*/
|
*/
|
||||||
if ($settings['includeOldUploads']) {
|
if ($settings['includeOldUploads']) {
|
||||||
$job->change('export_status_collecting_old_uploads');
|
$jobs->changeStatus($job, 'export_status_collecting_old_uploads');
|
||||||
$processor->collectOldUploads();
|
$processor->collectOldUploads();
|
||||||
$job->change('export_status_collected_old_uploads');
|
$jobs->changeStatus($job, 'export_status_collected_old_uploads');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create ZIP file:
|
* Create ZIP file:
|
||||||
*/
|
*/
|
||||||
$job->change('export_status_creating_zip_file');
|
$jobs->changeStatus($job, 'export_status_creating_zip_file');
|
||||||
$processor->createZipFile();
|
$processor->createZipFile();
|
||||||
$job->change('export_status_created_zip_file');
|
$jobs->changeStatus($job, 'export_status_created_zip_file');
|
||||||
|
$jobs->changeStatus($job, 'export_status_finished');
|
||||||
$job->change('export_status_finished');
|
|
||||||
|
|
||||||
return Response::json('ok');
|
return Response::json('ok');
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,6 @@ class HomeController extends Controller
|
|||||||
// a possible problem with the budgets.
|
// a possible problem with the budgets.
|
||||||
if ($label === strval(trans('firefly.everything')) || $label === strval(trans('firefly.customRange'))) {
|
if ($label === strval(trans('firefly.everything')) || $label === strval(trans('firefly.customRange'))) {
|
||||||
$isCustomRange = true;
|
$isCustomRange = true;
|
||||||
//Preferences::set('viewRange', 'custom');
|
|
||||||
Log::debug('Range is now marked as "custom".');
|
Log::debug('Range is now marked as "custom".');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,9 +174,6 @@ class HomeController extends Controller
|
|||||||
'logout',
|
'logout',
|
||||||
'two-fac',
|
'two-fac',
|
||||||
'lost-two',
|
'lost-two',
|
||||||
'confirm',
|
|
||||||
'resend',
|
|
||||||
'do_confirm',
|
|
||||||
// test troutes
|
// test troutes
|
||||||
'test-flash',
|
'test-flash',
|
||||||
'all-routes',
|
'all-routes',
|
||||||
|
@ -23,6 +23,7 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Log;
|
use Log;
|
||||||
use Response;
|
use Response;
|
||||||
|
use Session;
|
||||||
use SplFileObject;
|
use SplFileObject;
|
||||||
use Storage;
|
use Storage;
|
||||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
@ -368,14 +369,33 @@ class ImportController extends Controller
|
|||||||
$content = $uploaded->fread($uploaded->getSize());
|
$content = $uploaded->fread($uploaded->getSize());
|
||||||
$contentEncrypted = Crypt::encrypt($content);
|
$contentEncrypted = Crypt::encrypt($content);
|
||||||
$disk = Storage::disk('upload');
|
$disk = Storage::disk('upload');
|
||||||
|
|
||||||
|
// user is demo user, replace upload with prepared file.
|
||||||
|
if (auth()->user()->hasRole('demo')) {
|
||||||
|
$stubsDisk = Storage::disk('stubs');
|
||||||
|
$content = $stubsDisk->get('demo-import.csv');
|
||||||
|
$contentEncrypted = Crypt::encrypt($content);
|
||||||
$disk->put($newName, $contentEncrypted);
|
$disk->put($newName, $contentEncrypted);
|
||||||
|
Log::debug('Replaced upload with demo file.');
|
||||||
|
|
||||||
|
// also set up prepared configuration.
|
||||||
|
$configuration = json_decode($stubsDisk->get('demo-configuration.json'), true);
|
||||||
|
$job->configuration = $configuration;
|
||||||
|
$job->save();
|
||||||
|
Log::debug('Set configuration for demo user', $configuration);
|
||||||
|
|
||||||
|
// also flash info
|
||||||
|
Session::flash('info', trans('demo.import-configure-security'));
|
||||||
|
}
|
||||||
|
if (!auth()->user()->hasRole('demo')) {
|
||||||
|
// user is not demo, process original upload:
|
||||||
|
$disk->put($newName, $contentEncrypted);
|
||||||
Log::debug('Uploaded file', ['name' => $upload->getClientOriginalName(), 'size' => $upload->getSize(), 'mime' => $upload->getClientMimeType()]);
|
Log::debug('Uploaded file', ['name' => $upload->getClientOriginalName(), 'size' => $upload->getSize(), 'mime' => $upload->getClientMimeType()]);
|
||||||
|
}
|
||||||
|
|
||||||
// store configuration file's content into the job's configuration
|
// store configuration file's content into the job's configuration thing. Otherwise, leave it empty.
|
||||||
// thing.
|
// demo user's configuration upload is ignored completely.
|
||||||
// otherwise, leave it empty.
|
if ($request->files->has('configuration_file') && !auth()->user()->hasRole('demo')) {
|
||||||
if ($request->files->has('configuration_file')) {
|
|
||||||
/** @var UploadedFile $configFile */
|
/** @var UploadedFile $configFile */
|
||||||
$configFile = $request->files->get('configuration_file');
|
$configFile = $request->files->get('configuration_file');
|
||||||
Log::debug(
|
Log::debug(
|
||||||
@ -394,6 +414,9 @@ class ImportController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if user is demo user, replace config with prepared config:
|
||||||
|
|
||||||
|
|
||||||
return redirect(route('import.configure', [$job->key]));
|
return redirect(route('import.configure', [$job->key]));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
use Amount;
|
use Amount;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
@ -23,7 +23,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
|
||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
use Input;
|
use Illuminate\Http\Request;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
|
|
||||||
@ -43,11 +43,13 @@ class JsonController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function action()
|
public function action(Request $request)
|
||||||
{
|
{
|
||||||
$count = intval(Input::get('count')) > 0 ? intval(Input::get('count')) : 1;
|
$count = intval($request->get('count')) > 0 ? intval($request->get('count')) : 1;
|
||||||
$keys = array_keys(config('firefly.rule-actions'));
|
$keys = array_keys(config('firefly.rule-actions'));
|
||||||
$actions = [];
|
$actions = [];
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
@ -269,18 +271,18 @@ class JsonController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $what
|
* @param JournalCollectorInterface $collector
|
||||||
|
* @param string $what
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function transactionJournals($what)
|
public function transactionJournals(JournalCollectorInterface $collector, string $what)
|
||||||
{
|
{
|
||||||
$descriptions = [];
|
$descriptions = [];
|
||||||
$type = config('firefly.transactionTypesByWhat.' . $what);
|
$type = config('firefly.transactionTypesByWhat.' . $what);
|
||||||
$types = [$type];
|
$types = [$type];
|
||||||
|
|
||||||
// use journal collector instead:
|
// use journal collector instead:
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setTypes($types)->setLimit(100)->setPage(1);
|
$collector->setTypes($types)->setLimit(100)->setPage(1);
|
||||||
$journals = $collector->getJournals();
|
$journals = $collector->getJournals();
|
||||||
foreach ($journals as $j) {
|
foreach ($journals as $j) {
|
||||||
@ -296,11 +298,13 @@ class JsonController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function trigger()
|
public function trigger(Request $request)
|
||||||
{
|
{
|
||||||
$count = intval(Input::get('count')) > 0 ? intval(Input::get('count')) : 1;
|
$count = intval($request->get('count')) > 0 ? intval($request->get('count')) : 1;
|
||||||
$keys = array_keys(config('firefly.rule-triggers'));
|
$keys = array_keys(config('firefly.rule-triggers'));
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
|
@ -117,7 +117,7 @@ class NewUserController extends Controller
|
|||||||
'virtualBalance' => 0,
|
'virtualBalance' => 0,
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'accountRole' => 'defaultAsset',
|
'accountRole' => 'defaultAsset',
|
||||||
'openingBalance' => round($request->input('bank_balance'), 2),
|
'openingBalance' => round($request->input('bank_balance'), 12),
|
||||||
'openingBalanceDate' => new Carbon,
|
'openingBalanceDate' => new Carbon,
|
||||||
'openingBalanceCurrency' => intval($request->input('amount_currency_id_bank_balance')),
|
'openingBalanceCurrency' => intval($request->input('amount_currency_id_bank_balance')),
|
||||||
];
|
];
|
||||||
@ -142,7 +142,7 @@ class NewUserController extends Controller
|
|||||||
'virtualBalance' => 0,
|
'virtualBalance' => 0,
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'accountRole' => 'savingAsset',
|
'accountRole' => 'savingAsset',
|
||||||
'openingBalance' => round($request->input('savings_balance'), 2),
|
'openingBalance' => round($request->input('savings_balance'), 12),
|
||||||
'openingBalanceDate' => new Carbon,
|
'openingBalanceDate' => new Carbon,
|
||||||
'openingBalanceCurrency' => intval($request->input('amount_currency_id_savings_balance')),
|
'openingBalanceCurrency' => intval($request->input('amount_currency_id_savings_balance')),
|
||||||
];
|
];
|
||||||
@ -163,7 +163,7 @@ class NewUserController extends Controller
|
|||||||
'name' => 'Credit card',
|
'name' => 'Credit card',
|
||||||
'iban' => null,
|
'iban' => null,
|
||||||
'accountType' => 'asset',
|
'accountType' => 'asset',
|
||||||
'virtualBalance' => round($request->get('credit_card_limit'), 2),
|
'virtualBalance' => round($request->get('credit_card_limit'), 12),
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'accountRole' => 'ccAsset',
|
'accountRole' => 'ccAsset',
|
||||||
'openingBalance' => null,
|
'openingBalance' => null,
|
||||||
|
@ -20,8 +20,8 @@ use FireflyIII\Models\AccountType;
|
|||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
|
||||||
use Log;
|
use Log;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
@ -219,7 +219,7 @@ class PiggyBankController extends Controller
|
|||||||
$accounts = [];
|
$accounts = [];
|
||||||
/** @var PiggyBank $piggyBank */
|
/** @var PiggyBank $piggyBank */
|
||||||
foreach ($piggyBanks as $piggyBank) {
|
foreach ($piggyBanks as $piggyBank) {
|
||||||
$piggyBank->savedSoFar = round($piggyBank->currentRelevantRep()->currentamount, 2);
|
$piggyBank->savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||||
$piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
|
$piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
|
||||||
$piggyBank->leftToSave = bcsub($piggyBank->targetamount, strval($piggyBank->savedSoFar));
|
$piggyBank->leftToSave = bcsub($piggyBank->targetamount, strval($piggyBank->savedSoFar));
|
||||||
$piggyBank->percentage = $piggyBank->percentage > 100 ? 100 : $piggyBank->percentage;
|
$piggyBank->percentage = $piggyBank->percentage > 100 ? 100 : $piggyBank->percentage;
|
||||||
@ -234,7 +234,7 @@ class PiggyBankController extends Controller
|
|||||||
'balance' => Steam::balanceIgnoreVirtual($account, $end),
|
'balance' => Steam::balanceIgnoreVirtual($account, $end),
|
||||||
'leftForPiggyBanks' => $piggyBank->leftOnAccount($end),
|
'leftForPiggyBanks' => $piggyBank->leftOnAccount($end),
|
||||||
'sumOfSaved' => strval($piggyBank->savedSoFar),
|
'sumOfSaved' => strval($piggyBank->savedSoFar),
|
||||||
'sumOfTargets' => strval(round($piggyBank->targetamount, 2)),
|
'sumOfTargets' => $piggyBank->targetamount,
|
||||||
'leftToSave' => $piggyBank->leftToSave,
|
'leftToSave' => $piggyBank->leftToSave,
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
@ -248,13 +248,14 @@ class PiggyBankController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param PiggyBankRepositoryInterface $repository
|
* @param PiggyBankRepositoryInterface $repository
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function order(PiggyBankRepositoryInterface $repository)
|
public function order(Request $request, PiggyBankRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$data = Input::get('order');
|
$data = $request->get('order');
|
||||||
|
|
||||||
// set all users piggy banks to zero:
|
// set all users piggy banks to zero:
|
||||||
$repository->reset();
|
$repository->reset();
|
||||||
@ -270,22 +271,24 @@ class PiggyBankController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param PiggyBankRepositoryInterface $repository
|
* @param PiggyBankRepositoryInterface $repository
|
||||||
* @param PiggyBank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function postAdd(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
public function postAdd(Request $request, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
$amount = strval(round(Input::get('amount'), 2));
|
$amount = $request->get('amount');
|
||||||
|
Log::debug(sprintf('Found amount is %s', $amount));
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
$date = session('end', Carbon::now()->endOfMonth());
|
$date = session('end', Carbon::now()->endOfMonth());
|
||||||
$leftOnAccount = $piggyBank->leftOnAccount($date);
|
$leftOnAccount = $piggyBank->leftOnAccount($date);
|
||||||
$savedSoFar = strval($piggyBank->currentRelevantRep()->currentamount);
|
$savedSoFar = strval($piggyBank->currentRelevantRep()->currentamount);
|
||||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||||
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);
|
$maxAmount = strval(min(round($leftOnAccount, 12), round($leftToSave, 12)));
|
||||||
|
|
||||||
if ($amount <= $maxAmount) {
|
if (bccomp($amount, $maxAmount) <= 0) {
|
||||||
$repetition = $piggyBank->currentRelevantRep();
|
$repetition = $piggyBank->currentRelevantRep();
|
||||||
$currentAmount = $repetition->currentamount ?? '0';
|
$currentAmount = $repetition->currentamount ?? '0';
|
||||||
$repetition->currentamount = bcadd($currentAmount, $amount);
|
$repetition->currentamount = bcadd($currentAmount, $amount);
|
||||||
@ -309,18 +312,19 @@ class PiggyBankController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param PiggyBankRepositoryInterface $repository
|
* @param PiggyBankRepositoryInterface $repository
|
||||||
* @param PiggyBank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
public function postRemove(Request $request, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
$amount = strval(round(Input::get('amount'), 2));
|
$amount = strval(round($request->get('amount'), 12));
|
||||||
|
|
||||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||||
|
|
||||||
if ($amount <= $savedSoFar) {
|
if (bccomp($amount, $savedSoFar) === -1) {
|
||||||
$repetition = $piggyBank->currentRelevantRep();
|
$repetition = $piggyBank->currentRelevantRep();
|
||||||
$repetition->currentamount = bcsub($repetition->currentamount, $amount);
|
$repetition->currentamount = bcsub($repetition->currentamount, $amount);
|
||||||
$repetition->save();
|
$repetition->save();
|
||||||
@ -394,7 +398,7 @@ class PiggyBankController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.stored_piggy_bank', ['name' => e($piggyBank->name)])));
|
Session::flash('success', strval(trans('firefly.stored_piggy_bank', ['name' => e($piggyBank->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
Session::put('piggy-banks.create.fromStore', true);
|
Session::put('piggy-banks.create.fromStore', true);
|
||||||
|
|
||||||
return redirect(route('piggy-banks.create'))->withInput();
|
return redirect(route('piggy-banks.create'))->withInput();
|
||||||
@ -420,7 +424,7 @@ class PiggyBankController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_piggy_bank', ['name' => e($piggyBank->name)])));
|
Session::flash('success', strval(trans('firefly.updated_piggy_bank', ['name' => e($piggyBank->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
Session::put('piggy-banks.edit.fromUpdate', true);
|
Session::put('piggy-banks.edit.fromUpdate', true);
|
||||||
|
|
||||||
return redirect(route('piggy-banks.edit', [$piggyBank->id]));
|
return redirect(route('piggy-banks.edit', [$piggyBank->id]));
|
||||||
|
@ -17,7 +17,7 @@ namespace FireflyIII\Http\Controllers\Popup;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collection\BalanceLine;
|
use FireflyIII\Helpers\Collection\BalanceLine;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
@ -102,7 +102,8 @@ class ReportController extends Controller
|
|||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case ($role === BalanceLine::ROLE_DEFAULTROLE && !is_null($budget->id)):
|
case ($role === BalanceLine::ROLE_DEFAULTROLE && !is_null($budget->id)):
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector
|
$collector
|
||||||
->setAccounts(new Collection([$account]))
|
->setAccounts(new Collection([$account]))
|
||||||
->setRange($attributes['startDate'], $attributes['endDate'])
|
->setRange($attributes['startDate'], $attributes['endDate'])
|
||||||
@ -112,8 +113,8 @@ class ReportController extends Controller
|
|||||||
break;
|
break;
|
||||||
case ($role === BalanceLine::ROLE_DEFAULTROLE && is_null($budget->id)):
|
case ($role === BalanceLine::ROLE_DEFAULTROLE && is_null($budget->id)):
|
||||||
$budget->name = strval(trans('firefly.no_budget'));
|
$budget->name = strval(trans('firefly.no_budget'));
|
||||||
// collector
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = new JournalCollector(auth()->user());
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector
|
$collector
|
||||||
->setAccounts(new Collection([$account]))
|
->setAccounts(new Collection([$account]))
|
||||||
->setTypes($types)
|
->setTypes($types)
|
||||||
@ -122,8 +123,8 @@ class ReportController extends Controller
|
|||||||
$journals = $collector->getJournals();
|
$journals = $collector->getJournals();
|
||||||
break;
|
break;
|
||||||
case ($role === BalanceLine::ROLE_DIFFROLE):
|
case ($role === BalanceLine::ROLE_DIFFROLE):
|
||||||
// journals no budget, not corrected by a tag.
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = new JournalCollector(auth()->user());
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector
|
$collector
|
||||||
->setAccounts(new Collection([$account]))
|
->setAccounts(new Collection([$account]))
|
||||||
->setTypes($types)
|
->setTypes($types)
|
||||||
@ -167,7 +168,8 @@ class ReportController extends Controller
|
|||||||
/** @var BudgetRepositoryInterface $repository */
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
$repository = app(BudgetRepositoryInterface::class);
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
$budget = $repository->find(intval($attributes['budgetId']));
|
$budget = $repository->find(intval($attributes['budgetId']));
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
|
|
||||||
$collector
|
$collector
|
||||||
->setAccounts($attributes['accounts'])
|
->setAccounts($attributes['accounts'])
|
||||||
@ -200,8 +202,8 @@ class ReportController extends Controller
|
|||||||
$repository = app(CategoryRepositoryInterface::class);
|
$repository = app(CategoryRepositoryInterface::class);
|
||||||
$category = $repository->find(intval($attributes['categoryId']));
|
$category = $repository->find(intval($attributes['categoryId']));
|
||||||
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
|
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
|
||||||
// get journal collector instead:
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = new JournalCollector(auth()->user());
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($attributes['accounts'])->setTypes($types)
|
$collector->setAccounts($attributes['accounts'])->setTypes($types)
|
||||||
->setRange($attributes['startDate'], $attributes['endDate'])
|
->setRange($attributes['startDate'], $attributes['endDate'])
|
||||||
->setCategory($category);
|
->setCategory($category);
|
||||||
@ -227,7 +229,8 @@ class ReportController extends Controller
|
|||||||
|
|
||||||
$account = $repository->find(intval($attributes['accountId']));
|
$account = $repository->find(intval($attributes['accountId']));
|
||||||
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
|
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setTypes($types);
|
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setTypes($types);
|
||||||
$journals = $collector->getJournals();
|
$journals = $collector->getJournals();
|
||||||
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
|
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
|
||||||
@ -262,7 +265,8 @@ class ReportController extends Controller
|
|||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$account = $repository->find(intval($attributes['accountId']));
|
$account = $repository->find(intval($attributes['accountId']));
|
||||||
$types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
|
$types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setTypes($types);
|
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setTypes($types);
|
||||||
$journals = $collector->getJournals();
|
$journals = $collector->getJournals();
|
||||||
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
|
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
|
||||||
|
@ -113,6 +113,7 @@ class PreferencesController extends Controller
|
|||||||
* @param TokenFormRequest $request
|
* @param TokenFormRequest $request
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter) // it's unused but the class does some validation.
|
||||||
*/
|
*/
|
||||||
public function postCode(TokenFormRequest $request)
|
public function postCode(TokenFormRequest $request)
|
||||||
{
|
{
|
||||||
|
@ -48,8 +48,9 @@ class OperationsController extends Controller
|
|||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
$expenses = $this->getExpenseReport($start, $end, $accounts);
|
$entries = $this->getExpenseReport($start, $end, $accounts);
|
||||||
$result = view('reports.partials.expenses', compact('expenses'))->render();
|
$type = 'expense-entry';
|
||||||
|
$result = view('reports.partials.income-expenses', compact('entries', 'type'))->render();
|
||||||
$cache->store($result);
|
$cache->store($result);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
@ -74,9 +75,10 @@ class OperationsController extends Controller
|
|||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
$income = $this->getIncomeReport($start, $end, $accounts);
|
$entries = $this->getIncomeReport($start, $end, $accounts);
|
||||||
|
$type = 'income-entry';
|
||||||
|
$result = view('reports.partials.income-expenses', compact('entries', 'type'))->render();
|
||||||
|
|
||||||
$result = view('reports.partials.income', compact('income'))->render();
|
|
||||||
$cache->store($result);
|
$cache->store($result);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
@ -230,12 +232,19 @@ class OperationsController extends Controller
|
|||||||
'id' => $opposingId,
|
'id' => $opposingId,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'sum' => '0',
|
'sum' => '0',
|
||||||
|
'average' => '0',
|
||||||
'count' => 0,
|
'count' => 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount);
|
$expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount);
|
||||||
$expenses[$opposingId]['count']++;
|
$expenses[$opposingId]['count']++;
|
||||||
}
|
}
|
||||||
|
// do averages:
|
||||||
|
foreach ($expenses as $key => $entry) {
|
||||||
|
if ($expenses[$key]['count'] > 1) {
|
||||||
|
$expenses[$key]['average'] = bcdiv($expenses[$key]['sum'], strval($expenses[$key]['count']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return $expenses;
|
return $expenses;
|
||||||
|
@ -23,7 +23,6 @@ use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use FireflyIII\Rules\TransactionMatcher;
|
use FireflyIII\Rules\TransactionMatcher;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Input;
|
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
use Session;
|
use Session;
|
||||||
@ -58,11 +57,12 @@ class RuleController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Create a new rule. It will be stored under the given $ruleGroup.
|
* Create a new rule. It will be stored under the given $ruleGroup.
|
||||||
*
|
*
|
||||||
|
* @param Request $request
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function create(RuleGroup $ruleGroup)
|
public function create(Request $request, RuleGroup $ruleGroup)
|
||||||
{
|
{
|
||||||
// count for possible present previous entered triggers/actions.
|
// count for possible present previous entered triggers/actions.
|
||||||
$triggerCount = 0;
|
$triggerCount = 0;
|
||||||
@ -73,13 +73,13 @@ class RuleController extends Controller
|
|||||||
$oldActions = [];
|
$oldActions = [];
|
||||||
|
|
||||||
// has old input?
|
// has old input?
|
||||||
if (Input::old()) {
|
if ($request->old()) {
|
||||||
// process old triggers.
|
// process old triggers.
|
||||||
$oldTriggers = $this->getPreviousTriggers();
|
$oldTriggers = $this->getPreviousTriggers($request);
|
||||||
$triggerCount = count($oldTriggers);
|
$triggerCount = count($oldTriggers);
|
||||||
|
|
||||||
// process old actions
|
// process old actions
|
||||||
$oldActions = $this->getPreviousActions();
|
$oldActions = $this->getPreviousActions($request);
|
||||||
$actionCount = count($oldActions);
|
$actionCount = count($oldActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,12 +154,13 @@ class RuleController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param RuleRepositoryInterface $repository
|
* @param RuleRepositoryInterface $repository
|
||||||
* @param Rule $rule
|
* @param Rule $rule
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function edit(RuleRepositoryInterface $repository, Rule $rule)
|
public function edit(Request $request, RuleRepositoryInterface $repository, Rule $rule)
|
||||||
{
|
{
|
||||||
$oldTriggers = $this->getCurrentTriggers($rule);
|
$oldTriggers = $this->getCurrentTriggers($rule);
|
||||||
$triggerCount = count($oldTriggers);
|
$triggerCount = count($oldTriggers);
|
||||||
@ -167,10 +168,10 @@ class RuleController extends Controller
|
|||||||
$actionCount = count($oldActions);
|
$actionCount = count($oldActions);
|
||||||
|
|
||||||
// has old input?
|
// has old input?
|
||||||
if (Input::old()) {
|
if ($request->old()) {
|
||||||
$oldTriggers = $this->getPreviousTriggers();
|
$oldTriggers = $this->getPreviousTriggers($request);
|
||||||
$triggerCount = count($oldTriggers);
|
$triggerCount = count($oldTriggers);
|
||||||
$oldActions = $this->getPreviousActions();
|
$oldActions = $this->getPreviousActions($request);
|
||||||
$actionCount = count($oldActions);
|
$actionCount = count($oldActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +256,7 @@ class RuleController extends Controller
|
|||||||
Session::flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title]));
|
Session::flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title]));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
// set value so create routine will not overwrite URL:
|
// set value so create routine will not overwrite URL:
|
||||||
Session::put('rules.create.fromStore', true);
|
Session::put('rules.create.fromStore', true);
|
||||||
|
|
||||||
@ -342,7 +343,7 @@ class RuleController extends Controller
|
|||||||
Session::flash('success', trans('firefly.updated_rule', ['title' => $rule->title]));
|
Session::flash('success', trans('firefly.updated_rule', ['title' => $rule->title]));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('rules.edit.fromUpdate', true);
|
Session::put('rules.edit.fromUpdate', true);
|
||||||
|
|
||||||
@ -461,22 +462,24 @@ class RuleController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function getPreviousActions()
|
private function getPreviousActions(Request $request)
|
||||||
{
|
{
|
||||||
$newIndex = 0;
|
$newIndex = 0;
|
||||||
$actions = [];
|
$actions = [];
|
||||||
/** @var array $oldActions */
|
/** @var array $oldActions */
|
||||||
$oldActions = is_array(Input::old('rule-action')) ? Input::old('rule-action') : [];
|
$oldActions = is_array($request->old('rule-action')) ? $request->old('rule-action') : [];
|
||||||
foreach ($oldActions as $index => $entry) {
|
foreach ($oldActions as $index => $entry) {
|
||||||
$count = ($newIndex + 1);
|
$count = ($newIndex + 1);
|
||||||
$checked = isset(Input::old('rule-action-stop')[$index]) ? true : false;
|
$checked = isset($request->old('rule-action-stop')[$index]) ? true : false;
|
||||||
$actions[] = view(
|
$actions[] = view(
|
||||||
'rules.partials.action',
|
'rules.partials.action',
|
||||||
[
|
[
|
||||||
'oldTrigger' => $entry,
|
'oldTrigger' => $entry,
|
||||||
'oldValue' => Input::old('rule-action-value')[$index],
|
'oldValue' => $request->old('rule-action-value')[$index],
|
||||||
'oldChecked' => $checked,
|
'oldChecked' => $checked,
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
]
|
]
|
||||||
@ -488,22 +491,24 @@ class RuleController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function getPreviousTriggers()
|
private function getPreviousTriggers(Request $request)
|
||||||
{
|
{
|
||||||
$newIndex = 0;
|
$newIndex = 0;
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
/** @var array $oldTriggers */
|
/** @var array $oldTriggers */
|
||||||
$oldTriggers = is_array(Input::old('rule-trigger')) ? Input::old('rule-trigger') : [];
|
$oldTriggers = is_array($request->old('rule-trigger')) ? $request->old('rule-trigger') : [];
|
||||||
foreach ($oldTriggers as $index => $entry) {
|
foreach ($oldTriggers as $index => $entry) {
|
||||||
$count = ($newIndex + 1);
|
$count = ($newIndex + 1);
|
||||||
$oldChecked = isset(Input::old('rule-trigger-stop')[$index]) ? true : false;
|
$oldChecked = isset($request->old('rule-trigger-stop')[$index]) ? true : false;
|
||||||
$triggers[] = view(
|
$triggers[] = view(
|
||||||
'rules.partials.trigger',
|
'rules.partials.trigger',
|
||||||
[
|
[
|
||||||
'oldTrigger' => $entry,
|
'oldTrigger' => $entry,
|
||||||
'oldValue' => Input::old('rule-trigger-value')[$index],
|
'oldValue' => $request->old('rule-trigger-value')[$index],
|
||||||
'oldChecked' => $oldChecked,
|
'oldChecked' => $oldChecked,
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
]
|
]
|
||||||
|
@ -22,7 +22,7 @@ use FireflyIII\Models\AccountType;
|
|||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use Input;
|
use Illuminate\Http\Request;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
use URL;
|
use URL;
|
||||||
@ -94,17 +94,17 @@ class RuleGroupController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
* @param RuleGroupRepositoryInterface $repository
|
* @param RuleGroupRepositoryInterface $repository
|
||||||
*
|
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function destroy(RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
|
public function destroy(Request $request, RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||||
{
|
{
|
||||||
|
|
||||||
$title = $ruleGroup->title;
|
$title = $ruleGroup->title;
|
||||||
$moveTo = auth()->user()->ruleGroups()->find(intval(Input::get('move_rules_before_delete')));
|
$moveTo = auth()->user()->ruleGroups()->find(intval($request->get('move_rules_before_delete')));
|
||||||
|
|
||||||
$repository->destroy($ruleGroup, $moveTo);
|
$repository->destroy($ruleGroup, $moveTo);
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ class RuleGroupController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])));
|
Session::flash('success', strval(trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
// set value so create routine will not overwrite URL:
|
// set value so create routine will not overwrite URL:
|
||||||
Session::put('rule-groups.create.fromStore', true);
|
Session::put('rule-groups.create.fromStore', true);
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ class RuleGroupController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])));
|
Session::flash('success', strval(trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('rule-groups.edit.fromUpdate', true);
|
Session::put('rule-groups.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Requests\TagFormRequest;
|
use FireflyIII\Http\Requests\TagFormRequest;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
use URL;
|
use URL;
|
||||||
@ -68,17 +68,20 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function create()
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
$subTitle = trans('firefly.new_tag');
|
$subTitle = trans('firefly.new_tag');
|
||||||
$subTitleIcon = 'fa-tag';
|
$subTitleIcon = 'fa-tag';
|
||||||
|
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
|
||||||
|
|
||||||
$preFilled = [
|
$preFilled = [
|
||||||
'tagMode' => 'nothing',
|
'tagMode' => 'nothing',
|
||||||
];
|
];
|
||||||
if (!Input::old('tagMode')) {
|
if (!$request->old('tagMode')) {
|
||||||
Session::flash('preFilled', $preFilled);
|
Session::flash('preFilled', $preFilled);
|
||||||
}
|
}
|
||||||
// put previous url in session if not redirect from store (not "create another").
|
// put previous url in session if not redirect from store (not "create another").
|
||||||
@ -89,7 +92,7 @@ class TagController extends Controller
|
|||||||
Session::flash('gaEventCategory', 'tags');
|
Session::flash('gaEventCategory', 'tags');
|
||||||
Session::flash('gaEventAction', 'create');
|
Session::flash('gaEventAction', 'create');
|
||||||
|
|
||||||
return view('tags.create', compact('subTitle', 'subTitleIcon'));
|
return view('tags.create', compact('subTitle', 'subTitleIcon', 'apiKey'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,6 +139,7 @@ class TagController extends Controller
|
|||||||
{
|
{
|
||||||
$subTitle = trans('firefly.edit_tag', ['tag' => $tag->tag]);
|
$subTitle = trans('firefly.edit_tag', ['tag' => $tag->tag]);
|
||||||
$subTitleIcon = 'fa-tag';
|
$subTitleIcon = 'fa-tag';
|
||||||
|
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default tag options (again)
|
* Default tag options (again)
|
||||||
@ -165,7 +169,7 @@ class TagController extends Controller
|
|||||||
Session::flash('gaEventCategory', 'tags');
|
Session::flash('gaEventCategory', 'tags');
|
||||||
Session::flash('gaEventAction', 'edit');
|
Session::flash('gaEventAction', 'edit');
|
||||||
|
|
||||||
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions'));
|
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions', 'apiKey'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -206,21 +210,21 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param JournalCollectorInterface $collector
|
||||||
* @param Tag $tag
|
* @param Tag $tag
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function show(Tag $tag)
|
public function show(Request $request, JournalCollectorInterface $collector, Tag $tag)
|
||||||
{
|
{
|
||||||
$subTitle = $tag->tag;
|
$subTitle = $tag->tag;
|
||||||
$subTitleIcon = 'fa-tag';
|
$subTitleIcon = 'fa-tag';
|
||||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||||
|
|
||||||
// use collector:
|
// use collector:
|
||||||
// replace with journal collector:
|
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTag($tag)->withBudgetInformation()->withCategoryInformation();
|
||||||
$collector = new JournalCollector(auth()->user());
|
|
||||||
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTag($tag);
|
|
||||||
$journals = $collector->getPaginatedJournals();
|
$journals = $collector->getPaginatedJournals();
|
||||||
$journals->setPath('tags/show/' . $tag->id);
|
$journals->setPath('tags/show/' . $tag->id);
|
||||||
|
|
||||||
@ -248,7 +252,7 @@ class TagController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.created_tag', ['tag' => e($data['tag'])])));
|
Session::flash('success', strval(trans('firefly.created_tag', ['tag' => e($data['tag'])])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('create_another')) === 1) {
|
if (intval($request->get('create_another')) === 1) {
|
||||||
// set value so create routine will not overwrite URL:
|
// set value so create routine will not overwrite URL:
|
||||||
Session::put('tags.create.fromStore', true);
|
Session::put('tags.create.fromStore', true);
|
||||||
|
|
||||||
@ -275,7 +279,7 @@ class TagController extends Controller
|
|||||||
Session::flash('success', strval(trans('firefly.updated_tag', ['tag' => e($data['tag'])])));
|
Session::flash('success', strval(trans('firefly.updated_tag', ['tag' => e($data['tag'])])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
if (intval(Input::get('return_to_edit')) === 1) {
|
if (intval($request->get('return_to_edit')) === 1) {
|
||||||
// set value so edit routine will not overwrite URL:
|
// set value so edit routine will not overwrite URL:
|
||||||
Session::put('tags.edit.fromUpdate', true);
|
Session::put('tags.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
@ -217,8 +217,8 @@ class ConvertController extends Controller
|
|||||||
switch ($joined) {
|
switch ($joined) {
|
||||||
default:
|
default:
|
||||||
throw new FireflyException('Cannot handle ' . $joined);
|
throw new FireflyException('Cannot handle ' . $joined);
|
||||||
case TransactionType::WITHDRAWAL . '-' . TransactionType::DEPOSIT: # one
|
case TransactionType::WITHDRAWAL . '-' . TransactionType::DEPOSIT: // one
|
||||||
case TransactionType::TRANSFER . '-' . TransactionType::DEPOSIT: #six
|
case TransactionType::TRANSFER . '-' . TransactionType::DEPOSIT: // six
|
||||||
$data = [
|
$data = [
|
||||||
'name' => $data['source_account_revenue'],
|
'name' => $data['source_account_revenue'],
|
||||||
'accountType' => 'revenue',
|
'accountType' => 'revenue',
|
||||||
@ -228,14 +228,14 @@ class ConvertController extends Controller
|
|||||||
];
|
];
|
||||||
$source = $accountRepository->store($data);
|
$source = $accountRepository->store($data);
|
||||||
break;
|
break;
|
||||||
case TransactionType::WITHDRAWAL . '-' . TransactionType::TRANSFER: # two
|
case TransactionType::WITHDRAWAL . '-' . TransactionType::TRANSFER: // two
|
||||||
case TransactionType::TRANSFER . '-' . TransactionType::WITHDRAWAL: #five
|
case TransactionType::TRANSFER . '-' . TransactionType::WITHDRAWAL: // five
|
||||||
$source = $sourceAccount;
|
$source = $sourceAccount;
|
||||||
break;
|
break;
|
||||||
case TransactionType::DEPOSIT . '-' . TransactionType::WITHDRAWAL: # three
|
case TransactionType::DEPOSIT . '-' . TransactionType::WITHDRAWAL: // three
|
||||||
$source = $destinationAccount;
|
$source = $destinationAccount;
|
||||||
break;
|
break;
|
||||||
case TransactionType::DEPOSIT . '-' . TransactionType::TRANSFER: # four
|
case TransactionType::DEPOSIT . '-' . TransactionType::TRANSFER: // four
|
||||||
$source = $accountRepository->find(intval($data['source_account_asset']));
|
$source = $accountRepository->find(intval($data['source_account_asset']));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ class MassController extends Controller
|
|||||||
'source_account_name' => $sourceAccountName,
|
'source_account_name' => $sourceAccountName,
|
||||||
'destination_account_id' => intval($destAccountId),
|
'destination_account_id' => intval($destAccountId),
|
||||||
'destination_account_name' => $destAccountName,
|
'destination_account_name' => $destAccountName,
|
||||||
'amount' => round($request->get('amount')[$journal->id], 4),
|
'amount' => round($request->get('amount')[$journal->id], 12),
|
||||||
'currency_id' => intval($request->get('amount_currency_id_amount_' . $journal->id)),
|
'currency_id' => intval($request->get('amount_currency_id_amount_' . $journal->id)),
|
||||||
'date' => new Carbon($request->get('date')[$journal->id]),
|
'date' => new Carbon($request->get('date')[$journal->id]),
|
||||||
'interest_date' => $journal->interest_date,
|
'interest_date' => $journal->interest_date,
|
||||||
|
@ -265,8 +265,8 @@ class SingleController extends Controller
|
|||||||
|
|
||||||
return redirect(route('transactions.create', [$request->input('what')]))->withInput();
|
return redirect(route('transactions.create', [$request->input('what')]))->withInput();
|
||||||
}
|
}
|
||||||
|
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||||
$this->attachments->saveAttachmentsForModel($journal);
|
$this->attachments->saveAttachmentsForModel($journal, $files);
|
||||||
|
|
||||||
// store the journal only, flash the rest.
|
// store the journal only, flash the rest.
|
||||||
if (count($this->attachments->getErrors()->get('attachments')) > 0) {
|
if (count($this->attachments->getErrors()->get('attachments')) > 0) {
|
||||||
@ -315,7 +315,8 @@ class SingleController extends Controller
|
|||||||
|
|
||||||
$data = $request->getJournalData();
|
$data = $request->getJournalData();
|
||||||
$journal = $repository->update($journal, $data);
|
$journal = $repository->update($journal, $data);
|
||||||
$this->attachments->saveAttachmentsForModel($journal);
|
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||||
|
$this->attachments->saveAttachmentsForModel($journal, $files);
|
||||||
|
|
||||||
// flash errors
|
// flash errors
|
||||||
if (count($this->attachments->getErrors()->get('attachments')) > 0) {
|
if (count($this->attachments->getErrors()->get('attachments')) > 0) {
|
||||||
|
@ -138,9 +138,9 @@ class SplitController extends Controller
|
|||||||
|
|
||||||
$data = $this->arrayFromInput($request);
|
$data = $this->arrayFromInput($request);
|
||||||
$journal = $repository->updateSplitJournal($journal, $data);
|
$journal = $repository->updateSplitJournal($journal, $data);
|
||||||
|
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||||
// save attachments:
|
// save attachments:
|
||||||
$this->attachments->saveAttachmentsForModel($journal);
|
$this->attachments->saveAttachmentsForModel($journal, $files);
|
||||||
|
|
||||||
event(new UpdatedTransactionJournal($journal));
|
event(new UpdatedTransactionJournal($journal));
|
||||||
// update, get events by date and sort DESC
|
// update, get events by date and sort DESC
|
||||||
@ -257,7 +257,7 @@ class SplitController extends Controller
|
|||||||
'source_account_name' => $transaction['source_account_name'],
|
'source_account_name' => $transaction['source_account_name'],
|
||||||
'destination_account_id' => $transaction['destination_account_id'],
|
'destination_account_id' => $transaction['destination_account_id'],
|
||||||
'destination_account_name' => $transaction['destination_account_name'],
|
'destination_account_name' => $transaction['destination_account_name'],
|
||||||
'amount' => round($transaction['destination_amount'], 2),
|
'amount' => round($transaction['destination_amount'], 12),
|
||||||
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
||||||
'category' => $transaction['category'],
|
'category' => $transaction['category'],
|
||||||
];
|
];
|
||||||
@ -292,7 +292,7 @@ class SplitController extends Controller
|
|||||||
'source_account_name' => $transaction['source_account_name'] ?? '',
|
'source_account_name' => $transaction['source_account_name'] ?? '',
|
||||||
'destination_account_id' => $transaction['destination_account_id'] ?? 0,
|
'destination_account_id' => $transaction['destination_account_id'] ?? 0,
|
||||||
'destination_account_name' => $transaction['destination_account_name'] ?? '',
|
'destination_account_name' => $transaction['destination_account_name'] ?? '',
|
||||||
'amount' => round($transaction['amount'] ?? 0, 2),
|
'amount' => round($transaction['amount'] ?? 0, 12),
|
||||||
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
||||||
'category' => $transaction['category'] ?? '',
|
'category' => $transaction['category'] ?? '',
|
||||||
];
|
];
|
||||||
|
@ -71,10 +71,10 @@ class TransactionController extends Controller
|
|||||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||||
|
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts();
|
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts();
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end)->withBudgetInformation()->withCategoryInformation();
|
||||||
|
|
||||||
// do not filter transfers if $what = transfer.
|
// do not filter transfers if $what = transfer.
|
||||||
if (!in_array($what, ['transfer', 'transfers'])) {
|
if (!in_array($what, ['transfer', 'transfers'])) {
|
||||||
@ -123,7 +123,7 @@ class TransactionController extends Controller
|
|||||||
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
|
||||||
|
|
||||||
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts();
|
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts()->withBudgetInformation()->withCategoryInformation();
|
||||||
|
|
||||||
// do not filter transfers if $what = transfer.
|
// do not filter transfers if $what = transfer.
|
||||||
if (!in_array($what, ['transfer', 'transfers'])) {
|
if (!in_array($what, ['transfer', 'transfers'])) {
|
||||||
@ -160,9 +160,10 @@ class TransactionController extends Controller
|
|||||||
|
|
||||||
Log::debug(sprintf('Transaction index by date will show between %s and %s', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
Log::debug(sprintf('Transaction index by date will show between %s and %s', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||||
|
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts();
|
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts();
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end)->withBudgetInformation()->withCategoryInformation();
|
||||||
|
|
||||||
// do not filter transfers if $what = transfer.
|
// do not filter transfers if $what = transfer.
|
||||||
if (!in_array($what, ['transfer', 'transfers'])) {
|
if (!in_array($what, ['transfer', 'transfers'])) {
|
||||||
|
@ -17,8 +17,6 @@ use FireflyIII\Http\Middleware\AuthenticateTwoFactor;
|
|||||||
use FireflyIII\Http\Middleware\Binder;
|
use FireflyIII\Http\Middleware\Binder;
|
||||||
use FireflyIII\Http\Middleware\EncryptCookies;
|
use FireflyIII\Http\Middleware\EncryptCookies;
|
||||||
use FireflyIII\Http\Middleware\IsAdmin;
|
use FireflyIII\Http\Middleware\IsAdmin;
|
||||||
use FireflyIII\Http\Middleware\IsConfirmed;
|
|
||||||
use FireflyIII\Http\Middleware\IsNotConfirmed;
|
|
||||||
use FireflyIII\Http\Middleware\Range;
|
use FireflyIII\Http\Middleware\Range;
|
||||||
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
|
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
|
||||||
use FireflyIII\Http\Middleware\RedirectIfTwoFactorAuthenticated;
|
use FireflyIII\Http\Middleware\RedirectIfTwoFactorAuthenticated;
|
||||||
@ -124,7 +122,6 @@ class Kernel extends HttpKernel
|
|||||||
SubstituteBindings::class,
|
SubstituteBindings::class,
|
||||||
Authenticate::class,
|
Authenticate::class,
|
||||||
AuthenticateTwoFactor::class,
|
AuthenticateTwoFactor::class,
|
||||||
IsNotConfirmed::class,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
// MUST be logged in
|
// MUST be logged in
|
||||||
@ -153,7 +150,6 @@ class Kernel extends HttpKernel
|
|||||||
SubstituteBindings::class,
|
SubstituteBindings::class,
|
||||||
Authenticate::class,
|
Authenticate::class,
|
||||||
AuthenticateTwoFactor::class,
|
AuthenticateTwoFactor::class,
|
||||||
IsConfirmed::class,
|
|
||||||
Range::class,
|
Range::class,
|
||||||
Binder::class,
|
Binder::class,
|
||||||
],
|
],
|
||||||
@ -171,11 +167,9 @@ class Kernel extends HttpKernel
|
|||||||
SubstituteBindings::class,
|
SubstituteBindings::class,
|
||||||
Authenticate::class,
|
Authenticate::class,
|
||||||
AuthenticateTwoFactor::class,
|
AuthenticateTwoFactor::class,
|
||||||
IsConfirmed::class,
|
|
||||||
IsAdmin::class,
|
IsAdmin::class,
|
||||||
Range::class,
|
Range::class,
|
||||||
Binder::class,
|
Binder::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,8 +26,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
class IsAdmin
|
class IsAdmin
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request. User account must be confirmed for this routine to let
|
* Handle an incoming request. Must be admin.
|
||||||
* the user pass.
|
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* IsConfirmed.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\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use FireflyConfig;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Preferences;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class IsConfirmed
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Http\Middleware
|
|
||||||
*/
|
|
||||||
class IsConfirmed
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle an incoming request. User account must be confirmed for this routine to let
|
|
||||||
* the user pass.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
* @param string|null $guard
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle(Request $request, Closure $next, $guard = null)
|
|
||||||
{
|
|
||||||
if (Auth::guard($guard)->guest()) {
|
|
||||||
if ($request->ajax()) {
|
|
||||||
return response('Unauthorized.', 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->guest('login');
|
|
||||||
}
|
|
||||||
// must the user be confirmed in the first place?
|
|
||||||
$confirmPreference = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'));
|
|
||||||
$mustConfirmAccount = false;
|
|
||||||
if (!is_null($confirmPreference)) {
|
|
||||||
$mustConfirmAccount = $confirmPreference->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// user must be logged in, then continue:
|
|
||||||
$isConfirmed = Preferences::get('user_confirmed', false)->data;
|
|
||||||
|
|
||||||
if ($isConfirmed === false && $mustConfirmAccount === true) {
|
|
||||||
|
|
||||||
// user account is not confirmed, redirect to
|
|
||||||
// confirmation page:
|
|
||||||
return redirect(route('confirmation_error'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* IsNotConfirmed.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\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use FireflyConfig;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Log;
|
|
||||||
use Preferences;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class IsNotConfirmed
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Http\Middleware
|
|
||||||
*/
|
|
||||||
class IsNotConfirmed
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle an incoming request. User account must be confirmed for this routine to let
|
|
||||||
* the user pass.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
* @param string|null $guard
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle(Request $request, Closure $next, $guard = null)
|
|
||||||
{
|
|
||||||
if (Auth::guard($guard)->guest()) {
|
|
||||||
if ($request->ajax()) {
|
|
||||||
return response('Unauthorized.', 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->guest('login');
|
|
||||||
}
|
|
||||||
// must the user be confirmed in the first place?
|
|
||||||
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'))->data;
|
|
||||||
Log::debug(sprintf('mustConfirmAccount is %s', $mustConfirmAccount));
|
|
||||||
// user must be logged in, then continue:
|
|
||||||
$isConfirmed = Preferences::get('user_confirmed', false)->data;
|
|
||||||
Log::debug(sprintf('isConfirmed is %s', $isConfirmed));
|
|
||||||
if ($isConfirmed || $mustConfirmAccount === false) {
|
|
||||||
Log::debug('User is confirmed or user does not have to confirm account. Redirect home.');
|
|
||||||
|
|
||||||
// user account is confirmed, simply send them home.
|
|
||||||
return redirect(route('home'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,6 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Middleware;
|
namespace FireflyIII\Http\Middleware;
|
||||||
|
|
||||||
|
use Amount;
|
||||||
use App;
|
use App;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Closure;
|
use Closure;
|
||||||
@ -109,19 +110,21 @@ class Range
|
|||||||
$monthFormat = (string)trans('config.month');
|
$monthFormat = (string)trans('config.month');
|
||||||
$monthAndDayFormat = (string)trans('config.month_and_day');
|
$monthAndDayFormat = (string)trans('config.month_and_day');
|
||||||
$dateTimeFormat = (string)trans('config.date_time');
|
$dateTimeFormat = (string)trans('config.date_time');
|
||||||
|
$defaultCurrency = Amount::getDefaultCurrency();
|
||||||
|
|
||||||
// change localeconv to a new array:
|
// change localeconv to a new array:
|
||||||
$numberFormatter = numfmt_create($lang, NumberFormatter::CURRENCY);
|
$numberFormatter = numfmt_create($lang, NumberFormatter::CURRENCY);
|
||||||
$localeconv = [
|
$localeconv = [
|
||||||
'mon_decimal_point' => $numberFormatter->getSymbol($numberFormatter->getAttribute(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL)),
|
'mon_decimal_point' => $numberFormatter->getSymbol($numberFormatter->getAttribute(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL)),
|
||||||
'mon_thousands_sep' => $numberFormatter->getSymbol($numberFormatter->getAttribute(NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL)),
|
'mon_thousands_sep' => $numberFormatter->getSymbol($numberFormatter->getAttribute(NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL)),
|
||||||
'frac_digits' => $numberFormatter->getAttribute(NumberFormatter::MAX_FRACTION_DIGITS),
|
'frac_digits' => $defaultCurrency->decimal_places,
|
||||||
];
|
];
|
||||||
View::share('monthFormat', $monthFormat);
|
View::share('monthFormat', $monthFormat);
|
||||||
View::share('monthAndDayFormat', $monthAndDayFormat);
|
View::share('monthAndDayFormat', $monthAndDayFormat);
|
||||||
View::share('dateTimeFormat', $dateTimeFormat);
|
View::share('dateTimeFormat', $dateTimeFormat);
|
||||||
View::share('language', $lang);
|
View::share('language', $lang);
|
||||||
View::share('localeconv', $localeconv);
|
View::share('localeconv', $localeconv);
|
||||||
|
View::share('defaultCurrency', $defaultCurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,13 +43,13 @@ class AccountFormRequest extends Request
|
|||||||
'active' => intval($this->input('active')) === 1,
|
'active' => intval($this->input('active')) === 1,
|
||||||
'accountType' => $this->input('what'),
|
'accountType' => $this->input('what'),
|
||||||
'currency_id' => intval($this->input('currency_id')),
|
'currency_id' => intval($this->input('currency_id')),
|
||||||
'virtualBalance' => round($this->input('virtualBalance'), 2),
|
'virtualBalance' => round($this->input('virtualBalance'), 12),
|
||||||
'virtualBalanceCurrency' => intval($this->input('amount_currency_id_virtualBalance')),
|
'virtualBalanceCurrency' => intval($this->input('amount_currency_id_virtualBalance')),
|
||||||
'iban' => trim(strval($this->input('iban'))),
|
'iban' => trim(strval($this->input('iban'))),
|
||||||
'BIC' => trim(strval($this->input('BIC'))),
|
'BIC' => trim(strval($this->input('BIC'))),
|
||||||
'accountNumber' => trim(strval($this->input('accountNumber'))),
|
'accountNumber' => trim(strval($this->input('accountNumber'))),
|
||||||
'accountRole' => $this->input('accountRole'),
|
'accountRole' => $this->input('accountRole'),
|
||||||
'openingBalance' => round($this->input('openingBalance'), 2),
|
'openingBalance' => round($this->input('openingBalance'), 12),
|
||||||
'openingBalanceDate' => new Carbon((string)$this->input('openingBalanceDate')),
|
'openingBalanceDate' => new Carbon((string)$this->input('openingBalanceDate')),
|
||||||
'openingBalanceCurrency' => intval($this->input('amount_currency_id_openingBalance')),
|
'openingBalanceCurrency' => intval($this->input('amount_currency_id_openingBalance')),
|
||||||
'ccType' => $this->input('ccType'),
|
'ccType' => $this->input('ccType'),
|
||||||
|
@ -40,10 +40,10 @@ class BillFormRequest extends Request
|
|||||||
return [
|
return [
|
||||||
'name' => $this->get('name'),
|
'name' => $this->get('name'),
|
||||||
'match' => $this->get('match'),
|
'match' => $this->get('match'),
|
||||||
'amount_min' => round($this->get('amount_min'), 2),
|
'amount_min' => round($this->get('amount_min'), 12),
|
||||||
'amount_currency_id_amount_min' => intval($this->get('amount_currency_id_amount_min')),
|
'amount_currency_id_amount_min' => intval($this->get('amount_currency_id_amount_min')),
|
||||||
'amount_currency_id_amount_max' => intval($this->get('amount_currency_id_amount_max')),
|
'amount_currency_id_amount_max' => intval($this->get('amount_currency_id_amount_max')),
|
||||||
'amount_max' => round($this->get('amount_max'), 2),
|
'amount_max' => round($this->get('amount_max'), 12),
|
||||||
'date' => new Carbon($this->get('date')),
|
'date' => new Carbon($this->get('date')),
|
||||||
'repeat_freq' => $this->get('repeat_freq'),
|
'repeat_freq' => $this->get('repeat_freq'),
|
||||||
'skip' => intval($this->get('skip')),
|
'skip' => intval($this->get('skip')),
|
||||||
|
@ -37,13 +37,7 @@ class ConfigurationRequest extends Request
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'single_user_mode' => intval($this->get('single_user_mode')) === 1,
|
'single_user_mode' => intval($this->get('single_user_mode')) === 1,
|
||||||
'must_confirm_account' => intval($this->get('must_confirm_account')) === 1,
|
|
||||||
'is_demo_site' => intval($this->get('is_demo_site')) === 1,
|
'is_demo_site' => intval($this->get('is_demo_site')) === 1,
|
||||||
'mail_for_lockout' => intval($this->get('mail_for_lockout')) === 1,
|
|
||||||
'mail_for_blocked_domain' => intval($this->get('mail_for_blocked_domain')) === 1,
|
|
||||||
'mail_for_blocked_email' => intval($this->get('mail_for_blocked_email')) === 1,
|
|
||||||
'mail_for_bad_login' => intval($this->get('mail_for_bad_login')) === 1,
|
|
||||||
'mail_for_blocked_login' => intval($this->get('mail_for_blocked_login')) === 1,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,13 +48,7 @@ class ConfigurationRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'single_user_mode' => 'between:0,1|numeric',
|
'single_user_mode' => 'between:0,1|numeric',
|
||||||
'must_confirm_account' => 'between:0,1|numeric',
|
|
||||||
'is_demo_site' => 'between:0,1|numeric',
|
'is_demo_site' => 'between:0,1|numeric',
|
||||||
'mail_for_lockout' => 'between:0,1|numeric',
|
|
||||||
'mail_for_blocked_domain' => 'between:0,1|numeric',
|
|
||||||
'mail_for_blocked_email' => 'between:0,1|numeric',
|
|
||||||
'mail_for_bad_login' => 'between:0,1|numeric',
|
|
||||||
'mail_for_blocked_login' => 'between:0,1|numeric',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -39,6 +39,7 @@ class CurrencyFormRequest extends Request
|
|||||||
'name' => $this->get('name'),
|
'name' => $this->get('name'),
|
||||||
'code' => $this->get('code'),
|
'code' => $this->get('code'),
|
||||||
'symbol' => $this->get('symbol'),
|
'symbol' => $this->get('symbol'),
|
||||||
|
'decimal_places' => intval($this->get('decimal_places')),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,15 +50,17 @@ class CurrencyFormRequest extends Request
|
|||||||
{
|
{
|
||||||
|
|
||||||
$rules = [
|
$rules = [
|
||||||
'code' => 'required|min:3|max:3|unique:transaction_currencies,code',
|
|
||||||
'name' => 'required|max:48|min:1|unique:transaction_currencies,name',
|
'name' => 'required|max:48|min:1|unique:transaction_currencies,name',
|
||||||
|
'code' => 'required|min:3|max:3|unique:transaction_currencies,code',
|
||||||
'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol',
|
'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol',
|
||||||
|
'decimal_places' => 'required|min:0|max:12|numeric',
|
||||||
];
|
];
|
||||||
if (intval($this->get('id')) > 0) {
|
if (intval($this->get('id')) > 0) {
|
||||||
$rules = [
|
$rules = [
|
||||||
'code' => 'required|min:3|max:3',
|
|
||||||
'name' => 'required|max:48|min:1',
|
'name' => 'required|max:48|min:1',
|
||||||
|
'code' => 'required|min:3|max:3',
|
||||||
'symbol' => 'required|min:1|max:8',
|
'symbol' => 'required|min:1|max:8',
|
||||||
|
'decimal_places' => 'required|min:0|max:12|numeric',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class JournalFormRequest extends Request
|
|||||||
|
|
||||||
// transaction / journal data:
|
// transaction / journal data:
|
||||||
'description' => $this->getFieldOrEmptyString('description'),
|
'description' => $this->getFieldOrEmptyString('description'),
|
||||||
'amount' => round($this->get('amount'), 2),
|
'amount' => round($this->get('amount'), 12),
|
||||||
'budget_id' => intval($this->get('budget_id')),
|
'budget_id' => intval($this->get('budget_id')),
|
||||||
'category' => $this->getFieldOrEmptyString('category'),
|
'category' => $this->getFieldOrEmptyString('category'),
|
||||||
'source_account_id' => intval($this->get('source_account_id')),
|
'source_account_id' => intval($this->get('source_account_id')),
|
||||||
|
@ -41,7 +41,7 @@ class PiggyBankFormRequest extends Request
|
|||||||
'name' => trim($this->get('name')),
|
'name' => trim($this->get('name')),
|
||||||
'startdate' => new Carbon,
|
'startdate' => new Carbon,
|
||||||
'account_id' => intval($this->get('account_id')),
|
'account_id' => intval($this->get('account_id')),
|
||||||
'targetamount' => round($this->get('targetamount'), 2),
|
'targetamount' => round($this->get('targetamount'), 12),
|
||||||
'targetdate' => strlen(strval($this->get('targetdate'))) > 0 ? new Carbon($this->get('targetdate')) : null,
|
'targetdate' => strlen(strval($this->get('targetdate'))) > 0 ? new Carbon($this->get('targetdate')) : null,
|
||||||
'note' => trim(strval($this->get('note'))),
|
'note' => trim(strval($this->get('note'))),
|
||||||
];
|
];
|
||||||
|
@ -93,7 +93,7 @@ class SplitJournalFormRequest extends Request
|
|||||||
$category = $this->get('category')[$index] ?? '';
|
$category = $this->get('category')[$index] ?? '';
|
||||||
$transaction = [
|
$transaction = [
|
||||||
'description' => $description,
|
'description' => $description,
|
||||||
'amount' => round($this->get('amount')[$index], 2),
|
'amount' => round($this->get('amount')[$index], 12),
|
||||||
'budget_id' => $this->get('budget_id')[$index] ? intval($this->get('budget_id')[$index]) : 0,
|
'budget_id' => $this->get('budget_id')[$index] ? intval($this->get('budget_id')[$index]) : 0,
|
||||||
'category' => trim($category),
|
'category' => trim($category),
|
||||||
'source_account_id' => isset($this->get('source_account_id')[$index])
|
'source_account_id' => isset($this->get('source_account_id')[$index])
|
||||||
|
@ -17,9 +17,9 @@ use FireflyIII\Models\Account;
|
|||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Models\Bill;
|
use FireflyIII\Models\Bill;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\Rule;
|
use FireflyIII\Models\Rule;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
@ -274,11 +274,20 @@ Breadcrumbs::register(
|
|||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'budgets.show.repetition', function (BreadCrumbGenerator $breadcrumbs, Budget $budget, LimitRepetition $repetition) {
|
'budgets.show.limit', function (BreadCrumbGenerator $breadcrumbs, Budget $budget, BudgetLimit $budgetLimit) {
|
||||||
$breadcrumbs->parent('budgets.index');
|
$breadcrumbs->parent('budgets.index');
|
||||||
$breadcrumbs->push(e($budget->name), route('budgets.show.repetition', [$budget->id, $repetition->id]));
|
$breadcrumbs->push(e($budget->name), route('budgets.show', [$budget->id]));
|
||||||
|
|
||||||
|
$title = trans(
|
||||||
|
'firefly.budget_in_period_breadcrumb', [
|
||||||
|
'name' => $budget->name,
|
||||||
|
'start' => $budgetLimit->start_date->formatLocalized(strval(trans('config.month_and_day'))),
|
||||||
|
'end' => $budgetLimit->end_date->formatLocalized(strval(trans('config.month_and_day'))),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$breadcrumbs->push(
|
$breadcrumbs->push(
|
||||||
Navigation::periodShow($repetition->startdate, $repetition->budgetLimit->repeat_freq), route('budgets.show', [$budget->id, $repetition->id])
|
$title, route('budgets.show.limit', [$budget->id, $budgetLimit->id])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -320,6 +329,14 @@ Breadcrumbs::register(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Breadcrumbs::register(
|
||||||
|
'categories.show.all', function (BreadCrumbGenerator $breadcrumbs, Category $category) {
|
||||||
|
$breadcrumbs->parent('categories.index');
|
||||||
|
$breadcrumbs->push(e($category->name) . '(' . strtolower(trans('firefly.all_periods')) . ')', route('categories.show.all', [$category->id]));
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'categories.show.date', function (BreadCrumbGenerator $breadcrumbs, Category $category, Carbon $date) {
|
'categories.show.date', function (BreadCrumbGenerator $breadcrumbs, Category $category, Carbon $date) {
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class Amount extends BasicConverter implements ConverterInterface
|
|||||||
$this->setCertainty(90);
|
$this->setCertainty(90);
|
||||||
|
|
||||||
|
|
||||||
return round(floatval($value), 4);
|
return round(floatval($value), 12);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Jobs;
|
namespace FireflyIII\Jobs;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
use FireflyIII\Rules\Processor;
|
use FireflyIII\Rules\Processor;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@ -155,7 +155,8 @@ class ExecuteRuleGroupOnExistingTransactions extends Job implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
protected function collectJournals()
|
protected function collectJournals()
|
||||||
{
|
{
|
||||||
$collector = new JournalCollector(auth()->user());
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
|
||||||
$collector->setAccounts($this->accounts)->setRange($this->startDate, $this->endDate);
|
$collector->setAccounts($this->accounts)->setRange($this->startDate, $this->endDate);
|
||||||
|
|
||||||
return $collector->getJournals();
|
return $collector->getJournals();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user