mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.6.3'
This commit is contained in:
commit
57d6677131
8
.github/CONTRIBUTING.md
vendored
8
.github/CONTRIBUTING.md
vendored
@ -6,14 +6,6 @@
|
|||||||
|
|
||||||
I am always interested in expanding Firefly III's many features. If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.github.io/requested-features/).
|
I am always interested in expanding Firefly III's many features. If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.github.io/requested-features/).
|
||||||
|
|
||||||
## Bugs
|
|
||||||
|
|
||||||
First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://firefly-iii.nder.be/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority!
|
|
||||||
|
|
||||||
## Installation problems
|
|
||||||
|
|
||||||
Please take the time to read the [installation guide FAQ](https://firefly-iii.github.io/installation-guide-faq/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can.
|
|
||||||
|
|
||||||
## Pull requests
|
## Pull requests
|
||||||
|
|
||||||
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `master` branch.
|
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `master` branch.
|
||||||
|
11
.github/SUPPORT.md
vendored
Normal file
11
.github/SUPPORT.md
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Welcome to Firefly III on Github!
|
||||||
|
|
||||||
|
:+1::tada: Thank you for taking the time to contribute something to Firefly III!
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://firefly-iii.nder.be/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority!
|
||||||
|
|
||||||
|
## Installation problems
|
||||||
|
|
||||||
|
Please take the time to read the [installation guide FAQ](https://firefly-iii.github.io/installation-guide-faq/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can.
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ Homestead.json
|
|||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
.env
|
.env
|
||||||
public/google*.html
|
public/google*.html
|
||||||
|
report.html
|
||||||
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -2,6 +2,36 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
## [4.6.3] - 2017-07-23
|
||||||
|
|
||||||
|
This will be the last release to support PHP 7.0.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- New guidelines and new introduction tour to aid new users.
|
||||||
|
- Rules can now be applied at will to transactions, not just rule groups.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Improved category overview.
|
||||||
|
- Improved budget overview.
|
||||||
|
- Improved budget report.
|
||||||
|
- Improved command line import responsiveness and speed.
|
||||||
|
- All code comparisons are now strict.
|
||||||
|
- Improve search page.
|
||||||
|
- Charts are easier to read thanks to @simonsmiley
|
||||||
|
- Fixed #708.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed bug where import would not respect default account. #694
|
||||||
|
- Fixed various broken paths
|
||||||
|
- Fixed several import inconsistencies.
|
||||||
|
- Various bug fixes.
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [4.6.2] - 2017-07-08
|
## [4.6.2] - 2017-07-08
|
||||||
### Added
|
### Added
|
||||||
- Links added to boxes, idea by @simonsmiley
|
- Links added to boxes, idea by @simonsmiley
|
||||||
|
@ -14,10 +14,14 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Console\Commands;
|
namespace FireflyIII\Console\Commands;
|
||||||
|
|
||||||
use Artisan;
|
use Artisan;
|
||||||
|
use FireflyIII\Import\Logging\CommandHandler;
|
||||||
|
use FireflyIII\Import\Routine\ImportRoutine;
|
||||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
use Log;
|
use Log;
|
||||||
|
use Monolog\Formatter\LineFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateImport
|
* Class CreateImport
|
||||||
@ -51,6 +55,7 @@ class CreateImport extends Command
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
|
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
@ -73,30 +78,55 @@ class CreateImport extends Command
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->info(sprintf('Going to create a job to import file: %s', $file));
|
$this->line(sprintf('Going to create a job to import file: %s', $file));
|
||||||
$this->info(sprintf('Using configuration file: %s', $configuration));
|
$this->line(sprintf('Using configuration file: %s', $configuration));
|
||||||
$this->info(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
$this->line(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
||||||
$this->info(sprintf('Type of import: %s', $type));
|
$this->line(sprintf('Type of import: %s', $type));
|
||||||
|
|
||||||
|
|
||||||
/** @var ImportJobRepositoryInterface $jobRepository */
|
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||||
$jobRepository = app(ImportJobRepositoryInterface::class);
|
$jobRepository = app(ImportJobRepositoryInterface::class);
|
||||||
$jobRepository->setUser($user);
|
$jobRepository->setUser($user);
|
||||||
$job = $jobRepository->create($type);
|
$job = $jobRepository->create($type);
|
||||||
$this->line(sprintf('Created job "%s"...', $job->key));
|
$this->line(sprintf('Created job "%s"', $job->key));
|
||||||
|
|
||||||
|
|
||||||
Artisan::call('firefly:encrypt-file', ['file' => $file, 'key' => $job->key]);
|
Artisan::call('firefly:encrypt-file', ['file' => $file, 'key' => $job->key]);
|
||||||
$this->line('Stored import data...');
|
$this->line('Stored import data...');
|
||||||
|
|
||||||
|
|
||||||
$job->configuration = $configurationData;
|
$job->configuration = $configurationData;
|
||||||
$job->status = 'configured';
|
$job->status = 'configured';
|
||||||
$job->save();
|
$job->save();
|
||||||
$this->line('Stored configuration...');
|
$this->line('Stored configuration...');
|
||||||
|
|
||||||
|
|
||||||
if ($this->option('start') === true) {
|
if ($this->option('start') === true) {
|
||||||
$this->line('The import will start in a moment. This process is not visible...');
|
$this->line('The import will start in a moment. This process is not visible...');
|
||||||
Log::debug('Go for import!');
|
Log::debug('Go for import!');
|
||||||
Artisan::call('firefly:start-import', ['key' => $job->key]);
|
|
||||||
$this->line('Done!');
|
// normally would refer to other firefly:start-import but that doesn't seem to work all to well...
|
||||||
|
$monolog = Log::getMonolog();
|
||||||
|
$handler = new CommandHandler($this);
|
||||||
|
$formatter = new LineFormatter(null, null, false, true);
|
||||||
|
$handler->setFormatter($formatter);
|
||||||
|
$monolog->pushHandler($handler);
|
||||||
|
|
||||||
|
|
||||||
|
// start the actual routine:
|
||||||
|
/** @var ImportRoutine $routine */
|
||||||
|
$routine = app(ImportRoutine::class);
|
||||||
|
$routine->setJob($job);
|
||||||
|
$routine->run();
|
||||||
|
|
||||||
|
// give feedback.
|
||||||
|
/** @var MessageBag $error */
|
||||||
|
foreach ($routine->errors as $index => $error) {
|
||||||
|
$this->error(sprintf('Error importing line #%d: %s', $index, $error));
|
||||||
|
}
|
||||||
|
$this->line(
|
||||||
|
sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->journals->count(), $routine->lines)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -36,6 +36,7 @@ use Steam;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UpgradeDatabase
|
* Class UpgradeDatabase
|
||||||
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it just touches a lot of things.
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Console\Commands
|
* @package FireflyIII\Console\Commands
|
||||||
*/
|
*/
|
||||||
@ -80,6 +81,8 @@ class UpgradeDatabase extends Command
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the currency id info to the transaction instead of the journal.
|
* Moves the currency id info to the transaction instead of the journal.
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // cannot be helped.
|
||||||
*/
|
*/
|
||||||
private function currencyInfoToTransactions()
|
private function currencyInfoToTransactions()
|
||||||
{
|
{
|
||||||
@ -96,7 +99,6 @@ class UpgradeDatabase extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// read and use the foreign amounts when present.
|
// read and use the foreign amounts when present.
|
||||||
if ($journal->hasMeta('foreign_amount')) {
|
if ($journal->hasMeta('foreign_amount')) {
|
||||||
$amount = Steam::positive($journal->getMeta('foreign_amount'));
|
$amount = Steam::positive($journal->getMeta('foreign_amount'));
|
||||||
@ -123,6 +125,8 @@ class UpgradeDatabase extends Command
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate budget repetitions to new format.
|
* Migrate budget repetitions to new format.
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 5.
|
||||||
*/
|
*/
|
||||||
private function migrateRepetitions()
|
private function migrateRepetitions()
|
||||||
{
|
{
|
||||||
@ -150,6 +154,8 @@ class UpgradeDatabase extends Command
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure there are only transfers linked to piggy bank events.
|
* Make sure there are only transfers linked to piggy bank events.
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // cannot be helped.
|
||||||
*/
|
*/
|
||||||
private function repairPiggyBanks()
|
private function repairPiggyBanks()
|
||||||
{
|
{
|
||||||
@ -157,6 +163,7 @@ class UpgradeDatabase extends Command
|
|||||||
if (!Schema::hasTable('piggy_bank_events')) {
|
if (!Schema::hasTable('piggy_bank_events')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
|
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
|
||||||
/** @var PiggyBankEvent $event */
|
/** @var PiggyBankEvent $event */
|
||||||
foreach ($set as $event) {
|
foreach ($set as $event) {
|
||||||
@ -208,7 +215,7 @@ class UpgradeDatabase extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Make sure all accounts have proper currency info.
|
||||||
*/
|
*/
|
||||||
private function updateAccountCurrencies()
|
private function updateAccountCurrencies()
|
||||||
{
|
{
|
||||||
@ -222,38 +229,34 @@ class UpgradeDatabase extends Command
|
|||||||
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
|
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
|
||||||
$accountCurrency = intval($account->getMeta('currency_id'));
|
$accountCurrency = intval($account->getMeta('currency_id'));
|
||||||
$openingBalance = $account->getOpeningBalance();
|
$openingBalance = $account->getOpeningBalance();
|
||||||
$openingBalanceCurrency = intval($openingBalance->transaction_currency_id);
|
$obCurrency = intval($openingBalance->transaction_currency_id);
|
||||||
|
|
||||||
// both 0? set to default currency:
|
// both 0? set to default currency:
|
||||||
if ($accountCurrency === 0 && $openingBalanceCurrency === 0) {
|
if ($accountCurrency === 0 && $obCurrency === 0) {
|
||||||
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $defaultCurrency->id]);
|
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $defaultCurrency->id]);
|
||||||
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
|
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// opening balance 0, account not zero? just continue:
|
|
||||||
if ($accountCurrency > 0 && $openingBalanceCurrency === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// account is set to 0, opening balance is not?
|
// account is set to 0, opening balance is not?
|
||||||
if ($accountCurrency === 0 && $openingBalanceCurrency > 0) {
|
if ($accountCurrency === 0 && $obCurrency > 0) {
|
||||||
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $openingBalanceCurrency]);
|
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $obCurrency]);
|
||||||
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
|
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// both are equal, just continue:
|
|
||||||
if ($accountCurrency === $openingBalanceCurrency) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// do not match:
|
// do not match:
|
||||||
if ($accountCurrency !== $openingBalanceCurrency) {
|
if ($accountCurrency !== $obCurrency) {
|
||||||
// update opening balance:
|
// update opening balance:
|
||||||
$openingBalance->transaction_currency_id = $accountCurrency;
|
$openingBalance->transaction_currency_id = $accountCurrency;
|
||||||
$openingBalance->save();
|
$openingBalance->save();
|
||||||
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
|
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// opening balance 0, account not zero? just continue:
|
||||||
|
// both are equal, just continue:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,10 +50,10 @@ class UpgradeFireflyInstructions extends Command
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($this->argument('task') == 'update') {
|
if ($this->argument('task') === 'update') {
|
||||||
$this->updateInstructions();
|
$this->updateInstructions();
|
||||||
}
|
}
|
||||||
if ($this->argument('task') == 'install') {
|
if ($this->argument('task') === 'install') {
|
||||||
$this->installInstructions();
|
$this->installInstructions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ class VerifyDatabase extends Command
|
|||||||
{
|
{
|
||||||
$plural = str_plural($name);
|
$plural = str_plural($name);
|
||||||
$class = sprintf('FireflyIII\Models\%s', ucfirst($name));
|
$class = sprintf('FireflyIII\Models\%s', ucfirst($name));
|
||||||
$field = $name == 'tag' ? 'tag' : 'name';
|
$field = $name === 'tag' ? 'tag' : 'name';
|
||||||
$set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id')
|
$set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id')
|
||||||
->leftJoin('users', $plural . '.user_id', '=', 'users.id')
|
->leftJoin('users', $plural . '.user_id', '=', 'users.id')
|
||||||
->distinct()
|
->distinct()
|
||||||
|
@ -88,7 +88,7 @@ final class Entry
|
|||||||
$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 . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,14 @@ class ChartJsGenerator implements GeneratorInterface
|
|||||||
];
|
];
|
||||||
|
|
||||||
// sort by value, keep keys.
|
// sort by value, keep keys.
|
||||||
|
// different sort when values are positive and when they're negative.
|
||||||
asort($data);
|
asort($data);
|
||||||
|
$next = next($data);
|
||||||
|
if (!is_bool($next) && bccomp($next, '0') === 1) {
|
||||||
|
// next is positive, sort other way around.
|
||||||
|
arsort($data);
|
||||||
|
}
|
||||||
|
unset($next);
|
||||||
|
|
||||||
$index = 0;
|
$index = 0;
|
||||||
foreach ($data as $key => $value) {
|
foreach ($data as $key => $value) {
|
||||||
|
@ -147,13 +147,13 @@ class BalanceLine
|
|||||||
if ($this->getBudget() instanceof BudgetModel && !is_null($this->getBudget()->id)) {
|
if ($this->getBudget() instanceof BudgetModel && !is_null($this->getBudget()->id)) {
|
||||||
return $this->getBudget()->name;
|
return $this->getBudget()->name;
|
||||||
}
|
}
|
||||||
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
|
if ($this->getRole() === self::ROLE_DEFAULTROLE) {
|
||||||
return strval(trans('firefly.no_budget'));
|
return strval(trans('firefly.no_budget'));
|
||||||
}
|
}
|
||||||
if ($this->getRole() == self::ROLE_TAGROLE) {
|
if ($this->getRole() === self::ROLE_TAGROLE) {
|
||||||
return strval(trans('firefly.coveredWithTags'));
|
return strval(trans('firefly.coveredWithTags'));
|
||||||
}
|
}
|
||||||
if ($this->getRole() == self::ROLE_DIFFROLE) {
|
if ($this->getRole() === self::ROLE_DIFFROLE) {
|
||||||
return strval(trans('firefly.leftUnbalanced'));
|
return strval(trans('firefly.leftUnbalanced'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ class Bill
|
|||||||
{
|
{
|
||||||
$set = $this->bills->sortBy(
|
$set = $this->bills->sortBy(
|
||||||
function (BillLine $bill) {
|
function (BillLine $bill) {
|
||||||
$active = intval($bill->getBill()->active) == 0 ? 1 : 0;
|
$active = intval($bill->getBill()->active) === 0 ? 1 : 0;
|
||||||
$name = $bill->getBill()->name;
|
$name = $bill->getBill()->name;
|
||||||
|
|
||||||
return $active . $name;
|
return $active . $name;
|
||||||
|
@ -89,8 +89,6 @@ class JournalCollector implements JournalCollectorInterface
|
|||||||
'account_types.type as account_type',
|
'account_types.type as account_type',
|
||||||
];
|
];
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $filterInternalTransfers;
|
|
||||||
/** @var bool */
|
|
||||||
private $filterTransfers = false;
|
private $filterTransfers = false;
|
||||||
/** @var array */
|
/** @var array */
|
||||||
private $filters = [InternalTransferFilter::class];
|
private $filters = [InternalTransferFilter::class];
|
||||||
@ -508,7 +506,8 @@ class JournalCollector implements JournalCollectorInterface
|
|||||||
->where('transaction_journals.user_id', $this->user->id)
|
->where('transaction_journals.user_id', $this->user->id)
|
||||||
->orderBy('transaction_journals.date', 'DESC')
|
->orderBy('transaction_journals.date', 'DESC')
|
||||||
->orderBy('transaction_journals.order', 'ASC')
|
->orderBy('transaction_journals.order', 'ASC')
|
||||||
->orderBy('transaction_journals.id', 'DESC');
|
->orderBy('transaction_journals.id', 'DESC')
|
||||||
|
->orderBy('transaction_journals.description', 'DESC');
|
||||||
|
|
||||||
$this->query = $query;
|
$this->query = $query;
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ use Route;
|
|||||||
*/
|
*/
|
||||||
class Help implements HelpInterface
|
class Help implements HelpInterface
|
||||||
{
|
{
|
||||||
|
const CACHEKEY = 'help_%s_%s';
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36';
|
protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36';
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ class Help implements HelpInterface
|
|||||||
*/
|
*/
|
||||||
public function getFromCache(string $route, string $language): string
|
public function getFromCache(string $route, string $language): string
|
||||||
{
|
{
|
||||||
$line = sprintf('help.%s.%s', $route, $language);
|
$line = sprintf(self::CACHEKEY, $route, $language);
|
||||||
|
|
||||||
return Cache::get($line);
|
return Cache::get($line);
|
||||||
}
|
}
|
||||||
@ -64,12 +65,12 @@ class Help implements HelpInterface
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Log::debug(sprintf('Status code is %d', $result->status_code));
|
Log::debug(sprintf('Status code is %d', $result->status_code));
|
||||||
|
|
||||||
if ($result->status_code === 200) {
|
if ($result->status_code === 200) {
|
||||||
$content = trim($result->body);
|
$content = trim($result->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($content) > 0) {
|
if (strlen($content) > 0) {
|
||||||
Log::debug('Content is longer than zero. Expect something.');
|
Log::debug('Content is longer than zero. Expect something.');
|
||||||
$converter = new CommonMarkConverter();
|
$converter = new CommonMarkConverter();
|
||||||
@ -98,7 +99,7 @@ class Help implements HelpInterface
|
|||||||
*/
|
*/
|
||||||
public function inCache(string $route, string $language): bool
|
public function inCache(string $route, string $language): bool
|
||||||
{
|
{
|
||||||
$line = sprintf('help.%s.%s', $route, $language);
|
$line = sprintf(self::CACHEKEY, $route, $language);
|
||||||
$result = Cache::has($line);
|
$result = Cache::has($line);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
Log::debug(sprintf('Cache has this entry: %s', 'help.' . $route . '.' . $language));
|
Log::debug(sprintf('Cache has this entry: %s', 'help.' . $route . '.' . $language));
|
||||||
@ -120,7 +121,7 @@ class Help implements HelpInterface
|
|||||||
*/
|
*/
|
||||||
public function putInCache(string $route, string $language, string $content)
|
public function putInCache(string $route, string $language, string $content)
|
||||||
{
|
{
|
||||||
$key = sprintf('help.%s.%s', $route, $language);
|
$key = sprintf(self::CACHEKEY, $route, $language);
|
||||||
if (strlen($content) > 0) {
|
if (strlen($content) > 0) {
|
||||||
Log::debug(sprintf('Will store entry in cache: %s', $key));
|
Log::debug(sprintf('Will store entry in cache: %s', $key));
|
||||||
Cache::put($key, $content, 10080); // a week.
|
Cache::put($key, $content, 10080); // a week.
|
||||||
|
@ -244,7 +244,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
|||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$leftEntry = $tagsLeft->filter(
|
$leftEntry = $tagsLeft->filter(
|
||||||
function (Tag $tag) use ($account) {
|
function (Tag $tag) use ($account) {
|
||||||
return $tag->account_id == $account->id;
|
return $tag->account_id === $account->id;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$left = '0';
|
$left = '0';
|
||||||
|
@ -56,7 +56,7 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
|||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($set as $budget) {
|
foreach ($set as $budget) {
|
||||||
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
|
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
if ($budgetLimits->count() == 0) { // no budget limit(s) for this budget
|
if ($budgetLimits->count() === 0) { // no budget limit(s) for this budget
|
||||||
|
|
||||||
$spent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);// spent for budget in time range
|
$spent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);// spent for budget in time range
|
||||||
if (bccomp($spent, '0') === -1) {
|
if (bccomp($spent, '0') === -1) {
|
||||||
|
@ -194,7 +194,7 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
return view(
|
return view(
|
||||||
'accounts.edit', compact(
|
'accounts.edit', compact(
|
||||||
'allCurrencies', 'currencySelectList', 'account', 'currency', 'subTitle', 'subTitleIcon', 'openingBalance', 'what', 'roles'
|
'allCurrencies', 'currencySelectList', 'account', 'currency', 'subTitle', 'subTitleIcon', 'what', 'roles'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ class AccountController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moment != 'all' && $loop > 1) {
|
if ($moment !== 'all' && $loop > 1) {
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||||
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
|
@ -153,7 +153,7 @@ 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';
|
||||||
}
|
}
|
||||||
$file = public_path($image);
|
$file = public_path($image);
|
||||||
|
@ -175,7 +175,7 @@ class BillController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function rescan(Request $request, BillRepositoryInterface $repository, Bill $bill)
|
public function rescan(Request $request, BillRepositoryInterface $repository, Bill $bill)
|
||||||
{
|
{
|
||||||
if (intval($bill->active) == 0) {
|
if (intval($bill->active) === 0) {
|
||||||
$request->session()->flash('warning', strval(trans('firefly.cannot_scan_inactive_bill')));
|
$request->session()->flash('warning', strval(trans('firefly.cannot_scan_inactive_bill')));
|
||||||
|
|
||||||
return redirect(URL::previous());
|
return redirect(URL::previous());
|
||||||
@ -206,7 +206,7 @@ class BillController extends Controller
|
|||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
$date = session('start');
|
$date = session('start');
|
||||||
$year = $date->year;
|
$year = $date->year;
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
|
@ -81,7 +81,7 @@ class BudgetController extends Controller
|
|||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = session('end', Carbon::now()->endOfMonth());
|
$end = session('end', Carbon::now()->endOfMonth());
|
||||||
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
|
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
|
||||||
if ($amount == 0) {
|
if ($amount === 0) {
|
||||||
$budgetLimit = null;
|
$budgetLimit = null;
|
||||||
}
|
}
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
@ -293,7 +293,7 @@ class BudgetController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
@ -318,7 +318,7 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moment != 'all' && $loop > 1) {
|
if ($moment !== 'all' && $loop > 1) {
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.without_budget_between',
|
'firefly.without_budget_between',
|
||||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
@ -357,7 +357,7 @@ class BudgetController extends Controller
|
|||||||
/** @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($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
$limits = $this->getLimits($budget, $start, $end);
|
$limits = $this->getLimits($budget, $start, $end);
|
||||||
$repetition = null;
|
$repetition = null;
|
||||||
@ -384,11 +384,11 @@ class BudgetController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit)
|
public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit)
|
||||||
{
|
{
|
||||||
if ($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.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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.budget_in_period', [
|
'firefly.budget_in_period', [
|
||||||
|
@ -199,7 +199,7 @@ class CategoryController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
@ -224,7 +224,7 @@ class CategoryController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moment != 'all' && $loop > 1) {
|
if ($moment !== 'all' && $loop > 1) {
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.without_category_between',
|
'firefly.without_category_between',
|
||||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
@ -247,7 +247,7 @@ class CategoryController extends Controller
|
|||||||
// default values:
|
// default values:
|
||||||
$subTitle = $category->name;
|
$subTitle = $category->name;
|
||||||
$subTitleIcon = 'fa-bar-chart';
|
$subTitleIcon = 'fa-bar-chart';
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$loop = 0;
|
$loop = 0;
|
||||||
@ -308,7 +308,7 @@ class CategoryController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moment != 'all' && $loop > 1) {
|
if ($moment !== 'all' && $loop > 1) {
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.journals_in_period_for_category',
|
'firefly.journals_in_period_for_category',
|
||||||
['name' => $category->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
['name' => $category->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
|
||||||
@ -463,7 +463,7 @@ class CategoryController extends Controller
|
|||||||
$accountRepository = app(AccountRepositoryInterface::class);
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||||
$first = $repository->firstUseDate($category);
|
$first = $repository->firstUseDate($category);
|
||||||
if ($first->year == 1900) {
|
if ($first->year === 1900) {
|
||||||
$first = new Carbon;
|
$first = new Carbon;
|
||||||
}
|
}
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
@ -124,7 +124,7 @@ class BudgetController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function budgetLimit(Budget $budget, BudgetLimit $budgetLimit)
|
public function budgetLimit(Budget $budget, BudgetLimit $budgetLimit)
|
||||||
{
|
{
|
||||||
if ($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.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class CategoryController extends Controller
|
|||||||
|
|
||||||
$start = $repository->firstUseDate($category);
|
$start = $repository->firstUseDate($category);
|
||||||
|
|
||||||
if ($start->year == 1900) {
|
if ($start->year === 1900) {
|
||||||
$start = new Carbon;
|
$start = new Carbon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ class CategoryReportController extends Controller
|
|||||||
// remove all empty entries to prevent cluttering:
|
// remove all empty entries to prevent cluttering:
|
||||||
$newSet = [];
|
$newSet = [];
|
||||||
foreach ($chartData as $key => $entry) {
|
foreach ($chartData as $key => $entry) {
|
||||||
if (!array_sum($entry['entries']) == 0) {
|
if (!array_sum($entry['entries']) === 0) {
|
||||||
$newSet[$key] = $chartData[$key];
|
$newSet[$key] = $chartData[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ class TagReportController extends Controller
|
|||||||
// remove all empty entries to prevent cluttering:
|
// remove all empty entries to prevent cluttering:
|
||||||
$newSet = [];
|
$newSet = [];
|
||||||
foreach ($chartData as $key => $entry) {
|
foreach ($chartData as $key => $entry) {
|
||||||
if (!array_sum($entry['entries']) == 0) {
|
if (!array_sum($entry['entries']) === 0) {
|
||||||
$newSet[$key] = $chartData[$key];
|
$newSet[$key] = $chartData[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,13 @@ use FireflyIII\Models\AccountType;
|
|||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Support\Facades\Preferences;
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
use Illuminate\Routing\Controller as BaseController;
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
use Log;
|
||||||
|
use Route;
|
||||||
use Session;
|
use Session;
|
||||||
use URL;
|
use URL;
|
||||||
use View;
|
use View;
|
||||||
@ -47,22 +50,50 @@ class Controller extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
// for transaction lists:
|
||||||
View::share('hideBudgets', false);
|
View::share('hideBudgets', false);
|
||||||
View::share('hideCategories', false);
|
View::share('hideCategories', false);
|
||||||
View::share('hideBills', false);
|
View::share('hideBills', false);
|
||||||
View::share('hideTags', false);
|
View::share('hideTags', false);
|
||||||
|
|
||||||
|
// is site a demo site?
|
||||||
$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;
|
||||||
View::share('IS_DEMO_SITE', $isDemoSite);
|
View::share('IS_DEMO_SITE', $isDemoSite);
|
||||||
View::share('DEMO_USERNAME', env('DEMO_USERNAME', ''));
|
View::share('DEMO_USERNAME', env('DEMO_USERNAME', ''));
|
||||||
View::share('DEMO_PASSWORD', env('DEMO_PASSWORD', ''));
|
View::share('DEMO_PASSWORD', env('DEMO_PASSWORD', ''));
|
||||||
|
|
||||||
// translations:
|
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
// translations for specific strings:
|
||||||
$this->monthFormat = (string)trans('config.month');
|
$this->monthFormat = (string)trans('config.month');
|
||||||
$this->monthAndDayFormat = (string)trans('config.month_and_day');
|
$this->monthAndDayFormat = (string)trans('config.month_and_day');
|
||||||
$this->dateTimeFormat = (string)trans('config.date_time');
|
$this->dateTimeFormat = (string)trans('config.date_time');
|
||||||
|
|
||||||
|
// get shown-intro-preference:
|
||||||
|
if (auth()->check()) {
|
||||||
|
// some routes have a "what" parameter, which indicates a special page:
|
||||||
|
$specificPage = is_null(Route::current()->parameter('what')) ? '' : '_' . Route::current()->parameter('what');
|
||||||
|
$page = str_replace('.', '_', Route::currentRouteName());
|
||||||
|
|
||||||
|
// indicator if user has seen the help for this page ( + special page):
|
||||||
|
$key = 'shown_demo_' . $page . $specificPage;
|
||||||
|
// is there an intro for this route?
|
||||||
|
$intro = config('intro.' . $page);
|
||||||
|
$specialIntro = config('intro.' . $page . $specificPage);
|
||||||
|
$shownDemo = true;
|
||||||
|
|
||||||
|
// either must be array and either must be > 0
|
||||||
|
if ((is_array($intro) || is_array($specialIntro)) && (count($intro) > 0 || count($specialIntro) > 0)) {
|
||||||
|
$shownDemo = Preferences::get($key, false)->data;
|
||||||
|
Log::debug(sprintf('Check if user has already seen intro with key "%s". Result is %d', $key, $shownDemo));
|
||||||
|
}
|
||||||
|
|
||||||
|
View::share('shownDemo', $shownDemo);
|
||||||
|
View::share('current_route_name', $page);
|
||||||
|
View::share('original_route_name', Route::currentRouteName());
|
||||||
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -25,63 +25,96 @@ use Response;
|
|||||||
*/
|
*/
|
||||||
class HelpController extends Controller
|
class HelpController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @var HelpInterface */
|
||||||
|
private $help;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HelpController constructor.
|
* HelpController constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
$this->help = app(HelpInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param HelpInterface $help
|
|
||||||
* @param $route
|
* @param $route
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function show(HelpInterface $help, string $route)
|
public function show(string $route)
|
||||||
{
|
{
|
||||||
|
|
||||||
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
|
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
|
||||||
|
$html = $this->getHelpText($route, $language);
|
||||||
|
|
||||||
|
return Response::json(['html' => $html]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getHelpText(string $route, string $language): string
|
||||||
|
{
|
||||||
|
// get language and default variables.
|
||||||
|
|
||||||
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
|
|
||||||
if (!$help->hasRoute($route)) {
|
// if no such route, log error and return default text.
|
||||||
|
if (!$this->help->hasRoute($route)) {
|
||||||
Log::error('No such route: ' . $route);
|
Log::error('No such route: ' . $route);
|
||||||
|
|
||||||
return Response::json($content);
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($help->inCache($route, $language)) {
|
// help content may be cached:
|
||||||
$content = $help->getFromCache($route, $language);
|
if ($this->help->inCache($route, $language)) {
|
||||||
|
$content = $this->help->getFromCache($route, $language);
|
||||||
Log::debug(sprintf('Help text %s was in cache.', $language));
|
Log::debug(sprintf('Help text %s was in cache.', $language));
|
||||||
|
|
||||||
return Response::json($content);
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = $help->getFromGithub($route, $language);
|
// get help content from Github:
|
||||||
$notYourLanguage = '<p><em>' . strval(trans('firefly.help_may_not_be_your_language')) . '</em></p>';
|
$content = $this->help->getFromGithub($route, $language);
|
||||||
|
|
||||||
// get backup language content (try English):
|
// content will have 0 length when Github failed. Try en_US when it does:
|
||||||
if (strlen($content) === 0) {
|
if (strlen($content) === 0) {
|
||||||
$language = 'en_US';
|
$language = 'en_US';
|
||||||
if ($help->inCache($route, $language)) {
|
|
||||||
|
// also check cache first:
|
||||||
|
if ($this->help->inCache($route, $language)) {
|
||||||
Log::debug(sprintf('Help text %s was in cache.', $language));
|
Log::debug(sprintf('Help text %s was in cache.', $language));
|
||||||
$content = $notYourLanguage . $help->getFromCache($route, $language);
|
$content = $this->help->getFromCache($route, $language);
|
||||||
}
|
|
||||||
if (!$help->inCache($route, $language)) {
|
return $content;
|
||||||
$content = trim($notYourLanguage . $help->getFromGithub($route, $language));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($content === $notYourLanguage) {
|
$content = $this->help->getFromGithub($route, $language);
|
||||||
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$help->putInCache($route, $language, $content);
|
// help still empty?
|
||||||
|
if (strlen($content) !== 0) {
|
||||||
|
$this->help->putInCache($route, $language, $content);
|
||||||
|
|
||||||
return Response::json($content);
|
return $content;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,11 @@ use FireflyIII\Models\AccountType;
|
|||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Route;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
use Log;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
|
use Route as RouteFacade;
|
||||||
use Session;
|
use Session;
|
||||||
use View;
|
use View;
|
||||||
|
|
||||||
@ -107,7 +109,7 @@ class HomeController extends Controller
|
|||||||
$types = config('firefly.accountTypesByIdentifier.asset');
|
$types = config('firefly.accountTypesByIdentifier.asset');
|
||||||
$count = $repository->count($types);
|
$count = $repository->count($types);
|
||||||
|
|
||||||
if ($count == 0) {
|
if ($count === 0) {
|
||||||
return redirect(route('new-user.index'));
|
return redirect(route('new-user.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +122,6 @@ class HomeController extends Controller
|
|||||||
$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());
|
||||||
$showTour = Preferences::get('tour', true)->data;
|
|
||||||
$accounts = $repository->getAccountsById($frontPage->data);
|
$accounts = $repository->getAccountsById($frontPage->data);
|
||||||
$showDepositsFrontpage = Preferences::get('showDepositsFrontpage', false)->data;
|
$showDepositsFrontpage = Preferences::get('showDepositsFrontpage', false)->data;
|
||||||
|
|
||||||
@ -137,10 +138,34 @@ class HomeController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'index', compact('count', 'showTour', 'title', 'subTitle', 'mainTitleIcon', 'transactions', 'showDepositsFrontpage', 'billCount')
|
'index', compact('count', 'title', 'subTitle', 'mainTitleIcon', 'transactions', 'showDepositsFrontpage', 'billCount')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function routes()
|
||||||
|
{
|
||||||
|
$set = RouteFacade::getRoutes();
|
||||||
|
$ignore = ['chart.', 'javascript.', 'json.', 'report-data.', 'popup.', 'debugbar.'];
|
||||||
|
/** @var Route $route */
|
||||||
|
foreach ($set as $route) {
|
||||||
|
$name = $route->getName();
|
||||||
|
if (!is_null($name) && in_array('GET', $route->methods()) && strlen($name) > 0) {
|
||||||
|
$found = false;
|
||||||
|
foreach ($ignore as $string) {
|
||||||
|
if (strpos($name, $string) !== false) {
|
||||||
|
$found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$found) {
|
||||||
|
echo 'touch ' . $route->getName() . '.md;';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ' ';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
|
@ -92,7 +92,7 @@ class ImportController extends Controller
|
|||||||
Log::debug('Now in download()', ['job' => $job->key]);
|
Log::debug('Now in download()', ['job' => $job->key]);
|
||||||
$config = $job->configuration;
|
$config = $job->configuration;
|
||||||
|
|
||||||
// TODO this is CSV import specific:
|
// This is CSV import specific:
|
||||||
$config['column-roles-complete'] = false;
|
$config['column-roles-complete'] = false;
|
||||||
$config['column-mapping-complete'] = false;
|
$config['column-mapping-complete'] = false;
|
||||||
$config['initial-config-complete'] = false;
|
$config['initial-config-complete'] = false;
|
||||||
|
166
app/Http/Controllers/Json/IntroController.php
Normal file
166
app/Http/Controllers/Json/IntroController.php
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* IntroController.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\Http\Controllers\Json;
|
||||||
|
|
||||||
|
use FireflyIII\Support\Facades\Preferences;
|
||||||
|
use Log;
|
||||||
|
use Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IntroController
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Http\Controllers\Json
|
||||||
|
*/
|
||||||
|
class IntroController
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
* @param string $specificPage
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function getIntroSteps(string $route, string $specificPage = '')
|
||||||
|
{
|
||||||
|
$steps = $this->getBasicSteps($route);
|
||||||
|
$specificSteps = $this->getSpecificSteps($route, $specificPage);
|
||||||
|
if (count($specificSteps) === 0) {
|
||||||
|
return Response::json($steps);
|
||||||
|
}
|
||||||
|
if ($this->hasOutroStep($route)) {
|
||||||
|
// save last step:
|
||||||
|
$lastStep = $steps[count($steps) - 1];
|
||||||
|
// remove last step:
|
||||||
|
array_pop($steps);
|
||||||
|
// merge arrays and add last step again
|
||||||
|
$steps = array_merge($steps, $specificSteps);
|
||||||
|
$steps[] = $lastStep;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!$this->hasOutroStep($route)) {
|
||||||
|
$steps = array_merge($steps, $specificSteps);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::json($steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasOutroStep(string $route): bool
|
||||||
|
{
|
||||||
|
$routeKey = str_replace('.', '_', $route);
|
||||||
|
$elements = config(sprintf('intro.%s', $routeKey));
|
||||||
|
if (!is_array($elements)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$keys = array_keys($elements);
|
||||||
|
|
||||||
|
return in_array('outro', $keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
* @param string $specialPage
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function postEnable(string $route, string $specialPage = '')
|
||||||
|
{
|
||||||
|
$route = str_replace('.', '_', $route);
|
||||||
|
$key = 'shown_demo_' . $route;
|
||||||
|
if ($specialPage !== '') {
|
||||||
|
$key .= '_' . $specialPage;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Going to mark the following route as NOT done: %s with special "%s" (%s)', $route, $specialPage, $key));
|
||||||
|
Preferences::set($key, false);
|
||||||
|
|
||||||
|
return Response::json(['message' => trans('firefly.intro_boxes_after_refresh')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
* @param string $specialPage
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function postFinished(string $route, string $specialPage = '')
|
||||||
|
{
|
||||||
|
$key = 'shown_demo_' . $route;
|
||||||
|
if ($specialPage !== '') {
|
||||||
|
$key .= '_' . $specialPage;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Going to mark the following route as done: %s with special "%s" (%s)', $route, $specialPage, $key));
|
||||||
|
Preferences::set($key, true);
|
||||||
|
|
||||||
|
return Response::json(['result' => sprintf('Reported demo watched for route "%s".', $route)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getBasicSteps(string $route): array
|
||||||
|
{
|
||||||
|
$routeKey = str_replace('.', '_', $route);
|
||||||
|
$elements = config(sprintf('intro.%s', $routeKey));
|
||||||
|
$steps = [];
|
||||||
|
if (is_array($elements) && count($elements) > 0) {
|
||||||
|
foreach ($elements as $key => $options) {
|
||||||
|
$currentStep = $options;
|
||||||
|
|
||||||
|
// get the text:
|
||||||
|
$currentStep['intro'] = trans('intro.' . $route . '_' . $key);
|
||||||
|
|
||||||
|
|
||||||
|
// save in array:
|
||||||
|
$steps[] = $currentStep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $route
|
||||||
|
* @param string $specificPage
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getSpecificSteps(string $route, string $specificPage): array
|
||||||
|
{
|
||||||
|
$steps = [];
|
||||||
|
|
||||||
|
// user is on page with specific instructions:
|
||||||
|
if (strlen($specificPage) > 0) {
|
||||||
|
$routeKey = str_replace('.', '_', $route);
|
||||||
|
$elements = config(sprintf('intro.%s', $routeKey . '_' . $specificPage));
|
||||||
|
if (is_array($elements) && count($elements) > 0) {
|
||||||
|
foreach ($elements as $key => $options) {
|
||||||
|
$currentStep = $options;
|
||||||
|
|
||||||
|
// get the text:
|
||||||
|
$currentStep['intro'] = trans('intro.' . $route . '_' . $specificPage . '_' . $key);
|
||||||
|
|
||||||
|
// save in array:
|
||||||
|
$steps[] = $currentStep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,7 +15,6 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
|
|
||||||
use Amount;
|
use Amount;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
@ -27,7 +26,6 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Preferences;
|
|
||||||
use Response;
|
use Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,16 +235,6 @@ class JsonController extends Controller
|
|||||||
return Response::json($return);
|
return Response::json($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function endTour()
|
|
||||||
{
|
|
||||||
Preferences::set('tour', false);
|
|
||||||
|
|
||||||
return Response::json('true');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a JSON list of all beneficiaries.
|
* Returns a JSON list of all beneficiaries.
|
||||||
*
|
*
|
||||||
@ -293,34 +281,6 @@ class JsonController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function tour()
|
|
||||||
{
|
|
||||||
$pref = Preferences::get('tour', true);
|
|
||||||
if (!$pref) {
|
|
||||||
throw new FireflyException('Cannot find preference for tour. Exit.'); // @codeCoverageIgnore
|
|
||||||
}
|
|
||||||
$headers = ['main-content', 'sidebar-toggle', 'account-menu', 'budget-menu', 'report-menu', 'transaction-menu', 'option-menu', 'main-content-end'];
|
|
||||||
$steps = [];
|
|
||||||
foreach ($headers as $header) {
|
|
||||||
$steps[] = [
|
|
||||||
'element' => '#' . $header,
|
|
||||||
'title' => trans('help.' . $header . '-title'),
|
|
||||||
'content' => trans('help.' . $header . '-text'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$steps[0]['orphan'] = true;// orphan and backdrop for first element.
|
|
||||||
$steps[0]['backdrop'] = true;
|
|
||||||
$steps[1]['placement'] = 'left';// sidebar position left:
|
|
||||||
$steps[7]['orphan'] = true; // final in the center again.
|
|
||||||
$steps[7]['backdrop'] = true;
|
|
||||||
$template = view('json.tour')->render();
|
|
||||||
|
|
||||||
return Response::json(['steps' => $steps, 'template' => $template]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param JournalCollectorInterface $collector
|
* @param JournalCollectorInterface $collector
|
||||||
* @param string $what
|
* @param string $what
|
||||||
@ -365,7 +325,7 @@ class JsonController extends Controller
|
|||||||
$keys = array_keys(config('firefly.rule-triggers'));
|
$keys = array_keys(config('firefly.rule-triggers'));
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
if ($key != 'user_action') {
|
if ($key !== 'user_action') {
|
||||||
$triggers[$key] = trans('firefly.rule_trigger_' . $key . '_choice');
|
$triggers[$key] = trans('firefly.rule_trigger_' . $key . '_choice');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@ class NewUserController extends Controller
|
|||||||
View::share('title', trans('firefly.welcome'));
|
View::share('title', trans('firefly.welcome'));
|
||||||
View::share('mainTitleIcon', 'fa-fire');
|
View::share('mainTitleIcon', 'fa-fire');
|
||||||
|
|
||||||
|
|
||||||
$types = config('firefly.accountTypesByIdentifier.asset');
|
$types = config('firefly.accountTypesByIdentifier.asset');
|
||||||
$count = $repository->count($types);
|
$count = $repository->count($types);
|
||||||
|
|
||||||
@ -74,30 +73,13 @@ class NewUserController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function submit(NewUserFormRequest $request, AccountRepositoryInterface $repository)
|
public function submit(NewUserFormRequest $request, AccountRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$count = 1;
|
|
||||||
// create normal asset account:
|
// create normal asset account:
|
||||||
$this->createAssetAccount($request, $repository);
|
$this->createAssetAccount($request, $repository);
|
||||||
|
|
||||||
// create savings account
|
// create savings account
|
||||||
$savingBalance = strval($request->get('savings_balance')) === '' ? '0' : strval($request->get('savings_balance'));
|
|
||||||
if (bccomp($savingBalance, '0') !== 0) {
|
|
||||||
$this->createSavingsAccount($request, $repository);
|
$this->createSavingsAccount($request, $repository);
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Session::flash('success', strval(trans('firefly.stored_new_accounts_new_user')));
|
||||||
// create credit card.
|
|
||||||
$limit = strval($request->get('credit_card_limit')) === '' ? '0' : strval($request->get('credit_card_limit'));
|
|
||||||
if (bccomp($limit, '0') !== 0) {
|
|
||||||
$this->storeCreditCard($request, $repository);
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
$message = strval(trans('firefly.stored_new_accounts_new_user'));
|
|
||||||
if ($count == 1) {
|
|
||||||
$message = strval(trans('firefly.stored_new_account_new_user'));
|
|
||||||
}
|
|
||||||
|
|
||||||
Session::flash('success', $message);
|
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
|
||||||
return redirect(route('index'));
|
return redirect(route('index'));
|
||||||
@ -152,29 +134,4 @@ class NewUserController extends Controller
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param NewUserFormRequest $request
|
|
||||||
* @param AccountRepositoryInterface $repository
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function storeCreditCard(NewUserFormRequest $request, AccountRepositoryInterface $repository): bool
|
|
||||||
{
|
|
||||||
$creditAccount = [
|
|
||||||
'name' => 'Credit card',
|
|
||||||
'iban' => null,
|
|
||||||
'accountType' => 'asset',
|
|
||||||
'virtualBalance' => round($request->get('credit_card_limit'), 12),
|
|
||||||
'active' => true,
|
|
||||||
'accountRole' => 'ccAsset',
|
|
||||||
'openingBalance' => null,
|
|
||||||
'openingBalanceDate' => null,
|
|
||||||
'openingBalanceCurrency' => intval($request->input('amount_currency_id_credit_card_limit')),
|
|
||||||
'ccType' => 'monthlyFull',
|
|
||||||
'ccMonthlyPaymentDate' => Carbon::now()->year . '-01-01',
|
|
||||||
];
|
|
||||||
$repository->store($creditAccount);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ class PiggyBankController extends Controller
|
|||||||
/** @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 = $piggyBank->currentRelevantRep()->currentamount?? '0';
|
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount ?? '0';
|
||||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||||
|
|
||||||
|
@ -13,12 +13,18 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use ExpandedForm;
|
||||||
use FireflyIII\Http\Requests\RuleFormRequest;
|
use FireflyIII\Http\Requests\RuleFormRequest;
|
||||||
|
use FireflyIII\Http\Requests\SelectTransactionsRequest;
|
||||||
use FireflyIII\Http\Requests\TestRuleFormRequest;
|
use FireflyIII\Http\Requests\TestRuleFormRequest;
|
||||||
|
use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Rule;
|
use FireflyIII\Models\Rule;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
use FireflyIII\Models\RuleTrigger;
|
use FireflyIII\Models\RuleTrigger;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use FireflyIII\Rules\TransactionMatcher;
|
use FireflyIII\Rules\TransactionMatcher;
|
||||||
@ -188,6 +194,41 @@ class RuleController extends Controller
|
|||||||
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount'));
|
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the given rule on a set of existing transactions
|
||||||
|
*
|
||||||
|
* @param SelectTransactionsRequest $request
|
||||||
|
* @param AccountRepositoryInterface $repository
|
||||||
|
* @param Rule $rule
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @internal param RuleGroup $ruleGroup
|
||||||
|
*/
|
||||||
|
public function execute(SelectTransactionsRequest $request, AccountRepositoryInterface $repository, Rule $rule)
|
||||||
|
{
|
||||||
|
// Get parameters specified by the user
|
||||||
|
$accounts = $repository->getAccountsById($request->get('accounts'));
|
||||||
|
$startDate = new Carbon($request->get('start_date'));
|
||||||
|
$endDate = new Carbon($request->get('end_date'));
|
||||||
|
|
||||||
|
// Create a job to do the work asynchronously
|
||||||
|
$job = new ExecuteRuleOnExistingTransactions($rule);
|
||||||
|
|
||||||
|
// Apply parameters to the job
|
||||||
|
$job->setUser(auth()->user());
|
||||||
|
$job->setAccounts($accounts);
|
||||||
|
$job->setStartDate($startDate);
|
||||||
|
$job->setEndDate($endDate);
|
||||||
|
|
||||||
|
// Dispatch a new job to execute it in a queue
|
||||||
|
$this->dispatch($job);
|
||||||
|
|
||||||
|
// Tell the user that the job is queued
|
||||||
|
Session::flash('success', strval(trans('firefly.applied_rule_selection', ['title' => $rule->title])));
|
||||||
|
|
||||||
|
return redirect()->route('rules.index');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RuleGroupRepositoryInterface $repository
|
* @param RuleGroupRepositoryInterface $repository
|
||||||
*
|
*
|
||||||
@ -238,6 +279,25 @@ class RuleController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param AccountRepositoryInterface $repository
|
||||||
|
* @param Rule $rule
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function selectTransactions(AccountRepositoryInterface $repository, Rule $rule)
|
||||||
|
{
|
||||||
|
// does the user have shared accounts?
|
||||||
|
$accounts = $repository->getAccountsByType([AccountType::ASSET]);
|
||||||
|
$accountList = ExpandedForm::makeSelectList($accounts);
|
||||||
|
$checkedAccounts = array_keys($accountList);
|
||||||
|
$first = session('first')->format('Y-m-d');
|
||||||
|
$today = Carbon::create()->format('Y-m-d');
|
||||||
|
$subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]);
|
||||||
|
|
||||||
|
return view('rules.rule.select-transactions', compact('checkedAccounts', 'accountList', 'first', 'today', 'rule', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RuleFormRequest $request
|
* @param RuleFormRequest $request
|
||||||
* @param RuleRepositoryInterface $repository
|
* @param RuleRepositoryInterface $repository
|
||||||
@ -282,7 +342,7 @@ class RuleController extends Controller
|
|||||||
// build trigger array from response
|
// build trigger array from response
|
||||||
$triggers = $this->getValidTriggerList($request);
|
$triggers = $this->getValidTriggerList($request);
|
||||||
|
|
||||||
if (count($triggers) == 0) {
|
if (count($triggers) === 0) {
|
||||||
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]);
|
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,14 +354,61 @@ class RuleController extends Controller
|
|||||||
$matcher->setLimit($limit);
|
$matcher->setLimit($limit);
|
||||||
$matcher->setRange($range);
|
$matcher->setRange($range);
|
||||||
$matcher->setTriggers($triggers);
|
$matcher->setTriggers($triggers);
|
||||||
$matchingTransactions = $matcher->findMatchingTransactions();
|
$matchingTransactions = $matcher->findTransactionsByTriggers();
|
||||||
|
|
||||||
// Warn the user if only a subset of transactions is returned
|
// Warn the user if only a subset of transactions is returned
|
||||||
$warning = '';
|
$warning = '';
|
||||||
if (count($matchingTransactions) == $limit) {
|
if (count($matchingTransactions) === $limit) {
|
||||||
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]);
|
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]);
|
||||||
}
|
}
|
||||||
if (count($matchingTransactions) == 0) {
|
if (count($matchingTransactions) === 0) {
|
||||||
|
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return json response
|
||||||
|
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
|
||||||
|
|
||||||
|
return Response::json(['html' => $view, 'warning' => $warning]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method allows the user to test a certain set of rule triggers. The rule triggers are grabbed from
|
||||||
|
* the rule itself.
|
||||||
|
*
|
||||||
|
* This method will parse and validate those rules and create a "TransactionMatcher" which will attempt
|
||||||
|
* to find transaction journals matching the users input. A maximum range of transactions to try (range) and
|
||||||
|
* a maximum number of transactions to return (limit) are set as well.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param Rule $rule
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function testTriggersByRule(Rule $rule)
|
||||||
|
{
|
||||||
|
|
||||||
|
$triggers = $rule->ruleTriggers;
|
||||||
|
|
||||||
|
if (count($triggers) === 0) {
|
||||||
|
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$limit = config('firefly.test-triggers.limit');
|
||||||
|
$range = config('firefly.test-triggers.range');
|
||||||
|
|
||||||
|
/** @var TransactionMatcher $matcher */
|
||||||
|
$matcher = app(TransactionMatcher::class);
|
||||||
|
$matcher->setLimit($limit);
|
||||||
|
$matcher->setRange($range);
|
||||||
|
$matcher->setRule($rule);
|
||||||
|
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||||
|
|
||||||
|
// Warn the user if only a subset of transactions is returned
|
||||||
|
$warning = '';
|
||||||
|
if (count($matchingTransactions) === $limit) {
|
||||||
|
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]);
|
||||||
|
}
|
||||||
|
if (count($matchingTransactions) === 0) {
|
||||||
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]);
|
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +547,7 @@ class RuleController extends Controller
|
|||||||
|
|
||||||
/** @var RuleTrigger $entry */
|
/** @var RuleTrigger $entry */
|
||||||
foreach ($rule->ruleTriggers as $entry) {
|
foreach ($rule->ruleTriggers as $entry) {
|
||||||
if ($entry->trigger_type != 'user_action') {
|
if ($entry->trigger_type !== 'user_action') {
|
||||||
$count = ($index + 1);
|
$count = ($index + 1);
|
||||||
$triggers[] = view(
|
$triggers[] = view(
|
||||||
'rules.partials.trigger',
|
'rules.partials.trigger',
|
||||||
|
@ -178,7 +178,7 @@ class RuleGroupController extends Controller
|
|||||||
$this->dispatch($job);
|
$this->dispatch($job);
|
||||||
|
|
||||||
// Tell the user that the job is queued
|
// Tell the user that the job is queued
|
||||||
Session::flash('success', strval(trans('firefly.executed_group_on_existing_transactions', ['title' => $ruleGroup->title])));
|
Session::flash('success', strval(trans('firefly.applied_rule_group_selection', ['title' => $ruleGroup->title])));
|
||||||
|
|
||||||
return redirect()->route('rules.index');
|
return redirect()->route('rules.index');
|
||||||
}
|
}
|
||||||
@ -197,7 +197,7 @@ class RuleGroupController extends Controller
|
|||||||
$checkedAccounts = array_keys($accountList);
|
$checkedAccounts = array_keys($accountList);
|
||||||
$first = session('first')->format('Y-m-d');
|
$first = session('first')->format('Y-m-d');
|
||||||
$today = Carbon::create()->format('Y-m-d');
|
$today = Carbon::create()->format('Y-m-d');
|
||||||
$subTitle = (string)trans('firefly.execute_on_existing_transactions');
|
$subTitle = (string)trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]);
|
||||||
|
|
||||||
return view('rules.rule-group.select-transactions', compact('checkedAccounts', 'accountList', 'first', 'today', 'ruleGroup', 'subTitle'));
|
return view('rules.rule-group.select-transactions', compact('checkedAccounts', 'accountList', 'first', 'today', 'ruleGroup', 'subTitle'));
|
||||||
}
|
}
|
||||||
@ -246,14 +246,14 @@ class RuleGroupController extends Controller
|
|||||||
* @param RuleGroupRepositoryInterface $repository
|
* @param RuleGroupRepositoryInterface $repository
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
*/
|
*/
|
||||||
public function update(RuleGroupFormRequest $request, RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
|
public function update(RuleGroupFormRequest $request, RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
'title' => $request->input('title'),
|
'title' => $request->input('title'),
|
||||||
'description' => $request->input('description'),
|
'description' => $request->input('description'),
|
||||||
'active' => intval($request->input('active')) == 1,
|
'active' => intval($request->input('active')) === 1,
|
||||||
];
|
];
|
||||||
|
|
||||||
$repository->update($ruleGroup, $data);
|
$repository->update($ruleGroup, $data);
|
||||||
|
@ -15,7 +15,7 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
|
|
||||||
use FireflyIII\Support\Search\SearchInterface;
|
use FireflyIII\Support\Search\SearchInterface;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
use Response;
|
||||||
use View;
|
use View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,47 +51,29 @@ class SearchController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request, SearchInterface $searcher)
|
public function index(Request $request, SearchInterface $searcher)
|
||||||
{
|
{
|
||||||
// yes, hard coded values:
|
$fullQuery = $request->get('q');
|
||||||
$minSearchLen = 1;
|
|
||||||
$limit = 20;
|
|
||||||
|
|
||||||
// ui stuff:
|
// parse search terms:
|
||||||
$subTitle = '';
|
$searcher->parseQuery($fullQuery);
|
||||||
|
|
||||||
// query stuff
|
|
||||||
$query = null;
|
|
||||||
$result = [];
|
|
||||||
$rawQuery = $request->get('q');
|
|
||||||
$hasModifiers = true;
|
|
||||||
$modifiers = [];
|
|
||||||
|
|
||||||
if (!is_null($request->get('q')) && strlen($request->get('q')) >= $minSearchLen) {
|
|
||||||
// parse query, find modifiers:
|
|
||||||
// set limit for search
|
|
||||||
$searcher->setLimit($limit);
|
|
||||||
$searcher->parseQuery($request->get('q'));
|
|
||||||
|
|
||||||
$transactions = $searcher->searchTransactions();
|
|
||||||
$accounts = new Collection;
|
|
||||||
$categories = new Collection;
|
|
||||||
$tags = new Collection;
|
|
||||||
$budgets = new Collection;
|
|
||||||
|
|
||||||
// no special search thing?
|
|
||||||
if (!$searcher->hasModifiers()) {
|
|
||||||
$hasModifiers = false;
|
|
||||||
$accounts = $searcher->searchAccounts();
|
|
||||||
$categories = $searcher->searchCategories();
|
|
||||||
$budgets = $searcher->searchBudgets();
|
|
||||||
$tags = $searcher->searchTags();
|
|
||||||
}
|
|
||||||
$query = $searcher->getWordsAsString();
|
$query = $searcher->getWordsAsString();
|
||||||
$subTitle = trans('firefly.search_results_for', ['query' => $query]);
|
$subTitle = trans('breadcrumbs.search_result', ['query' => $query]);
|
||||||
$result = ['transactions' => $transactions, 'accounts' => $accounts, 'categories' => $categories, 'budgets' => $budgets, 'tags' => $tags];
|
|
||||||
|
|
||||||
|
return view('search.index', compact('query', 'fullQuery', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('search.index', compact('rawQuery', 'hasModifiers', 'modifiers', 'subTitle', 'limit', 'query', 'result'));
|
public function search(Request $request, SearchInterface $searcher)
|
||||||
|
{
|
||||||
|
$fullQuery = $request->get('query');
|
||||||
|
|
||||||
|
// parse search terms:
|
||||||
|
$searcher->parseQuery($fullQuery);
|
||||||
|
$searcher->setLimit(20);
|
||||||
|
$transactions = $searcher->searchTransactions();
|
||||||
|
$html = view('search.search', compact('transactions'))->render();
|
||||||
|
|
||||||
|
return Response::json(['count' => $transactions->count(), 'html' => $html]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ class TagController extends Controller
|
|||||||
// default values:
|
// default values:
|
||||||
$subTitle = $tag->tag;
|
$subTitle = $tag->tag;
|
||||||
$subTitleIcon = 'fa-tag';
|
$subTitleIcon = 'fa-tag';
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$loop = 0;
|
$loop = 0;
|
||||||
@ -301,7 +301,7 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moment != 'all' && $loop > 1) {
|
if ($moment !== 'all' && $loop > 1) {
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.journals_in_period_for_tag',
|
'firefly.journals_in_period_for_tag',
|
||||||
['tag' => $tag->tag, 'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
['tag' => $tag->tag, 'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
|
@ -86,7 +86,7 @@ class MassController extends Controller
|
|||||||
foreach ($ids as $journalId) {
|
foreach ($ids as $journalId) {
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = $repository->find(intval($journalId));
|
$journal = $repository->find(intval($journalId));
|
||||||
if (!is_null($journal->id) && $journalId == $journal->id) {
|
if (!is_null($journal->id) && $journalId === $journal->id) {
|
||||||
$set->push($journal);
|
$set->push($journal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,8 +135,8 @@ class MassController extends Controller
|
|||||||
* @var TransactionJournal $journal
|
* @var TransactionJournal $journal
|
||||||
*/
|
*/
|
||||||
foreach ($journals as $index => $journal) {
|
foreach ($journals as $index => $journal) {
|
||||||
$sources = $journal->sourceAccountList($journal);
|
$sources = $journal->sourceAccountList();
|
||||||
$destinations = $journal->destinationAccountList($journal);
|
$destinations = $journal->destinationAccountList();
|
||||||
if ($sources->count() > 1) {
|
if ($sources->count() > 1) {
|
||||||
$messages[] = trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]);
|
$messages[] = trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]);
|
||||||
continue;
|
continue;
|
||||||
|
@ -174,7 +174,7 @@ class SingleController extends Controller
|
|||||||
*
|
*
|
||||||
* @param TransactionJournal $journal
|
* @param TransactionJournal $journal
|
||||||
*
|
*
|
||||||
* @return View
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||||
*/
|
*/
|
||||||
public function delete(TransactionJournal $journal)
|
public function delete(TransactionJournal $journal)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +70,7 @@ class TransactionController extends Controller
|
|||||||
// default values:
|
// default values:
|
||||||
$subTitleIcon = config('firefly.transactionIconsByWhat.' . $what);
|
$subTitleIcon = config('firefly.transactionIconsByWhat.' . $what);
|
||||||
$types = config('firefly.transactionTypesByWhat.' . $what);
|
$types = config('firefly.transactionTypesByWhat.' . $what);
|
||||||
$page = intval($request->get('page')) == 0 ? 1 : intval($request->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);
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$loop = 0;
|
$loop = 0;
|
||||||
@ -93,6 +93,7 @@ class TransactionController extends Controller
|
|||||||
if (strlen($moment) > 0 && $moment !== 'all') {
|
if (strlen($moment) > 0 && $moment !== 'all') {
|
||||||
$start = new Carbon($moment);
|
$start = new Carbon($moment);
|
||||||
$end = Navigation::endOfPeriod($start, $range);
|
$end = Navigation::endOfPeriod($start, $range);
|
||||||
|
$path = '/transactions/' . $what . '/' . $moment;
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.title_' . $what . '_between',
|
'firefly.title_' . $what . '_between',
|
||||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
@ -130,7 +131,7 @@ class TransactionController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moment != 'all' && $loop > 1) {
|
if ($moment !== 'all' && $loop > 1) {
|
||||||
$subTitle = trans(
|
$subTitle = trans(
|
||||||
'firefly.title_' . $what . '_between',
|
'firefly.title_' . $what . '_between',
|
||||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
@ -172,7 +173,7 @@ class TransactionController extends Controller
|
|||||||
* @param TransactionJournal $journal
|
* @param TransactionJournal $journal
|
||||||
* @param JournalTaskerInterface $tasker
|
* @param JournalTaskerInterface $tasker
|
||||||
*
|
*
|
||||||
* @return View
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||||
*/
|
*/
|
||||||
public function show(TransactionJournal $journal, JournalTaskerInterface $tasker)
|
public function show(TransactionJournal $journal, JournalTaskerInterface $tasker)
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ class TagFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function collectTagData(): array
|
public function collectTagData(): array
|
||||||
{
|
{
|
||||||
if ($this->get('setTag') == 'true') {
|
if ($this->get('setTag') === 'true') {
|
||||||
$latitude = $this->string('latitude');
|
$latitude = $this->string('latitude');
|
||||||
$longitude = $this->string('longitude');
|
$longitude = $this->string('longitude');
|
||||||
$zoomLevel = $this->integer('zoomLevel');
|
$zoomLevel = $this->integer('zoomLevel');
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DaveJamesMiller\Breadcrumbs\Generator as BreadCrumbGenerator;
|
use DaveJamesMiller\Breadcrumbs\Generator as BreadCrumbGenerator;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
@ -680,7 +681,7 @@ Breadcrumbs::register(
|
|||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'search.index', function (BreadCrumbGenerator $breadcrumbs, $query) {
|
'search.index', function (BreadCrumbGenerator $breadcrumbs, $query) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search.index'));
|
$breadcrumbs->push(trans('breadcrumbs.search_result', ['query' => e($query)]), route('search.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ class Amount implements ConverterInterface
|
|||||||
$decimalPosition = $len - 3;
|
$decimalPosition = $len - 3;
|
||||||
$decimal = null;
|
$decimal = null;
|
||||||
|
|
||||||
if (($len > 2 && $value{$decimalPosition} == '.') || ($len > 2 && strpos($value, '.') > $decimalPosition)) {
|
if (($len > 2 && $value{$decimalPosition} === '.') || ($len > 2 && strpos($value, '.') > $decimalPosition)) {
|
||||||
$decimal = '.';
|
$decimal = '.';
|
||||||
}
|
}
|
||||||
if ($len > 2 && $value{$decimalPosition} == ',') {
|
if ($len > 2 && $value{$decimalPosition} === ',') {
|
||||||
$decimal = ',';
|
$decimal = ',';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ class CommandHandler extends AbstractProcessingHandler
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->command = $command;
|
$this->command = $command;
|
||||||
$this->changeLevel(env('LOG_LEVEL', 'debug'));
|
|
||||||
|
$this->changeLevel(env('APP_LOG_LEVEL', 'info'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,8 +58,9 @@ class CommandHandler extends AbstractProcessingHandler
|
|||||||
private function changeLevel(string $level)
|
private function changeLevel(string $level)
|
||||||
{
|
{
|
||||||
$level = strtoupper($level);
|
$level = strtoupper($level);
|
||||||
if (defined(sprintf('Logger::%s', $level))) {
|
$reference = sprintf('\Monolog\Logger::%s', $level);
|
||||||
$this->setLevel(constant(sprintf('Logger::%s', $level)));
|
if (defined($reference)) {
|
||||||
|
$this->setLevel(constant($reference));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class AssetAccountIbans implements MapperInterface
|
|||||||
if (strlen($iban) > 0) {
|
if (strlen($iban) > 0) {
|
||||||
$topList[$account->id] = $account->iban . ' (' . $account->name . ')';
|
$topList[$account->id] = $account->iban . ' (' . $account->name . ')';
|
||||||
}
|
}
|
||||||
if (strlen($iban) == 0) {
|
if (strlen($iban) === 0) {
|
||||||
$list[$account->id] = $account->name;
|
$list[$account->id] = $account->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ class OpposingAccountIbans implements MapperInterface
|
|||||||
if (strlen($iban) > 0) {
|
if (strlen($iban) > 0) {
|
||||||
$topList[$account->id] = $account->iban . ' (' . $account->name . ')';
|
$topList[$account->id] = $account->iban . ' (' . $account->name . ')';
|
||||||
}
|
}
|
||||||
if (strlen($iban) == 0) {
|
if (strlen($iban) === 0) {
|
||||||
$list[$account->id] = $account->name;
|
$list[$account->id] = $account->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ class ImportAccount
|
|||||||
private $accountName = [];
|
private $accountName = [];
|
||||||
/** @var array */
|
/** @var array */
|
||||||
private $accountNumber = [];
|
private $accountNumber = [];
|
||||||
|
/** @var int */
|
||||||
|
private $defaultAccountId = 0;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $expectedType = '';
|
private $expectedType = '';
|
||||||
/** @var AccountRepositoryInterface */
|
/** @var AccountRepositoryInterface */
|
||||||
@ -115,6 +117,14 @@ class ImportAccount
|
|||||||
$this->accountNumber = $accountNumber;
|
$this->accountNumber = $accountNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $defaultAccountId
|
||||||
|
*/
|
||||||
|
public function setDefaultAccountId(int $defaultAccountId)
|
||||||
|
{
|
||||||
|
$this->defaultAccountId = $defaultAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
* @param User $user
|
||||||
*/
|
*/
|
||||||
@ -249,13 +259,22 @@ class ImportAccount
|
|||||||
$search = intval($array['mapped']);
|
$search = intval($array['mapped']);
|
||||||
$account = $this->repository->find($search);
|
$account = $this->repository->find($search);
|
||||||
|
|
||||||
if ($account->accountType->type !== $this->expectedType) {
|
if (is_null($account->id)) {
|
||||||
|
Log::error(sprintf('There is no account with id #%d. Invalid mapping will be ignored!', $search));
|
||||||
|
|
||||||
|
return new Account;
|
||||||
|
}
|
||||||
|
// must be of the same type
|
||||||
|
// except when mapped is an asset, then it's fair game.
|
||||||
|
// which only shows that user must map very carefully.
|
||||||
|
if ($account->accountType->type !== $this->expectedType && $account->accountType->type !== AccountType::ASSET) {
|
||||||
Log::error(
|
Log::error(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Mapped account #%d is of type "%s" but we expect a "%s"-account. Mapping will be ignored.', $account->id, $account->accountType->type,
|
'Mapped account #%d is of type "%s" but we expect a "%s"-account. Mapping will be ignored.', $account->id, $account->accountType->type,
|
||||||
$this->expectedType
|
$this->expectedType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Account;
|
return new Account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +316,14 @@ class ImportAccount
|
|||||||
}
|
}
|
||||||
$this->expectedType = $oldExpectedType;
|
$this->expectedType = $oldExpectedType;
|
||||||
|
|
||||||
|
// if search for an asset account, fall back to given "default account" (mandatory)
|
||||||
|
if ($this->expectedType === AccountType::ASSET) {
|
||||||
|
$this->account = $this->repository->find($this->defaultAccountId);
|
||||||
|
Log::debug(sprintf('Fall back to default account #%d "%s"', $this->account->id, $this->account->name));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('Found no account of type %s so must create one ourselves.', $this->expectedType));
|
Log::debug(sprintf('Found no account of type %s so must create one ourselves.', $this->expectedType));
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -181,11 +181,18 @@ class ImportBill
|
|||||||
Log::debug('Finding a mapped bill based on', $array);
|
Log::debug('Finding a mapped bill based on', $array);
|
||||||
|
|
||||||
$search = intval($array['mapped']);
|
$search = intval($array['mapped']);
|
||||||
$account = $this->repository->find($search);
|
$bill = $this->repository->find($search);
|
||||||
|
|
||||||
Log::debug(sprintf('Found bill! #%d ("%s"). Return it', $account->id, $account->name));
|
if (is_null($bill->id)) {
|
||||||
|
Log::error(sprintf('There is no bill with id #%d. Invalid mapping will be ignored!', $search));
|
||||||
|
|
||||||
return $account;
|
return new Bill;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Log::debug(sprintf('Found bill! #%d ("%s"). Return it', $bill->id, $bill->name));
|
||||||
|
|
||||||
|
return $bill;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,11 +181,17 @@ class ImportBudget
|
|||||||
Log::debug('Finding a mapped budget based on', $array);
|
Log::debug('Finding a mapped budget based on', $array);
|
||||||
|
|
||||||
$search = intval($array['mapped']);
|
$search = intval($array['mapped']);
|
||||||
$account = $this->repository->find($search);
|
$budget = $this->repository->find($search);
|
||||||
|
|
||||||
Log::debug(sprintf('Found budget! #%d ("%s"). Return it', $account->id, $account->name));
|
if (is_null($budget->id)) {
|
||||||
|
Log::error(sprintf('There is no budget with id #%d. Invalid mapping will be ignored!', $search));
|
||||||
|
|
||||||
return $account;
|
return new Budget;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(sprintf('Found budget! #%d ("%s"). Return it', $budget->id, $budget->name));
|
||||||
|
|
||||||
|
return $budget;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,11 +175,17 @@ class ImportCategory
|
|||||||
Log::debug('Finding a mapped category based on', $array);
|
Log::debug('Finding a mapped category based on', $array);
|
||||||
|
|
||||||
$search = intval($array['mapped']);
|
$search = intval($array['mapped']);
|
||||||
$account = $this->repository->find($search);
|
$category = $this->repository->find($search);
|
||||||
|
|
||||||
Log::debug(sprintf('Found category! #%d ("%s"). Return it', $account->id, $account->name));
|
if (is_null($category->id)) {
|
||||||
|
Log::error(sprintf('There is no category with id #%d. Invalid mapping will be ignored!', $search));
|
||||||
|
|
||||||
return $account;
|
return new Category;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(sprintf('Found category! #%d ("%s"). Return it', $category->id, $category->name));
|
||||||
|
|
||||||
|
return $category;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,6 +209,13 @@ class ImportCurrency
|
|||||||
$search = intval($array['mapped']);
|
$search = intval($array['mapped']);
|
||||||
$currency = $this->repository->find($search);
|
$currency = $this->repository->find($search);
|
||||||
|
|
||||||
|
|
||||||
|
if (is_null($currency->id)) {
|
||||||
|
Log::error(sprintf('There is no currency with id #%d. Invalid mapping will be ignored!', $search));
|
||||||
|
|
||||||
|
return new TransactionCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('Found currency! #%d ("%s"). Return it', $currency->id, $currency->name));
|
Log::debug(sprintf('Found currency! #%d ("%s"). Return it', $currency->id, $currency->name));
|
||||||
|
|
||||||
return $currency;
|
return $currency;
|
||||||
|
@ -144,6 +144,18 @@ class ImportJournal
|
|||||||
return $date;
|
return $date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
if ($this->description === '') {
|
||||||
|
return '(no description)';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->description;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
*/
|
*/
|
||||||
@ -226,7 +238,7 @@ class ImportJournal
|
|||||||
$this->date = $array['value'];
|
$this->date = $array['value'];
|
||||||
break;
|
break;
|
||||||
case 'description':
|
case 'description':
|
||||||
$this->description = $array['value'];
|
$this->description .= $array['value'];
|
||||||
break;
|
break;
|
||||||
case 'sepa-ct-op':
|
case 'sepa-ct-op':
|
||||||
case 'sepa-ct-id':
|
case 'sepa-ct-id':
|
||||||
|
@ -13,11 +13,11 @@ namespace FireflyIII\Import\Routine;
|
|||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use DB;
|
||||||
use FireflyIII\Import\FileProcessor\FileProcessorInterface;
|
use FireflyIII\Import\FileProcessor\FileProcessorInterface;
|
||||||
use FireflyIII\Import\Storage\ImportStorage;
|
use FireflyIII\Import\Storage\ImportStorage;
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
use Log;
|
||||||
@ -64,14 +64,19 @@ class ImportRoutine
|
|||||||
Log::info(sprintf('Returned %d valid objects from file processor', $this->lines));
|
Log::info(sprintf('Returned %d valid objects from file processor', $this->lines));
|
||||||
|
|
||||||
$storage = $this->storeObjects($importObjects);
|
$storage = $this->storeObjects($importObjects);
|
||||||
|
Log::debug('Back in run()');
|
||||||
|
|
||||||
// update job:
|
// update job:
|
||||||
$this->job->status = 'finished';
|
$this->job->status = 'finished';
|
||||||
$this->job->save();
|
$this->job->save();
|
||||||
|
|
||||||
|
Log::debug('Updated job...');
|
||||||
|
|
||||||
$this->journals = $storage->journals;
|
$this->journals = $storage->journals;
|
||||||
$this->errors = $storage->errors;
|
$this->errors = $storage->errors;
|
||||||
|
|
||||||
|
Log::debug('Going to call createImportTag()');
|
||||||
|
|
||||||
// create tag, link tag to all journals:
|
// create tag, link tag to all journals:
|
||||||
$this->createImportTag();
|
$this->createImportTag();
|
||||||
|
|
||||||
@ -101,7 +106,7 @@ class ImportRoutine
|
|||||||
$processor = app($class);
|
$processor = app($class);
|
||||||
$processor->setJob($this->job);
|
$processor->setJob($this->job);
|
||||||
|
|
||||||
if ($this->job->status == 'configured') {
|
if ($this->job->status === 'configured') {
|
||||||
|
|
||||||
// set job as "running"...
|
// set job as "running"...
|
||||||
$this->job->status = 'running';
|
$this->job->status = 'running';
|
||||||
@ -120,6 +125,7 @@ class ImportRoutine
|
|||||||
*/
|
*/
|
||||||
private function createImportTag(): Tag
|
private function createImportTag(): Tag
|
||||||
{
|
{
|
||||||
|
Log::debug('Now in createImportTag()');
|
||||||
/** @var TagRepositoryInterface $repository */
|
/** @var TagRepositoryInterface $repository */
|
||||||
$repository = app(TagRepositoryInterface::class);
|
$repository = app(TagRepositoryInterface::class);
|
||||||
$repository->setUser($this->job->user);
|
$repository->setUser($this->job->user);
|
||||||
@ -138,14 +144,17 @@ class ImportRoutine
|
|||||||
$this->job->extended_status = $extended;
|
$this->job->extended_status = $extended;
|
||||||
$this->job->save();
|
$this->job->save();
|
||||||
|
|
||||||
$this->journals->each(
|
Log::debug(sprintf('Created tag #%d ("%s")', $tag->id, $tag->tag));
|
||||||
function (TransactionJournal $journal) use ($tag) {
|
Log::debug('Looping journals...');
|
||||||
$journal->tags()->save($tag);
|
$journalIds = $this->journals->pluck('id')->toArray();
|
||||||
|
$tagId = $tag->id;
|
||||||
|
foreach ($journalIds as $journalId) {
|
||||||
|
Log::debug(sprintf('Linking journal #%d to tag #%d...', $journalId, $tagId));
|
||||||
|
DB::table('tag_transaction_journal')->insert(['transaction_journal_id' => $journalId, 'tag_id' => $tagId]);
|
||||||
}
|
}
|
||||||
);
|
Log::info(sprintf('Linked %d journals to tag #%d ("%s")', $this->journals->count(), $tag->id, $tag->tag));
|
||||||
|
|
||||||
return $tag;
|
return $tag;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,6 +169,7 @@ class ImportRoutine
|
|||||||
$storage->setDateFormat($this->job->configuration['date-format']);
|
$storage->setDateFormat($this->job->configuration['date-format']);
|
||||||
$storage->setObjects($objects);
|
$storage->setObjects($objects);
|
||||||
$storage->store();
|
$storage->store();
|
||||||
|
Log::info('Back in storeObjects()');
|
||||||
|
|
||||||
return $storage;
|
return $storage;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ class AbnAmroDescription implements SpecificInterface
|
|||||||
$this->row[8] = $matches[4]; // 'opposing-account-name'
|
$this->row[8] = $matches[4]; // 'opposing-account-name'
|
||||||
$this->row[7] = $matches[4]; // 'description'
|
$this->row[7] = $matches[4]; // 'description'
|
||||||
|
|
||||||
if ($matches[1] == 'GEA') {
|
if ($matches[1] === 'GEA') {
|
||||||
$this->row[7] = 'GEA ' . $matches[4]; // 'description'
|
$this->row[7] = 'GEA ' . $matches[4]; // 'description'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
use FireflyIII\Rules\Processor;
|
use FireflyIII\Rules\Processor;
|
||||||
|
use Illuminate\Database\Query\JoinClause;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
use Log;
|
||||||
use Steam;
|
use Steam;
|
||||||
@ -43,6 +44,7 @@ class ImportStorage
|
|||||||
{
|
{
|
||||||
/** @var Collection */
|
/** @var Collection */
|
||||||
public $errors;
|
public $errors;
|
||||||
|
/** @var Collection */
|
||||||
public $journals;
|
public $journals;
|
||||||
/** @var CurrencyRepositoryInterface */
|
/** @var CurrencyRepositoryInterface */
|
||||||
private $currencyRepository;
|
private $currencyRepository;
|
||||||
@ -96,13 +98,12 @@ class ImportStorage
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do storage of import objects
|
* Do storage of import objects.
|
||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
$this->defaultCurrency = Amount::getDefaultCurrencyByUser($this->job->user);
|
$this->defaultCurrency = Amount::getDefaultCurrencyByUser($this->job->user);
|
||||||
|
|
||||||
// routine below consists of 3 steps.
|
|
||||||
/**
|
/**
|
||||||
* @var int $index
|
* @var int $index
|
||||||
* @var ImportJournal $object
|
* @var ImportJournal $object
|
||||||
@ -115,8 +116,9 @@ class ImportStorage
|
|||||||
Log::error(sprintf('Cannot import row #%d because: %s', $index, $e->getMessage()));
|
Log::error(sprintf('Cannot import row #%d because: %s', $index, $e->getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log::info('ImportStorage has finished.');
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,7 +129,6 @@ class ImportStorage
|
|||||||
protected function applyRules(TransactionJournal $journal): bool
|
protected function applyRules(TransactionJournal $journal): bool
|
||||||
{
|
{
|
||||||
if ($this->rules->count() > 0) {
|
if ($this->rules->count() > 0) {
|
||||||
|
|
||||||
/** @var Rule $rule */
|
/** @var Rule $rule */
|
||||||
foreach ($this->rules as $rule) {
|
foreach ($this->rules as $rule) {
|
||||||
Log::debug(sprintf('Going to apply rule #%d to journal %d.', $rule->id, $journal->id));
|
Log::debug(sprintf('Going to apply rule #%d to journal %d.', $rule->id, $journal->id));
|
||||||
@ -164,14 +165,60 @@ class ImportStorage
|
|||||||
$errorText = join(', ', $transaction->getErrors()->all());
|
$errorText = join(', ', $transaction->getErrors()->all());
|
||||||
throw new FireflyException($errorText);
|
throw new FireflyException($errorText);
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Created transaction with ID #%d and account #%d', $transaction->id, $accountId));
|
Log::debug(sprintf('Created transaction with ID #%d, account #%d, amount %s', $transaction->id, $accountId, $amount));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Collection $set
|
||||||
* @param ImportJournal $importJournal
|
* @param ImportJournal $importJournal
|
||||||
*
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function filterTransferSet(Collection $set, ImportJournal $importJournal): bool
|
||||||
|
{
|
||||||
|
$amount = Steam::positive($importJournal->getAmount());
|
||||||
|
$asset = $importJournal->asset->getAccount();
|
||||||
|
$opposing = $this->getOpposingAccount($importJournal->opposing, $amount);
|
||||||
|
$description = $importJournal->getDescription();
|
||||||
|
|
||||||
|
$filtered = $set->filter(
|
||||||
|
function (TransactionJournal $journal) use ($asset, $opposing, $description) {
|
||||||
|
$match = true;
|
||||||
|
$original = [app('steam')->tryDecrypt($journal->source_name), app('steam')->tryDecrypt($journal->destination_name)];
|
||||||
|
$compare = [$asset->name, $opposing->name];
|
||||||
|
sort($original);
|
||||||
|
sort($compare);
|
||||||
|
|
||||||
|
// description does not match? Then cannot be duplicate.
|
||||||
|
if ($journal->description !== $description) {
|
||||||
|
$match = false;
|
||||||
|
}
|
||||||
|
// not both accounts in journal? Then cannot be duplicate.
|
||||||
|
if ($original !== $compare) {
|
||||||
|
$match = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($match) {
|
||||||
|
return $journal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (count($filtered) > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ImportJournal $importJournal
|
||||||
|
*
|
||||||
|
* @param Account $account
|
||||||
|
*
|
||||||
* @return TransactionCurrency
|
* @return TransactionCurrency
|
||||||
*/
|
*/
|
||||||
private function getCurrency(ImportJournal $importJournal, Account $account): TransactionCurrency
|
private function getCurrency(ImportJournal $importJournal, Account $account): TransactionCurrency
|
||||||
@ -300,8 +347,8 @@ class ImportStorage
|
|||||||
|
|
||||||
private function storeImportJournal(int $index, ImportJournal $importJournal): bool
|
private function storeImportJournal(int $index, ImportJournal $importJournal): bool
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Going to store object #%d with description "%s"', $index, $importJournal->description));
|
Log::debug(sprintf('Going to store object #%d with description "%s"', $index, $importJournal->getDescription()));
|
||||||
|
$importJournal->asset->setDefaultAccountId($this->job->configuration['import-account']);
|
||||||
$asset = $importJournal->asset->getAccount();
|
$asset = $importJournal->asset->getAccount();
|
||||||
$amount = $importJournal->getAmount();
|
$amount = $importJournal->getAmount();
|
||||||
$currency = $this->getCurrency($importJournal, $asset);
|
$currency = $this->getCurrency($importJournal, $asset);
|
||||||
@ -317,18 +364,30 @@ class ImportStorage
|
|||||||
|
|
||||||
// verify that opposing account is of the correct type:
|
// verify that opposing account is of the correct type:
|
||||||
if ($opposing->accountType->type === AccountType::EXPENSE && $transactionType->type !== TransactionType::WITHDRAWAL) {
|
if ($opposing->accountType->type === AccountType::EXPENSE && $transactionType->type !== TransactionType::WITHDRAWAL) {
|
||||||
Log::error(sprintf('Row #%d is imported as a %s but opposing is an expense account. This cannot be!', $index, $transactionType->type));
|
$message = sprintf('Row #%d is imported as a %s but opposing is an expense account. This cannot be!', $index, $transactionType->type);
|
||||||
|
Log::error($message);
|
||||||
|
throw new FireflyException($message);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** First step done! */
|
/*** First step done! */
|
||||||
$this->job->addStepsDone(1);
|
$this->job->addStepsDone(1);
|
||||||
|
|
||||||
|
// could be that transfer is double: verify this.
|
||||||
|
if ($this->verifyDoubleTransfer($transactionType, $importJournal)) {
|
||||||
|
// add three steps:
|
||||||
|
$this->job->addStepsDone(3);
|
||||||
|
// throw error
|
||||||
|
throw new FireflyException('Detected a possible duplicate, skip this one.');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// create a journal:
|
// create a journal:
|
||||||
$journal = new TransactionJournal;
|
$journal = new TransactionJournal;
|
||||||
$journal->user_id = $this->job->user_id;
|
$journal->user_id = $this->job->user_id;
|
||||||
$journal->transaction_type_id = $transactionType->id;
|
$journal->transaction_type_id = $transactionType->id;
|
||||||
$journal->transaction_currency_id = $currency->id;
|
$journal->transaction_currency_id = $currency->id;
|
||||||
$journal->description = $importJournal->description;
|
$journal->description = $importJournal->getDescription();
|
||||||
$journal->date = $date->format('Y-m-d');
|
$journal->date = $date->format('Y-m-d');
|
||||||
$journal->order = 0;
|
$journal->order = 0;
|
||||||
$journal->tag_count = 0;
|
$journal->tag_count = 0;
|
||||||
@ -336,7 +395,9 @@ class ImportStorage
|
|||||||
|
|
||||||
if (!$journal->save()) {
|
if (!$journal->save()) {
|
||||||
$errorText = join(', ', $journal->getErrors()->all());
|
$errorText = join(', ', $journal->getErrors()->all());
|
||||||
|
// add three steps:
|
||||||
$this->job->addStepsDone(3);
|
$this->job->addStepsDone(3);
|
||||||
|
// throw error
|
||||||
throw new FireflyException($errorText);
|
throw new FireflyException($errorText);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +432,6 @@ class ImportStorage
|
|||||||
// run rules:
|
// run rules:
|
||||||
$this->applyRules($journal);
|
$this->applyRules($journal);
|
||||||
$this->job->addStepsDone(1);
|
$this->job->addStepsDone(1);
|
||||||
|
|
||||||
$this->journals->push($journal);
|
$this->journals->push($journal);
|
||||||
|
|
||||||
Log::info(
|
Log::info(
|
||||||
@ -402,4 +462,49 @@ class ImportStorage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if the given transaction is a transfer and if so, if it might be a duplicate of an already imported transfer.
|
||||||
|
* This is important for import files that cover multiple accounts (and include both A<>B and B<>A transactions).
|
||||||
|
*
|
||||||
|
* @param TransactionType $transactionType
|
||||||
|
* @param ImportJournal $importJournal
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function verifyDoubleTransfer(TransactionType $transactionType, ImportJournal $importJournal): bool
|
||||||
|
{
|
||||||
|
if ($transactionType->type === TransactionType::TRANSFER) {
|
||||||
|
$amount = Steam::positive($importJournal->getAmount());
|
||||||
|
$date = $importJournal->getDate($this->dateFormat);
|
||||||
|
$set = TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||||
|
->leftJoin(
|
||||||
|
'transactions AS source', function (JoinClause $join) {
|
||||||
|
$join->on('transaction_journals.id', '=', 'source.transaction_journal_id')->where('source.amount', '<', 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->leftJoin(
|
||||||
|
'transactions AS destination', function (JoinClause $join) {
|
||||||
|
$join->on('transaction_journals.id', '=', 'destination.transaction_journal_id')->where(
|
||||||
|
'destination.amount', '>', 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->leftJoin('accounts as source_accounts', 'source.account_id', '=', 'source_accounts.id')
|
||||||
|
->leftJoin('accounts as destination_accounts', 'destination.account_id', '=', 'destination_accounts.id')
|
||||||
|
->where('transaction_journals.user_id', $this->job->user_id)
|
||||||
|
->where('transaction_types.type', TransactionType::TRANSFER)
|
||||||
|
->where('transaction_journals.date', $date->format('Y-m-d'))
|
||||||
|
->where('destination.amount', $amount)
|
||||||
|
->get(
|
||||||
|
['transaction_journals.id', 'transaction_journals.encrypted', 'transaction_journals.description',
|
||||||
|
'source_accounts.name as source_name', 'destination_accounts.name as destination_name']
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->filterTransferSet($set, $importJournal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
161
app/Jobs/ExecuteRuleOnExistingTransactions.php
Normal file
161
app/Jobs/ExecuteRuleOnExistingTransactions.php
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ExecuteRuleOnExistingTransactions.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\Jobs;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
|
use FireflyIII\Models\Rule;
|
||||||
|
use FireflyIII\Rules\Processor;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ExecuteRuleOnExistingTransactions
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Jobs
|
||||||
|
*/
|
||||||
|
class ExecuteRuleOnExistingTransactions extends Job implements ShouldQueue
|
||||||
|
{
|
||||||
|
use InteractsWithQueue, SerializesModels;
|
||||||
|
|
||||||
|
/** @var Collection */
|
||||||
|
private $accounts;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $endDate;
|
||||||
|
/** @var Rule */
|
||||||
|
private $rule;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $startDate;
|
||||||
|
/** @var User */
|
||||||
|
private $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @param Rule $rule
|
||||||
|
*/
|
||||||
|
public function __construct(Rule $rule)
|
||||||
|
{
|
||||||
|
$this->rule = $rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getAccounts(): Collection
|
||||||
|
{
|
||||||
|
return $this->accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Collection $accounts
|
||||||
|
*/
|
||||||
|
public function setAccounts(Collection $accounts)
|
||||||
|
{
|
||||||
|
$this->accounts = $accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Carbon\Carbon
|
||||||
|
*/
|
||||||
|
public function getEndDate(): Carbon
|
||||||
|
{
|
||||||
|
return $this->endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Carbon $date
|
||||||
|
*/
|
||||||
|
public function setEndDate(Carbon $date)
|
||||||
|
{
|
||||||
|
$this->endDate = $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Carbon\Carbon
|
||||||
|
*/
|
||||||
|
public function getStartDate(): Carbon
|
||||||
|
{
|
||||||
|
return $this->startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Carbon $date
|
||||||
|
*/
|
||||||
|
public function setStartDate(Carbon $date)
|
||||||
|
{
|
||||||
|
$this->startDate = $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
public function getUser(): User
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function setUser(User $user)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
// Lookup all journals that match the parameters specified
|
||||||
|
$transactions = $this->collectJournals();
|
||||||
|
$processor = Processor::make($this->rule);
|
||||||
|
|
||||||
|
// Execute the rules for each transaction
|
||||||
|
foreach ($transactions as $transaction) {
|
||||||
|
|
||||||
|
$processor->handleTransaction($transaction);
|
||||||
|
|
||||||
|
// Stop processing this group if the rule specifies 'stop_processing'
|
||||||
|
if ($processor->getRule()->stop_processing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect all journals that should be processed
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
protected function collectJournals()
|
||||||
|
{
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setUser($this->user);
|
||||||
|
$collector->setAccounts($this->accounts)->setRange($this->startDate, $this->endDate);
|
||||||
|
|
||||||
|
return $collector->getJournals();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -80,7 +80,7 @@ class MailError extends Job implements ShouldQueue
|
|||||||
Mail::send(
|
Mail::send(
|
||||||
['emails.error-html', 'emails.error-text'], $args,
|
['emails.error-html', 'emails.error-text'], $args,
|
||||||
function (Message $message) use ($email) {
|
function (Message $message) use ($email) {
|
||||||
if ($email != 'mail@example.com') {
|
if ($email !== 'mail@example.com') {
|
||||||
$message->to($email, $email)->subject('Caught an error in Firely III');
|
$message->to($email, $email)->subject('Caught an error in Firely III');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ class Account extends Model
|
|||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($set as $account) {
|
foreach ($set as $account) {
|
||||||
if ($account->name == $fields['name']) {
|
if ($account->name === $fields['name']) {
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ class Account extends Model
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ class Account extends Model
|
|||||||
public function getMeta(string $fieldName): string
|
public function getMeta(string $fieldName): string
|
||||||
{
|
{
|
||||||
foreach ($this->accountMeta as $meta) {
|
foreach ($this->accountMeta as $meta) {
|
||||||
if ($meta->name == $fieldName) {
|
if ($meta->name === $fieldName) {
|
||||||
return strval($meta->data);
|
return strval($meta->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class Attachment extends Model
|
|||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
|
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class Bill extends Model
|
|||||||
public static function routeBinder(Bill $value)
|
public static function routeBinder(Bill $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ class Bill extends Model
|
|||||||
public function getMatchAttribute($value)
|
public function getMatchAttribute($value)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (intval($this->match_encrypted) == 1) {
|
if (intval($this->match_encrypted) === 1) {
|
||||||
return Crypt::decrypt($value);
|
return Crypt::decrypt($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ class Bill extends Model
|
|||||||
public function getNameAttribute($value)
|
public function getNameAttribute($value)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (intval($this->name_encrypted) == 1) {
|
if (intval($this->name_encrypted) === 1) {
|
||||||
return Crypt::decrypt($value);
|
return Crypt::decrypt($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ class Budget extends Model
|
|||||||
$set = $query->get(['budgets.*']);
|
$set = $query->get(['budgets.*']);
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($set as $budget) {
|
foreach ($set as $budget) {
|
||||||
if ($budget->name == $fields['name']) {
|
if ($budget->name === $fields['name']) {
|
||||||
return $budget;
|
return $budget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ class Budget extends Model
|
|||||||
public static function routeBinder(Budget $value)
|
public static function routeBinder(Budget $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class Category extends Model
|
|||||||
$set = $query->get(['categories.*']);
|
$set = $query->get(['categories.*']);
|
||||||
/** @var Category $category */
|
/** @var Category $category */
|
||||||
foreach ($set as $category) {
|
foreach ($set as $category) {
|
||||||
if ($category->name == $fields['name']) {
|
if ($category->name === $fields['name']) {
|
||||||
return $category;
|
return $category;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ class Category extends Model
|
|||||||
public static function routeBinder(Category $value)
|
public static function routeBinder(Category $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ class ImportJob extends Model
|
|||||||
if (is_null($value)) {
|
if (is_null($value)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
if (strlen($value) == 0) {
|
if (strlen($value) === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ class ImportJob extends Model
|
|||||||
*/
|
*/
|
||||||
public function getExtendedStatusAttribute($value)
|
public function getExtendedStatusAttribute($value)
|
||||||
{
|
{
|
||||||
if (strlen($value) == 0) {
|
if (strlen($value) === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class PiggyBank extends Model
|
|||||||
public static function routeBinder(PiggyBank $value)
|
public static function routeBinder(PiggyBank $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->account->user_id == auth()->user()->id) {
|
if (intval($value->account->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ class Rule extends Model
|
|||||||
public static function routeBinder(Rule $value)
|
public static function routeBinder(Rule $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ class RuleGroup extends Model
|
|||||||
public static function routeBinder(RuleGroup $value)
|
public static function routeBinder(RuleGroup $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class Tag extends Model
|
|||||||
$set = $query->get(['tags.*']);
|
$set = $query->get(['tags.*']);
|
||||||
/** @var Tag $tag */
|
/** @var Tag $tag */
|
||||||
foreach ($set as $tag) {
|
foreach ($set as $tag) {
|
||||||
if ($tag->tag == $fields['tag']) {
|
if ($tag->tag === $fields['tag']) {
|
||||||
return $tag;
|
return $tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ class Tag extends Model
|
|||||||
public static function routeBinder(Tag $value)
|
public static function routeBinder(Tag $value)
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ($value->user_id == auth()->user()->id) {
|
if (intval($value->user_id) === auth()->user()->id) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ class TransactionJournal extends Model
|
|||||||
public function isDeposit(): bool
|
public function isDeposit(): bool
|
||||||
{
|
{
|
||||||
if (!is_null($this->transaction_type_type)) {
|
if (!is_null($this->transaction_type_type)) {
|
||||||
return $this->transaction_type_type == TransactionType::DEPOSIT;
|
return $this->transaction_type_type === TransactionType::DEPOSIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->transactionType->isDeposit();
|
return $this->transactionType->isDeposit();
|
||||||
@ -220,7 +220,7 @@ class TransactionJournal extends Model
|
|||||||
public function isOpeningBalance(): bool
|
public function isOpeningBalance(): bool
|
||||||
{
|
{
|
||||||
if (!is_null($this->transaction_type_type)) {
|
if (!is_null($this->transaction_type_type)) {
|
||||||
return $this->transaction_type_type == TransactionType::OPENING_BALANCE;
|
return $this->transaction_type_type === TransactionType::OPENING_BALANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->transactionType->isOpeningBalance();
|
return $this->transactionType->isOpeningBalance();
|
||||||
@ -233,7 +233,7 @@ class TransactionJournal extends Model
|
|||||||
public function isTransfer(): bool
|
public function isTransfer(): bool
|
||||||
{
|
{
|
||||||
if (!is_null($this->transaction_type_type)) {
|
if (!is_null($this->transaction_type_type)) {
|
||||||
return $this->transaction_type_type == TransactionType::TRANSFER;
|
return $this->transaction_type_type === TransactionType::TRANSFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->transactionType->isTransfer();
|
return $this->transactionType->isTransfer();
|
||||||
@ -246,7 +246,7 @@ class TransactionJournal extends Model
|
|||||||
public function isWithdrawal(): bool
|
public function isWithdrawal(): bool
|
||||||
{
|
{
|
||||||
if (!is_null($this->transaction_type_type)) {
|
if (!is_null($this->transaction_type_type)) {
|
||||||
return $this->transaction_type_type == TransactionType::WITHDRAWAL;
|
return $this->transaction_type_type === TransactionType::WITHDRAWAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->transactionType->isWithdrawal();
|
return $this->transactionType->isWithdrawal();
|
||||||
|
@ -25,6 +25,7 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Log;
|
use Log;
|
||||||
|
use Validator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,7 +179,7 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
{
|
{
|
||||||
// update the account:
|
// update the account:
|
||||||
$account->name = $data['name'];
|
$account->name = $data['name'];
|
||||||
$account->active = $data['active'] == '1' ? true : false;
|
$account->active = $data['active'] === '1' ? true : false;
|
||||||
$account->virtual_balance = $data['virtualBalance'];
|
$account->virtual_balance = $data['virtualBalance'];
|
||||||
$account->iban = $data['iban'];
|
$account->iban = $data['iban'];
|
||||||
$account->save();
|
$account->save();
|
||||||
@ -236,7 +237,7 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
$data['accountType'] = $data['accountType'] ?? 'invalid';
|
$data['accountType'] = $data['accountType'] ?? 'invalid';
|
||||||
$type = config('firefly.accountTypeByIdentifier.' . $data['accountType']);
|
$type = config('firefly.accountTypeByIdentifier.' . $data['accountType']);
|
||||||
$accountType = AccountType::whereType($type)->first();
|
$accountType = AccountType::whereType($type)->first();
|
||||||
|
$data['iban'] = $this->filterIban($data['iban']);
|
||||||
// verify account type
|
// verify account type
|
||||||
if (is_null($accountType)) {
|
if (is_null($accountType)) {
|
||||||
throw new FireflyException(sprintf('Account type "%s" is invalid. Cannot create account.', $data['accountType']));
|
throw new FireflyException(sprintf('Account type "%s" is invalid. Cannot create account.', $data['accountType']));
|
||||||
@ -251,16 +252,17 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create it:
|
// create it:
|
||||||
$newAccount = new Account(
|
$databaseData
|
||||||
[
|
= [
|
||||||
'user_id' => $this->user->id,
|
'user_id' => $this->user->id,
|
||||||
'account_type_id' => $accountType->id,
|
'account_type_id' => $accountType->id,
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'virtual_balance' => $data['virtualBalance'],
|
'virtual_balance' => $data['virtualBalance'],
|
||||||
'active' => $data['active'] === true ? true : false,
|
'active' => $data['active'] === true ? true : false,
|
||||||
'iban' => $data['iban'],
|
'iban' => $data['iban'],
|
||||||
]
|
];
|
||||||
);
|
$newAccount = new Account($databaseData);
|
||||||
|
Log::debug('Final account creation dataset', $databaseData);
|
||||||
$newAccount->save();
|
$newAccount->save();
|
||||||
// verify its creation:
|
// verify its creation:
|
||||||
if (is_null($newAccount->id)) {
|
if (is_null($newAccount->id)) {
|
||||||
@ -268,6 +270,7 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
sprintf('Could not create account "%s" (%d error(s))', $data['name'], $newAccount->getErrors()->count()), $newAccount->getErrors()->toArray()
|
sprintf('Could not create account "%s" (%d error(s))', $data['name'], $newAccount->getErrors()->count()), $newAccount->getErrors()->toArray()
|
||||||
);
|
);
|
||||||
throw new FireflyException(sprintf('Tried to create account named "%s" but failed. The logs have more details.', $data['name']));
|
throw new FireflyException(sprintf('Tried to create account named "%s" but failed. The logs have more details.', $data['name']));
|
||||||
|
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Created new account #%d named "%s" of type %s.', $newAccount->id, $newAccount->name, $accountType->type));
|
Log::debug(sprintf('Created new account #%d named "%s" of type %s.', $newAccount->id, $newAccount->name, $accountType->type));
|
||||||
|
|
||||||
@ -457,12 +460,12 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
// update transactions:
|
// update transactions:
|
||||||
/** @var Transaction $transaction */
|
/** @var Transaction $transaction */
|
||||||
foreach ($journal->transactions()->get() as $transaction) {
|
foreach ($journal->transactions()->get() as $transaction) {
|
||||||
if ($account->id == $transaction->account_id) {
|
if ($account->id === $transaction->account_id) {
|
||||||
$transaction->amount = $amount;
|
$transaction->amount = $amount;
|
||||||
$transaction->transaction_currency_id = $currencyId;
|
$transaction->transaction_currency_id = $currencyId;
|
||||||
$transaction->save();
|
$transaction->save();
|
||||||
}
|
}
|
||||||
if ($account->id != $transaction->account_id) {
|
if ($account->id !== $transaction->account_id) {
|
||||||
$transaction->amount = bcmul($amount, '-1');
|
$transaction->amount = bcmul($amount, '-1');
|
||||||
$transaction->transaction_currency_id = $currencyId;
|
$transaction->transaction_currency_id = $currencyId;
|
||||||
$transaction->save();
|
$transaction->save();
|
||||||
@ -491,4 +494,26 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null|string $iban
|
||||||
|
*
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
private function filterIban(string $iban = null)
|
||||||
|
{
|
||||||
|
if (is_null($iban)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$data = ['iban' => $iban];
|
||||||
|
$rules = ['iban' => 'required|iban'];
|
||||||
|
$validator = Validator::make($data, $rules);
|
||||||
|
if ($validator->fails()) {
|
||||||
|
Log::error(sprintf('Detected invalid IBAN ("%s"). Return NULL instead.', $iban));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $iban;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$set = $set->sortBy(
|
$set = $set->sortBy(
|
||||||
function (Bill $bill) {
|
function (Bill $bill) {
|
||||||
|
|
||||||
$int = $bill->active == 1 ? 0 : 1;
|
$int = $bill->active === 1 ? 0 : 1;
|
||||||
|
|
||||||
return $int . strtolower($bill->name);
|
return $int . strtolower($bill->name);
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$set = $set->sortBy(
|
$set = $set->sortBy(
|
||||||
function (Bill $bill) {
|
function (Bill $bill) {
|
||||||
|
|
||||||
$int = $bill->active == 1 ? 0 : 1;
|
$int = $bill->active === 1 ? 0 : 1;
|
||||||
|
|
||||||
return $int . strtolower($bill->name);
|
return $int . strtolower($bill->name);
|
||||||
}
|
}
|
||||||
@ -500,7 +500,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($bill->id == $journal->bill_id) {
|
if ($bill->id === $journal->bill_id) {
|
||||||
// if no match, but bill used to match, remove it:
|
// if no match, but bill used to match, remove it:
|
||||||
$journal->bill_id = null;
|
$journal->bill_id = null;
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
@ -32,7 +32,14 @@ use Log;
|
|||||||
*/
|
*/
|
||||||
trait CreateJournalsTrait
|
trait CreateJournalsTrait
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
* @param TransactionType $type
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
abstract public function storeAccounts(User $user, TransactionType $type, array $data): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -73,7 +73,7 @@ trait UpdateJournalsTrait
|
|||||||
protected function updateDestinationTransaction(TransactionJournal $journal, Account $account, array $data)
|
protected function updateDestinationTransaction(TransactionJournal $journal, Account $account, array $data)
|
||||||
{
|
{
|
||||||
$set = $journal->transactions()->where('amount', '>', 0)->get();
|
$set = $journal->transactions()->where('amount', '>', 0)->get();
|
||||||
if ($set->count() != 1) {
|
if ($set->count() !== 1) {
|
||||||
throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count()));
|
throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count()));
|
||||||
}
|
}
|
||||||
/** @var Transaction $transaction */
|
/** @var Transaction $transaction */
|
||||||
@ -98,7 +98,7 @@ trait UpdateJournalsTrait
|
|||||||
{
|
{
|
||||||
// should be one:
|
// should be one:
|
||||||
$set = $journal->transactions()->where('amount', '<', 0)->get();
|
$set = $journal->transactions()->where('amount', '<', 0)->get();
|
||||||
if ($set->count() != 1) {
|
if ($set->count() !== 1) {
|
||||||
throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count()));
|
throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count()));
|
||||||
}
|
}
|
||||||
/** @var Transaction $transaction */
|
/** @var Transaction $transaction */
|
||||||
@ -140,7 +140,7 @@ trait UpdateJournalsTrait
|
|||||||
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete();
|
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete();
|
||||||
}
|
}
|
||||||
// if count is zero, delete them all:
|
// if count is zero, delete them all:
|
||||||
if (count($ids) == 0) {
|
if (count($ids) === 0) {
|
||||||
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
|
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ class RuleRepository implements RuleRepositoryInterface
|
|||||||
$rule->rule_group_id = $data['rule_group_id'];
|
$rule->rule_group_id = $data['rule_group_id'];
|
||||||
$rule->order = ($order + 1);
|
$rule->order = ($order + 1);
|
||||||
$rule->active = 1;
|
$rule->active = 1;
|
||||||
$rule->stop_processing = intval($data['stop_processing']) == 1;
|
$rule->stop_processing = intval($data['stop_processing']) === 1;
|
||||||
$rule->title = $data['title'];
|
$rule->title = $data['title'];
|
||||||
$rule->description = strlen($data['description']) > 0 ? $data['description'] : null;
|
$rule->description = strlen($data['description']) > 0 ? $data['description'] : null;
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ class RuleRepository implements RuleRepositoryInterface
|
|||||||
$ruleAction->active = 1;
|
$ruleAction->active = 1;
|
||||||
$ruleAction->stop_processing = $values['stopProcessing'];
|
$ruleAction->stop_processing = $values['stopProcessing'];
|
||||||
$ruleAction->action_type = $values['action'];
|
$ruleAction->action_type = $values['action'];
|
||||||
$ruleAction->action_value = $values['value'];
|
$ruleAction->action_value = is_null($values['value']) ? '' : $values['value'];
|
||||||
$ruleAction->save();
|
$ruleAction->save();
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
* changed to an advancePayment.
|
* changed to an advancePayment.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ($tag->tagMode == 'balancingAct' || $tag->tagMode == 'nothing') {
|
if ($tag->tagMode === 'balancingAct' || $tag->tagMode === 'nothing') {
|
||||||
foreach ($tag->transactionjournals as $journal) {
|
foreach ($tag->transactionjournals as $journal) {
|
||||||
if ($journal->isTransfer()) {
|
if ($journal->isTransfer()) {
|
||||||
return false;
|
return false;
|
||||||
@ -394,7 +394,7 @@ class TagRepository implements TagRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if already has transaction journals, must match ALL asset account id's:
|
// if already has transaction journals, must match ALL asset account id's:
|
||||||
if ($deposits > 0 || $withdrawals == 1) {
|
if ($deposits > 0 || $withdrawals === 1) {
|
||||||
Log::debug('Need to match all asset accounts.');
|
Log::debug('Need to match all asset accounts.');
|
||||||
|
|
||||||
return $this->matchAll($journal, $tag);
|
return $this->matchAll($journal, $tag);
|
||||||
|
@ -52,7 +52,7 @@ class RemoveTag implements ActionInterface
|
|||||||
/** @var Tag $tag */
|
/** @var Tag $tag */
|
||||||
$tag = $journal->user->tags()->get()->filter(
|
$tag = $journal->user->tags()->get()->filter(
|
||||||
function (Tag $tag) use ($name) {
|
function (Tag $tag) use ($name) {
|
||||||
return $tag->tag == $name;
|
return $tag->tag === $name;
|
||||||
}
|
}
|
||||||
)->first();
|
)->first();
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class SetBudget implements ActionInterface
|
|||||||
$budgets = $repository->getActiveBudgets();
|
$budgets = $repository->getActiveBudgets();
|
||||||
$budget = $budgets->filter(
|
$budget = $budgets->filter(
|
||||||
function (Budget $current) use ($search) {
|
function (Budget $current) use ($search) {
|
||||||
return $current->name == $search;
|
return $current->name === $search;
|
||||||
}
|
}
|
||||||
)->first();
|
)->first();
|
||||||
if (is_null($budget)) {
|
if (is_null($budget)) {
|
||||||
@ -65,7 +65,7 @@ class SetBudget implements ActionInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($journal->transactionType->type == TransactionType::TRANSFER) {
|
if ($journal->transactionType->type === TransactionType::TRANSFER) {
|
||||||
Log::debug(sprintf('RuleAction SetBudget could not set budget of journal #%d to "%s" because journal is a transfer.', $journal->id, $search));
|
Log::debug(sprintf('RuleAction SetBudget could not set budget of journal #%d to "%s" because journal is a transfer.', $journal->id, $search));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -59,9 +59,11 @@ final class Processor
|
|||||||
*
|
*
|
||||||
* @param Rule $rule
|
* @param Rule $rule
|
||||||
*
|
*
|
||||||
|
* @param bool $includeActions
|
||||||
|
*
|
||||||
* @return Processor
|
* @return Processor
|
||||||
*/
|
*/
|
||||||
public static function make(Rule $rule)
|
public static function make(Rule $rule, $includeActions = true)
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Making new rule from Rule %d', $rule->id));
|
Log::debug(sprintf('Making new rule from Rule %d', $rule->id));
|
||||||
$self = new self;
|
$self = new self;
|
||||||
@ -72,7 +74,9 @@ final class Processor
|
|||||||
Log::debug(sprintf('Push trigger %d', $trigger->id));
|
Log::debug(sprintf('Push trigger %d', $trigger->id));
|
||||||
$self->triggers->push(TriggerFactory::getTrigger($trigger));
|
$self->triggers->push(TriggerFactory::getTrigger($trigger));
|
||||||
}
|
}
|
||||||
|
if ($includeActions) {
|
||||||
$self->actions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
$self->actions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
||||||
|
}
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
@ -254,7 +258,7 @@ final class Processor
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
$result = ($hitTriggers == $foundTriggers && $foundTriggers > 0);
|
$result = ($hitTriggers === $foundTriggers && $foundTriggers > 0);
|
||||||
Log::debug('Result of triggered()', ['hitTriggers' => $hitTriggers, 'foundTriggers' => $foundTriggers, 'result' => $result]);
|
Log::debug('Result of triggered()', ['hitTriggers' => $hitTriggers, 'foundTriggers' => $foundTriggers, 'result' => $result]);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -14,6 +14,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Rules;
|
namespace FireflyIII\Rules;
|
||||||
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
|
use FireflyIII\Models\Rule;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
|
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
|
||||||
@ -32,6 +33,8 @@ class TransactionMatcher
|
|||||||
private $limit = 10;
|
private $limit = 10;
|
||||||
/** @var int Maximum number of transaction to search in (for performance reasons) * */
|
/** @var int Maximum number of transaction to search in (for performance reasons) * */
|
||||||
private $range = 200;
|
private $range = 200;
|
||||||
|
/** @var Rule */
|
||||||
|
private $rule;
|
||||||
/** @var JournalTaskerInterface */
|
/** @var JournalTaskerInterface */
|
||||||
private $tasker;
|
private $tasker;
|
||||||
/** @var array */
|
/** @var array */
|
||||||
@ -50,6 +53,31 @@ class TransactionMatcher
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will search the user's transaction journal (with an upper limit of $range) for
|
||||||
|
* transaction journals matching the given rule. This is accomplished by trying to fire these
|
||||||
|
* triggers onto each transaction journal until enough matches are found ($limit).
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function findTransactionsByRule()
|
||||||
|
{
|
||||||
|
if (count($this->rule->ruleTriggers) === 0) {
|
||||||
|
return new Collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables used within the loop
|
||||||
|
$processor = Processor::make($this->rule, false);
|
||||||
|
$result = $this->runProcessor($processor);
|
||||||
|
|
||||||
|
// If the list of matchingTransactions is larger than the maximum number of results
|
||||||
|
// (e.g. if a large percentage of the transactions match), truncate the list
|
||||||
|
$result = $result->slice(0, $this->limit);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will search the user's transaction journal (with an upper limit of $range) for
|
* This method will search the user's transaction journal (with an upper limit of $range) for
|
||||||
* transaction journals matching the given $triggers. This is accomplished by trying to fire these
|
* transaction journals matching the given $triggers. This is accomplished by trying to fire these
|
||||||
@ -58,64 +86,15 @@ class TransactionMatcher
|
|||||||
* @return Collection
|
* @return Collection
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function findMatchingTransactions(): Collection
|
public function findTransactionsByTriggers(): Collection
|
||||||
{
|
{
|
||||||
if (count($this->triggers) === 0) {
|
if (count($this->triggers) === 0) {
|
||||||
return new Collection;
|
return new Collection;
|
||||||
}
|
}
|
||||||
$pageSize = min($this->range / 2, $this->limit * 2);
|
|
||||||
|
|
||||||
// Variables used within the loop
|
// Variables used within the loop
|
||||||
$processed = 0;
|
|
||||||
$page = 1;
|
|
||||||
$result = new Collection();
|
|
||||||
$processor = Processor::makeFromStringArray($this->triggers);
|
$processor = Processor::makeFromStringArray($this->triggers);
|
||||||
|
$result = $this->runProcessor($processor);
|
||||||
// Start a loop to fetch batches of transactions. The loop will finish if:
|
|
||||||
// - all transactions have been fetched from the database
|
|
||||||
// - the maximum number of transactions to return has been found
|
|
||||||
// - the maximum number of transactions to search in have been searched
|
|
||||||
do {
|
|
||||||
// Fetch a batch of transactions from the database
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setUser(auth()->user());
|
|
||||||
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTypes($this->transactionTypes);
|
|
||||||
$set = $collector->getPaginatedJournals();
|
|
||||||
Log::debug(sprintf('Found %d journals to check. ', $set->count()));
|
|
||||||
|
|
||||||
// Filter transactions that match the given triggers.
|
|
||||||
$filtered = $set->filter(
|
|
||||||
function (Transaction $transaction) use ($processor) {
|
|
||||||
Log::debug(sprintf('Test these triggers on journal #%d (transaction #%d)', $transaction->transaction_journal_id, $transaction->id));
|
|
||||||
|
|
||||||
return $processor->handleTransaction($transaction);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Log::debug(sprintf('Found %d journals that match.', $filtered->count()));
|
|
||||||
|
|
||||||
// merge:
|
|
||||||
/** @var Collection $result */
|
|
||||||
$result = $result->merge($filtered);
|
|
||||||
Log::debug(sprintf('Total count is now %d', $result->count()));
|
|
||||||
|
|
||||||
// Update counters
|
|
||||||
$page++;
|
|
||||||
$processed += count($set);
|
|
||||||
|
|
||||||
Log::debug(sprintf('Page is now %d, processed is %d', $page, $processed));
|
|
||||||
|
|
||||||
// Check for conditions to finish the loop
|
|
||||||
$reachedEndOfList = $set->count() < 1;
|
|
||||||
$foundEnough = $result->count() >= $this->limit;
|
|
||||||
$searchedEnough = ($processed >= $this->range);
|
|
||||||
|
|
||||||
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
|
|
||||||
Log::debug(sprintf('foundEnough: %s', var_export($foundEnough, true)));
|
|
||||||
Log::debug(sprintf('searchedEnough: %s', var_export($searchedEnough, true)));
|
|
||||||
|
|
||||||
} while (!$reachedEndOfList && !$foundEnough && !$searchedEnough);
|
|
||||||
|
|
||||||
// If the list of matchingTransactions is larger than the maximum number of results
|
// If the list of matchingTransactions is larger than the maximum number of results
|
||||||
// (e.g. if a large percentage of the transactions match), truncate the list
|
// (e.g. if a large percentage of the transactions match), truncate the list
|
||||||
@ -185,5 +164,73 @@ class TransactionMatcher
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Rule $rule
|
||||||
|
*/
|
||||||
|
public function setRule(Rule $rule)
|
||||||
|
{
|
||||||
|
$this->rule = $rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Processor $processor
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
private function runProcessor(Processor $processor): Collection
|
||||||
|
{
|
||||||
|
// Start a loop to fetch batches of transactions. The loop will finish if:
|
||||||
|
// - all transactions have been fetched from the database
|
||||||
|
// - the maximum number of transactions to return has been found
|
||||||
|
// - the maximum number of transactions to search in have been searched
|
||||||
|
$pageSize = min($this->range / 2, $this->limit * 2);
|
||||||
|
$processed = 0;
|
||||||
|
$page = 1;
|
||||||
|
$result = new Collection();
|
||||||
|
do {
|
||||||
|
// Fetch a batch of transactions from the database
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setUser(auth()->user());
|
||||||
|
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTypes($this->transactionTypes);
|
||||||
|
$set = $collector->getPaginatedJournals();
|
||||||
|
Log::debug(sprintf('Found %d journals to check. ', $set->count()));
|
||||||
|
|
||||||
|
// Filter transactions that match the given triggers.
|
||||||
|
$filtered = $set->filter(
|
||||||
|
function (Transaction $transaction) use ($processor) {
|
||||||
|
Log::debug(sprintf('Test these triggers on journal #%d (transaction #%d)', $transaction->transaction_journal_id, $transaction->id));
|
||||||
|
|
||||||
|
return $processor->handleTransaction($transaction);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Log::debug(sprintf('Found %d journals that match.', $filtered->count()));
|
||||||
|
|
||||||
|
// merge:
|
||||||
|
/** @var Collection $result */
|
||||||
|
$result = $result->merge($filtered);
|
||||||
|
Log::debug(sprintf('Total count is now %d', $result->count()));
|
||||||
|
|
||||||
|
// Update counters
|
||||||
|
$page++;
|
||||||
|
$processed += count($set);
|
||||||
|
|
||||||
|
Log::debug(sprintf('Page is now %d, processed is %d', $page, $processed));
|
||||||
|
|
||||||
|
// Check for conditions to finish the loop
|
||||||
|
$reachedEndOfList = $set->count() < 1;
|
||||||
|
$foundEnough = $result->count() >= $this->limit;
|
||||||
|
$searchedEnough = ($processed >= $this->range);
|
||||||
|
|
||||||
|
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
|
||||||
|
Log::debug(sprintf('foundEnough: %s', var_export($foundEnough, true)));
|
||||||
|
Log::debug(sprintf('searchedEnough: %s', var_export($searchedEnough, true)));
|
||||||
|
|
||||||
|
} while (!$reachedEndOfList && !$foundEnough && !$searchedEnough);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -311,6 +311,9 @@ class Amount
|
|||||||
$coloured = false;
|
$coloured = false;
|
||||||
$format = '<span class="text-info">%s</span>';
|
$format = '<span class="text-info">%s</span>';
|
||||||
}
|
}
|
||||||
|
if ($transaction->transaction_type_type === TransactionType::OPENING_BALANCE) {
|
||||||
|
$amount = strval($transaction->transaction_amount);
|
||||||
|
}
|
||||||
|
|
||||||
$currency = new TransactionCurrency;
|
$currency = new TransactionCurrency;
|
||||||
$currency->symbol = $transaction->transaction_currency_symbol;
|
$currency->symbol = $transaction->transaction_currency_symbol;
|
||||||
|
@ -18,7 +18,6 @@ use Cache;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
|
||||||
use Preferences as Prefs;
|
use Preferences as Prefs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +74,7 @@ class CacheProperties
|
|||||||
*/
|
*/
|
||||||
public function has(): bool
|
public function has(): bool
|
||||||
{
|
{
|
||||||
if (getenv('APP_ENV') == 'testing') {
|
if (getenv('APP_ENV') === 'testing') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->md5();
|
$this->md5();
|
||||||
@ -119,8 +118,6 @@ class CacheProperties
|
|||||||
|
|
||||||
$this->md5 .= json_encode($property);
|
$this->md5 .= json_encode($property);
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Cache string is %s', $this->md5));
|
|
||||||
$this->md5 = md5($this->md5);
|
$this->md5 = md5($this->md5);
|
||||||
Log::debug(sprintf('Cache MD5 is %s', $this->md5));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,9 @@ class Map implements ConfigurationInterface
|
|||||||
}
|
}
|
||||||
foreach ($this->data as $index => $entry) {
|
foreach ($this->data as $index => $entry) {
|
||||||
$this->data[$index]['values'] = array_unique($this->data[$index]['values']);
|
$this->data[$index]['values'] = array_unique($this->data[$index]['values']);
|
||||||
|
asort($this->data[$index]['values']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save number of rows, thus number of steps, in job:
|
// save number of rows, thus number of steps, in job:
|
||||||
$steps = $rowIndex * 5;
|
$steps = $rowIndex * 5;
|
||||||
$extended = $this->job->extended_status;
|
$extended = $this->job->extended_status;
|
||||||
|
@ -96,7 +96,7 @@ class Navigation
|
|||||||
// if the range is custom, the end of the period
|
// if the range is custom, the end of the period
|
||||||
// is another X days (x is the difference between start)
|
// is another X days (x is the difference between start)
|
||||||
// and end added to $theCurrentEnd
|
// and end added to $theCurrentEnd
|
||||||
if ($repeatFreq == 'custom') {
|
if ($repeatFreq === 'custom') {
|
||||||
/** @var Carbon $tStart */
|
/** @var Carbon $tStart */
|
||||||
$tStart = session('start', Carbon::now()->startOfMonth());
|
$tStart = session('start', Carbon::now()->startOfMonth());
|
||||||
/** @var Carbon $tEnd */
|
/** @var Carbon $tEnd */
|
||||||
@ -393,7 +393,7 @@ class Navigation
|
|||||||
|
|
||||||
return $date;
|
return $date;
|
||||||
}
|
}
|
||||||
if ($repeatFreq == 'half-year' || $repeatFreq == '6M') {
|
if ($repeatFreq === 'half-year' || $repeatFreq === '6M') {
|
||||||
$month = $date->month;
|
$month = $date->month;
|
||||||
$date->startOfYear();
|
$date->startOfYear();
|
||||||
if ($month >= 7) {
|
if ($month >= 7) {
|
||||||
@ -496,7 +496,7 @@ class Navigation
|
|||||||
|
|
||||||
return $end;
|
return $end;
|
||||||
}
|
}
|
||||||
if ($range == '6M') {
|
if ($range === '6M') {
|
||||||
if ($start->month >= 7) {
|
if ($start->month >= 7) {
|
||||||
$end->endOfYear();
|
$end->endOfYear();
|
||||||
|
|
||||||
@ -532,7 +532,7 @@ class Navigation
|
|||||||
|
|
||||||
return $start;
|
return $start;
|
||||||
}
|
}
|
||||||
if ($range == '6M') {
|
if ($range === '6M') {
|
||||||
if ($start->month >= 7) {
|
if ($start->month >= 7) {
|
||||||
$start->startOfYear()->addMonths(6);
|
$start->startOfYear()->addMonths(6);
|
||||||
|
|
||||||
|
@ -86,17 +86,17 @@ class Modifier
|
|||||||
case 'date':
|
case 'date':
|
||||||
case 'on':
|
case 'on':
|
||||||
$res = self::sameDate($transaction->date, $modifier['value']);
|
$res = self::sameDate($transaction->date, $modifier['value']);
|
||||||
Log::debug(sprintf('Date is %s? %s', $modifier['value'], var_export($res, true)));
|
Log::debug(sprintf('Date same as %s? %s', $modifier['value'], var_export($res, true)));
|
||||||
break;
|
break;
|
||||||
case 'date_before':
|
case 'date_before':
|
||||||
case 'before':
|
case 'before':
|
||||||
$res = self::dateBefore($transaction->date, $modifier['value']);
|
$res = self::dateBefore($transaction->date, $modifier['value']);
|
||||||
Log::debug(sprintf('Date is %s? %s', $modifier['value'], var_export($res, true)));
|
Log::debug(sprintf('Date before %s? %s', $modifier['value'], var_export($res, true)));
|
||||||
break;
|
break;
|
||||||
case 'date_after':
|
case 'date_after':
|
||||||
case 'after':
|
case 'after':
|
||||||
$res = self::dateAfter($transaction->date, $modifier['value']);
|
$res = self::dateAfter($transaction->date, $modifier['value']);
|
||||||
Log::debug(sprintf('Date is %s? %s', $modifier['value'], var_export($res, true)));
|
Log::debug(sprintf('Date before %s? %s', $modifier['value'], var_export($res, true)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,11 +17,6 @@ namespace FireflyIII\Support\Search;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use FireflyIII\Models\AccountType;
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
use FireflyIII\Models\Category;
|
|
||||||
use FireflyIII\Models\Tag;
|
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -98,112 +93,20 @@ class Search implements SearchInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchAccounts(): Collection
|
|
||||||
{
|
|
||||||
$words = $this->words;
|
|
||||||
$accounts = $this->user->accounts()
|
|
||||||
->accountTypeIn([AccountType::DEFAULT, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE, AccountType::BENEFICIARY])
|
|
||||||
->get(['accounts.*']);
|
|
||||||
/** @var Collection $result */
|
|
||||||
$result = $accounts->filter(
|
|
||||||
function (Account $account) use ($words) {
|
|
||||||
if ($this->strpos_arr(strtolower($account->name), $words)) {
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = $result->slice(0, $this->limit);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchBudgets(): Collection
|
|
||||||
{
|
|
||||||
/** @var Collection $set */
|
|
||||||
$set = auth()->user()->budgets()->get();
|
|
||||||
$words = $this->words;
|
|
||||||
/** @var Collection $result */
|
|
||||||
$result = $set->filter(
|
|
||||||
function (Budget $budget) use ($words) {
|
|
||||||
if ($this->strpos_arr(strtolower($budget->name), $words)) {
|
|
||||||
return $budget;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = $result->slice(0, $this->limit);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchCategories(): Collection
|
|
||||||
{
|
|
||||||
$words = $this->words;
|
|
||||||
$categories = $this->user->categories()->get();
|
|
||||||
/** @var Collection $result */
|
|
||||||
$result = $categories->filter(
|
|
||||||
function (Category $category) use ($words) {
|
|
||||||
if ($this->strpos_arr(strtolower($category->name), $words)) {
|
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$result = $result->slice(0, $this->limit);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchTags(): Collection
|
|
||||||
{
|
|
||||||
$words = $this->words;
|
|
||||||
$tags = $this->user->tags()->get();
|
|
||||||
/** @var Collection $result */
|
|
||||||
$result = $tags->filter(
|
|
||||||
function (Tag $tag) use ($words) {
|
|
||||||
if ($this->strpos_arr(strtolower($tag->tag), $words)) {
|
|
||||||
return $tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$result = $result->slice(0, $this->limit);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function searchTransactions(): Collection
|
public function searchTransactions(): Collection
|
||||||
{
|
{
|
||||||
|
Log::debug('Start of searchTransactions()');
|
||||||
$pageSize = 100;
|
$pageSize = 100;
|
||||||
$processed = 0;
|
$processed = 0;
|
||||||
$page = 1;
|
$page = 1;
|
||||||
$result = new Collection();
|
$result = new Collection();
|
||||||
|
$startTime = microtime(true);
|
||||||
do {
|
do {
|
||||||
/** @var JournalCollectorInterface $collector */
|
/** @var JournalCollectorInterface $collector */
|
||||||
$collector = app(JournalCollectorInterface::class);
|
$collector = app(JournalCollectorInterface::class);
|
||||||
$collector->setUser($this->user);
|
|
||||||
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page);
|
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page);
|
||||||
if ($this->hasModifiers()) {
|
if ($this->hasModifiers()) {
|
||||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||||
@ -247,7 +150,11 @@ class Search implements SearchInterface
|
|||||||
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
|
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
|
||||||
Log::debug(sprintf('foundEnough: %s', var_export($foundEnough, true)));
|
Log::debug(sprintf('foundEnough: %s', var_export($foundEnough, true)));
|
||||||
|
|
||||||
} while (!$reachedEndOfList && !$foundEnough);
|
// break at some point so the script does not crash:
|
||||||
|
$currentTime = microtime(true) - $startTime;
|
||||||
|
Log::debug(sprintf('Have been running for %f seconds.', $currentTime));
|
||||||
|
|
||||||
|
} while (!$reachedEndOfList && !$foundEnough && $currentTime <= 30);
|
||||||
|
|
||||||
$result = $result->slice(0, $this->limit);
|
$result = $result->slice(0, $this->limit);
|
||||||
|
|
||||||
|
@ -38,25 +38,6 @@ interface SearchInterface
|
|||||||
*/
|
*/
|
||||||
public function parseQuery(string $query);
|
public function parseQuery(string $query);
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchAccounts(): Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchBudgets(): Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchCategories(): Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchTags(): Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
|
@ -19,6 +19,7 @@ use Crypt;
|
|||||||
use DB;
|
use DB;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,4 +346,20 @@ class Steam
|
|||||||
return $amount;
|
return $amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $value
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function tryDecrypt($value)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$value = Crypt::decrypt($value);
|
||||||
|
} catch (DecryptException $e) {
|
||||||
|
// do not care.
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ class General extends Twig_Extension
|
|||||||
$what = $args[2]; // name of the route.
|
$what = $args[2]; // name of the route.
|
||||||
$activeWhat = $context['what'] ?? false;
|
$activeWhat = $context['what'] ?? false;
|
||||||
|
|
||||||
if ($what == $activeWhat && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
|
if ($what === $activeWhat && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
|
||||||
return 'active';
|
return 'active';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ class General extends Twig_Extension
|
|||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$route = $args[0]; // name of the route.
|
$route = $args[0]; // name of the route.
|
||||||
|
|
||||||
if (Route::getCurrentRoute()->getName() == $route) {
|
if (Route::getCurrentRoute()->getName() === $route) {
|
||||||
return 'active';
|
return 'active';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class Journal extends Twig_Extension
|
|||||||
$array = [];
|
$array = [];
|
||||||
/** @var Account $entry */
|
/** @var Account $entry */
|
||||||
foreach ($list as $entry) {
|
foreach ($list as $entry) {
|
||||||
if ($entry->accountType->type == AccountType::CASH) {
|
if ($entry->accountType->type === AccountType::CASH) {
|
||||||
$array[] = '<span class="text-success">(cash)</span>';
|
$array[] = '<span class="text-success">(cash)</span>';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ class Journal extends Twig_Extension
|
|||||||
$array = [];
|
$array = [];
|
||||||
/** @var Account $entry */
|
/** @var Account $entry */
|
||||||
foreach ($list as $entry) {
|
foreach ($list as $entry) {
|
||||||
if ($entry->accountType->type == 'Cash account') {
|
if ($entry->accountType->type === AccountType::CASH) {
|
||||||
$array[] = '<span class="text-success">(cash)</span>';
|
$array[] = '<span class="text-success">(cash)</span>';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ class Rule extends Twig_Extension
|
|||||||
$ruleTriggers = array_keys(Config::get('firefly.rule-triggers'));
|
$ruleTriggers = array_keys(Config::get('firefly.rule-triggers'));
|
||||||
$possibleTriggers = [];
|
$possibleTriggers = [];
|
||||||
foreach ($ruleTriggers as $key) {
|
foreach ($ruleTriggers as $key) {
|
||||||
if ($key != 'user_action') {
|
if ($key !== 'user_action') {
|
||||||
$possibleTriggers[$key] = trans('firefly.rule_trigger_' . $key . '_choice');
|
$possibleTriggers[$key] = trans('firefly.rule_trigger_' . $key . '_choice');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
|
|
||||||
foreach ($this->roles as $role) {
|
foreach ($this->roles as $role) {
|
||||||
if ($role->name == $name) {
|
if ($role->name === $name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ class FireflyValidator extends Validator
|
|||||||
// count budgets, should have at least one
|
// count budgets, should have at least one
|
||||||
$count = $budgets->filter(
|
$count = $budgets->filter(
|
||||||
function (Budget $budget) use ($value) {
|
function (Budget $budget) use ($value) {
|
||||||
return $budget->name == $value;
|
return $budget->name === $value;
|
||||||
}
|
}
|
||||||
)->count();
|
)->count();
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ class FireflyValidator extends Validator
|
|||||||
|
|
||||||
/** @var AccountMeta $entry */
|
/** @var AccountMeta $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
if ($entry->data == $value) {
|
if ($entry->data === $value) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -398,7 +398,7 @@ class FireflyValidator extends Validator
|
|||||||
/** @var PiggyBank $entry */
|
/** @var PiggyBank $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$fieldValue = $this->tryDecrypt($entry->name);
|
$fieldValue = $this->tryDecrypt($entry->name);
|
||||||
if ($fieldValue == $value) {
|
if ($fieldValue === $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -460,7 +460,7 @@ class FireflyValidator extends Validator
|
|||||||
$set = $user->accounts()->where('account_type_id', $type->id)->get();
|
$set = $user->accounts()->where('account_type_id', $type->id)->get();
|
||||||
/** @var Account $entry */
|
/** @var Account $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
if ($entry->name == $value) {
|
if ($entry->name === $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,7 +486,7 @@ class FireflyValidator extends Validator
|
|||||||
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
||||||
/** @var Account $entry */
|
/** @var Account $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
if ($entry->name == $value) {
|
if ($entry->name === $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -510,7 +510,7 @@ class FireflyValidator extends Validator
|
|||||||
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
||||||
/** @var Account $entry */
|
/** @var Account $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
if ($entry->name == $value) {
|
if ($entry->name === $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -534,7 +534,7 @@ class FireflyValidator extends Validator
|
|||||||
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
||||||
/** @var Account $entry */
|
/** @var Account $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
if ($entry->name == $value) {
|
if ($entry->name === $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
189
composer.lock
generated
189
composer.lock
generated
@ -220,16 +220,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/cache",
|
"name": "doctrine/cache",
|
||||||
"version": "v1.6.1",
|
"version": "v1.6.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/cache.git",
|
"url": "https://github.com/doctrine/cache.git",
|
||||||
"reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3"
|
"reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3",
|
"url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b",
|
||||||
"reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3",
|
"reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -286,7 +286,7 @@
|
|||||||
"cache",
|
"cache",
|
||||||
"caching"
|
"caching"
|
||||||
],
|
],
|
||||||
"time": "2016-10-29T11:16:17+00:00"
|
"time": "2017-07-22T12:49:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/collections",
|
"name": "doctrine/collections",
|
||||||
@ -357,16 +357,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/common",
|
"name": "doctrine/common",
|
||||||
"version": "v2.7.2",
|
"version": "v2.7.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/common.git",
|
"url": "https://github.com/doctrine/common.git",
|
||||||
"reference": "930297026c8009a567ac051fd545bf6124150347"
|
"reference": "4acb8f89626baafede6ee5475bc5844096eba8a9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/common/zipball/930297026c8009a567ac051fd545bf6124150347",
|
"url": "https://api.github.com/repos/doctrine/common/zipball/4acb8f89626baafede6ee5475bc5844096eba8a9",
|
||||||
"reference": "930297026c8009a567ac051fd545bf6124150347",
|
"reference": "4acb8f89626baafede6ee5475bc5844096eba8a9",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -426,20 +426,20 @@
|
|||||||
"persistence",
|
"persistence",
|
||||||
"spl"
|
"spl"
|
||||||
],
|
],
|
||||||
"time": "2017-01-13T14:02:13+00:00"
|
"time": "2017-07-22T08:35:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/dbal",
|
"name": "doctrine/dbal",
|
||||||
"version": "v2.5.12",
|
"version": "v2.5.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/dbal.git",
|
"url": "https://github.com/doctrine/dbal.git",
|
||||||
"reference": "7b9e911f9d8b30d43b96853dab26898c710d8f44"
|
"reference": "729340d8d1eec8f01bff708e12e449a3415af873"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/7b9e911f9d8b30d43b96853dab26898c710d8f44",
|
"url": "https://api.github.com/repos/doctrine/dbal/zipball/729340d8d1eec8f01bff708e12e449a3415af873",
|
||||||
"reference": "7b9e911f9d8b30d43b96853dab26898c710d8f44",
|
"reference": "729340d8d1eec8f01bff708e12e449a3415af873",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -497,37 +497,37 @@
|
|||||||
"persistence",
|
"persistence",
|
||||||
"queryobject"
|
"queryobject"
|
||||||
],
|
],
|
||||||
"time": "2017-02-08T12:53:47+00:00"
|
"time": "2017-07-22T20:44:48+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/inflector",
|
"name": "doctrine/inflector",
|
||||||
"version": "v1.1.0",
|
"version": "v1.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/inflector.git",
|
"url": "https://github.com/doctrine/inflector.git",
|
||||||
"reference": "90b2128806bfde671b6952ab8bea493942c1fdae"
|
"reference": "e11d84c6e018beedd929cff5220969a3c6d1d462"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae",
|
"url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462",
|
||||||
"reference": "90b2128806bfde671b6952ab8bea493942c1fdae",
|
"reference": "e11d84c6e018beedd929cff5220969a3c6d1d462",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.2"
|
"php": "^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "4.*"
|
"phpunit/phpunit": "^6.2"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.1.x-dev"
|
"dev-master": "1.2.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Inflector\\": "lib/"
|
"Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@ -564,7 +564,7 @@
|
|||||||
"singularize",
|
"singularize",
|
||||||
"string"
|
"string"
|
||||||
],
|
],
|
||||||
"time": "2015-11-06T14:35:42+00:00"
|
"time": "2017-07-22T12:18:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/lexer",
|
"name": "doctrine/lexer",
|
||||||
@ -664,16 +664,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v5.4.28",
|
"version": "v5.4.30",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "442511fc62121085d184355e4f964c88942bbecb"
|
"reference": "b9a64955f4278f45ac348a6e000b5ecc85da167a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/442511fc62121085d184355e4f964c88942bbecb",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/b9a64955f4278f45ac348a6e000b5ecc85da167a",
|
||||||
"reference": "442511fc62121085d184355e4f964c88942bbecb",
|
"reference": "b9a64955f4278f45ac348a6e000b5ecc85da167a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -789,7 +789,7 @@
|
|||||||
"framework",
|
"framework",
|
||||||
"laravel"
|
"laravel"
|
||||||
],
|
],
|
||||||
"time": "2017-06-30T13:43:07+00:00"
|
"time": "2017-07-19T19:26:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravelcollective/html",
|
"name": "laravelcollective/html",
|
||||||
@ -916,16 +916,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/csv",
|
"name": "league/csv",
|
||||||
"version": "8.2.1",
|
"version": "8.2.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/csv.git",
|
"url": "https://github.com/thephpleague/csv.git",
|
||||||
"reference": "43fd8b022815a0758d85e925dd92a43fe0d41bb4"
|
"reference": "fa8bc05f64eb6c66b96edfaf60648f022ecb5f55"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/43fd8b022815a0758d85e925dd92a43fe0d41bb4",
|
"url": "https://api.github.com/repos/thephpleague/csv/zipball/fa8bc05f64eb6c66b96edfaf60648f022ecb5f55",
|
||||||
"reference": "43fd8b022815a0758d85e925dd92a43fe0d41bb4",
|
"reference": "fa8bc05f64eb6c66b96edfaf60648f022ecb5f55",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -969,7 +969,7 @@
|
|||||||
"read",
|
"read",
|
||||||
"write"
|
"write"
|
||||||
],
|
],
|
||||||
"time": "2017-02-23T08:25:03+00:00"
|
"time": "2017-07-12T07:18:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/flysystem",
|
"name": "league/flysystem",
|
||||||
@ -1636,7 +1636,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
@ -1758,7 +1758,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug",
|
"name": "symfony/debug",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/debug.git",
|
"url": "https://github.com/symfony/debug.git",
|
||||||
@ -1814,7 +1814,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v2.8.24",
|
"version": "v2.8.25",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||||
@ -1874,7 +1874,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
@ -1923,16 +1923,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-foundation",
|
"name": "symfony/http-foundation",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-foundation.git",
|
"url": "https://github.com/symfony/http-foundation.git",
|
||||||
"reference": "f347a5f561b03db95ed666959db42bbbf429b7e5"
|
"reference": "e307abe4b79ccbbfdced9b91c132fd128f456bc5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f347a5f561b03db95ed666959db42bbbf429b7e5",
|
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/e307abe4b79ccbbfdced9b91c132fd128f456bc5",
|
||||||
"reference": "f347a5f561b03db95ed666959db42bbbf429b7e5",
|
"reference": "e307abe4b79ccbbfdced9b91c132fd128f456bc5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1972,7 +1972,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpFoundation Component",
|
"description": "Symfony HttpFoundation Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2017-06-24T09:29:48+00:00"
|
"time": "2017-07-17T14:07:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-kernel",
|
"name": "symfony/http-kernel",
|
||||||
@ -2228,16 +2228,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/process.git",
|
"url": "https://github.com/symfony/process.git",
|
||||||
"reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30"
|
"reference": "07432804942b9f6dd7b7377faf9920af5f95d70a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/process/zipball/5ab8949b682b1bf9d4511a228b5e045c96758c30",
|
"url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a",
|
||||||
"reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30",
|
"reference": "07432804942b9f6dd7b7377faf9920af5f95d70a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2273,11 +2273,11 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Process Component",
|
"description": "Symfony Process Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2017-07-03T08:12:02+00:00"
|
"time": "2017-07-13T13:05:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/routing",
|
"name": "symfony/routing",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/routing.git",
|
"url": "https://github.com/symfony/routing.git",
|
||||||
@ -2355,7 +2355,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/translation",
|
"name": "symfony/translation",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/translation.git",
|
"url": "https://github.com/symfony/translation.git",
|
||||||
@ -2420,16 +2420,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
"reference": "9ee920bba1d2ce877496dcafca7cbffff4dbe08a"
|
"reference": "0f32b62d21991700250fed5109b092949007c5b3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/9ee920bba1d2ce877496dcafca7cbffff4dbe08a",
|
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/0f32b62d21991700250fed5109b092949007c5b3",
|
||||||
"reference": "9ee920bba1d2ce877496dcafca7cbffff4dbe08a",
|
"reference": "0f32b62d21991700250fed5109b092949007c5b3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2484,7 +2484,7 @@
|
|||||||
"debug",
|
"debug",
|
||||||
"dump"
|
"dump"
|
||||||
],
|
],
|
||||||
"time": "2017-07-05T13:02:37+00:00"
|
"time": "2017-07-10T14:18:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "tijsverkoyen/css-to-inline-styles",
|
"name": "tijsverkoyen/css-to-inline-styles",
|
||||||
@ -2698,16 +2698,16 @@
|
|||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "barryvdh/laravel-debugbar",
|
"name": "barryvdh/laravel-debugbar",
|
||||||
"version": "v2.4.1",
|
"version": "v2.4.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
||||||
"reference": "af98b3a4ccac9364f2145fae974ff3392ec402b1"
|
"reference": "d7c88f08131f6404cb714f3f6cf0642f6afa3903"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/af98b3a4ccac9364f2145fae974ff3392ec402b1",
|
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/d7c88f08131f6404cb714f3f6cf0642f6afa3903",
|
||||||
"reference": "af98b3a4ccac9364f2145fae974ff3392ec402b1",
|
"reference": "d7c88f08131f6404cb714f3f6cf0642f6afa3903",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2717,19 +2717,6 @@
|
|||||||
"symfony/finder": "~2.7|~3.0"
|
"symfony/finder": "~2.7|~3.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "2.4-dev"
|
|
||||||
},
|
|
||||||
"laravel": {
|
|
||||||
"providers": [
|
|
||||||
"Barryvdh\\Debugbar\\ServiceProvider"
|
|
||||||
],
|
|
||||||
"aliases": {
|
|
||||||
"Debugbar": "Barryvdh\\Debugbar\\Facade"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Barryvdh\\Debugbar\\": "src/"
|
"Barryvdh\\Debugbar\\": "src/"
|
||||||
@ -2756,20 +2743,20 @@
|
|||||||
"profiler",
|
"profiler",
|
||||||
"webprofiler"
|
"webprofiler"
|
||||||
],
|
],
|
||||||
"time": "2017-06-14T07:44:44+00:00"
|
"time": "2017-07-21T11:56:48+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "barryvdh/laravel-ide-helper",
|
"name": "barryvdh/laravel-ide-helper",
|
||||||
"version": "v2.4.0",
|
"version": "v2.4.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/barryvdh/laravel-ide-helper.git",
|
"url": "https://github.com/barryvdh/laravel-ide-helper.git",
|
||||||
"reference": "87a02ff574f722c685e011f76692ab869ab64f6c"
|
"reference": "2b1273c45e2f8df7a625563e2283a17c14f02ae8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/87a02ff574f722c685e011f76692ab869ab64f6c",
|
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/2b1273c45e2f8df7a625563e2283a17c14f02ae8",
|
||||||
"reference": "87a02ff574f722c685e011f76692ab869ab64f6c",
|
"reference": "2b1273c45e2f8df7a625563e2283a17c14f02ae8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2829,7 +2816,7 @@
|
|||||||
"phpstorm",
|
"phpstorm",
|
||||||
"sublime"
|
"sublime"
|
||||||
],
|
],
|
||||||
"time": "2017-06-16T14:08:59+00:00"
|
"time": "2017-07-16T00:24:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "barryvdh/reflection-docblock",
|
"name": "barryvdh/reflection-docblock",
|
||||||
@ -3223,7 +3210,7 @@
|
|||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Pádraic Brady",
|
"name": "Padraic Brady",
|
||||||
"email": "padraic.brady@gmail.com",
|
"email": "padraic.brady@gmail.com",
|
||||||
"homepage": "http://blog.astrumfutura.com"
|
"homepage": "http://blog.astrumfutura.com"
|
||||||
},
|
},
|
||||||
@ -3347,22 +3334,22 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-docblock",
|
"name": "phpdocumentor/reflection-docblock",
|
||||||
"version": "3.1.1",
|
"version": "3.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||||
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
|
"reference": "46f7e8bb075036c92695b15a1ddb6971c751e585"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
|
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/46f7e8bb075036c92695b15a1ddb6971c751e585",
|
||||||
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
|
"reference": "46f7e8bb075036c92695b15a1ddb6971c751e585",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.5",
|
"php": ">=5.5",
|
||||||
"phpdocumentor/reflection-common": "^1.0@dev",
|
"phpdocumentor/reflection-common": "^1.0@dev",
|
||||||
"phpdocumentor/type-resolver": "^0.2.0",
|
"phpdocumentor/type-resolver": "^0.4.0",
|
||||||
"webmozart/assert": "^1.0"
|
"webmozart/assert": "^1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
@ -3388,24 +3375,24 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||||
"time": "2016-09-30T07:12:33+00:00"
|
"time": "2017-07-15T11:38:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/type-resolver",
|
"name": "phpdocumentor/type-resolver",
|
||||||
"version": "0.2.1",
|
"version": "0.4.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||||
"reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb"
|
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
|
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
|
||||||
"reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
|
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.5",
|
"php": "^5.5 || ^7.0",
|
||||||
"phpdocumentor/reflection-common": "^1.0"
|
"phpdocumentor/reflection-common": "^1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
@ -3435,7 +3422,7 @@
|
|||||||
"email": "me@mikevanriel.com"
|
"email": "me@mikevanriel.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2016-11-25T06:54:22+00:00"
|
"time": "2017-07-14T14:27:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpspec/prophecy",
|
"name": "phpspec/prophecy",
|
||||||
@ -4463,7 +4450,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/class-loader",
|
"name": "symfony/class-loader",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/class-loader.git",
|
"url": "https://github.com/symfony/class-loader.git",
|
||||||
@ -4519,7 +4506,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/config",
|
"name": "symfony/config",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/config.git",
|
"url": "https://github.com/symfony/config.git",
|
||||||
@ -4637,16 +4624,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/filesystem.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
"reference": "311fa718389efbd8b627c272b9324a62437018cc"
|
"reference": "427987eb4eed764c3b6e38d52a0f87989e010676"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/311fa718389efbd8b627c272b9324a62437018cc",
|
"url": "https://api.github.com/repos/symfony/filesystem/zipball/427987eb4eed764c3b6e38d52a0f87989e010676",
|
||||||
"reference": "311fa718389efbd8b627c272b9324a62437018cc",
|
"reference": "427987eb4eed764c3b6e38d52a0f87989e010676",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -4682,11 +4669,11 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Filesystem Component",
|
"description": "Symfony Filesystem Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2017-06-24T09:29:48+00:00"
|
"time": "2017-07-11T07:17:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/stopwatch",
|
"name": "symfony/stopwatch",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/stopwatch.git",
|
"url": "https://github.com/symfony/stopwatch.git",
|
||||||
@ -4735,7 +4722,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
|
@ -23,7 +23,7 @@ return [
|
|||||||
'is_demo_site' => false,
|
'is_demo_site' => false,
|
||||||
],
|
],
|
||||||
'encryption' => (is_null(env('USE_ENCRYPTION')) || env('USE_ENCRYPTION') === true),
|
'encryption' => (is_null(env('USE_ENCRYPTION')) || env('USE_ENCRYPTION') === true),
|
||||||
'version' => '4.6.2',
|
'version' => '4.6.3',
|
||||||
'maxUploadSize' => 15242880,
|
'maxUploadSize' => 15242880,
|
||||||
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
|
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
|
||||||
'list_length' => 10,
|
'list_length' => 10,
|
||||||
@ -109,7 +109,8 @@ return [
|
|||||||
'nl_NL' => ['name_locale' => 'Nederlands', 'name_english' => 'Dutch', 'complete' => true],
|
'nl_NL' => ['name_locale' => 'Nederlands', 'name_english' => 'Dutch', 'complete' => true],
|
||||||
'pl_PL' => ['name_locale' => 'Polski', 'name_english' => 'Polish ', 'complete' => false],
|
'pl_PL' => ['name_locale' => 'Polski', 'name_english' => 'Polish ', 'complete' => false],
|
||||||
'pt_BR' => ['name_locale' => 'Português do Brasil', 'name_english' => 'Portuguese (Brazil)', 'complete' => true],
|
'pt_BR' => ['name_locale' => 'Português do Brasil', 'name_english' => 'Portuguese (Brazil)', 'complete' => true],
|
||||||
'sl-SI' => ['name_locale' => 'Slovenščina', 'name_english' => 'Slovenian', 'complete' => false],
|
'ru_RU' => ['name_locale' => 'Русский', 'name_english' => 'Russian', 'complete' => false],
|
||||||
|
'sl_SI' => ['name_locale' => 'Slovenščina', 'name_english' => 'Slovenian', 'complete' => false],
|
||||||
'zh-TW' => ['name_locale' => '正體中文', 'name_english' => 'Chinese Traditional', 'complete' => false],
|
'zh-TW' => ['name_locale' => '正體中文', 'name_english' => 'Chinese Traditional', 'complete' => false],
|
||||||
],
|
],
|
||||||
'transactionTypesByWhat' => [
|
'transactionTypesByWhat' => [
|
||||||
|
159
config/intro.php
Normal file
159
config/intro.php
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* intro.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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always make sure intro is the first element (if any) and outro is the last one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
// index
|
||||||
|
'index' => [
|
||||||
|
'intro' => [],
|
||||||
|
'accounts-chart' => ['element' => '#accounts-chart'],
|
||||||
|
'box_out_holder' => ['element' => '#box_out_holder'],
|
||||||
|
'help' => ['element' => '#help', 'position' => 'bottom'],
|
||||||
|
'sidebar-toggle' => ['element' => '#sidebar-toggle', 'position' => 'bottom'],
|
||||||
|
'outro' => [],
|
||||||
|
],
|
||||||
|
// accounts: create
|
||||||
|
'accounts_create' => [
|
||||||
|
'iban' => ['element' => '#ffInput_iban'],
|
||||||
|
],
|
||||||
|
// extra text for asset account creation.
|
||||||
|
'accounts_create_asset' => [
|
||||||
|
'opening_balance' => ['element' => '#ffInput_openingBalance'],
|
||||||
|
'currency' => ['element' => '#ffInput_currency_id'],
|
||||||
|
'virtual' => ['element' => '#ffInput_virtualBalance'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// budgets: index
|
||||||
|
'budgets_index' => [
|
||||||
|
'intro' => [],
|
||||||
|
'set_budget' => ['element' => '#availableBar',],
|
||||||
|
'see_expenses_bar' => ['element' => '#spentBar'],
|
||||||
|
'navigate_periods' => ['element' => '#periodNavigator'],
|
||||||
|
'new_budget' => ['element' => '#createBudgetBox'],
|
||||||
|
'list_of_budgets' => ['element' => '#budgetList'],
|
||||||
|
|
||||||
|
],
|
||||||
|
// reports: index, default report, audit, budget, cat, tag
|
||||||
|
'reports_index' => [
|
||||||
|
'intro' => [],
|
||||||
|
'inputReportType' => ['element' => '#inputReportType'],
|
||||||
|
'inputAccountsSelect' => ['element' => '#inputAccountsSelect'],
|
||||||
|
'inputDateRange' => ['element' => '#inputDateRange'],
|
||||||
|
'extra-options-box' => ['element' => '#extra-options-box', 'position' => 'top'],
|
||||||
|
],
|
||||||
|
'reports_report_default' => [
|
||||||
|
'intro' => [],
|
||||||
|
],
|
||||||
|
'reports_report_audit' => [
|
||||||
|
'intro' => [],
|
||||||
|
'optionsBox' => ['element' => '#optionsBox'],
|
||||||
|
],
|
||||||
|
'reports_report_category' => [
|
||||||
|
'intro' => [],
|
||||||
|
'pieCharts' => ['element' => '#pieCharts'],
|
||||||
|
'incomeAndExpensesChart' => ['element' => '#incomeAndExpensesChart', 'position' => 'top'],
|
||||||
|
|
||||||
|
],
|
||||||
|
'reports_report_tag' => [
|
||||||
|
'intro' => [],
|
||||||
|
'pieCharts' => ['element' => '#pieCharts'],
|
||||||
|
'incomeAndExpensesChart' => ['element' => '#incomeAndExpensesChart', 'position' => 'top'],
|
||||||
|
],
|
||||||
|
'reports_report_budget' => [
|
||||||
|
'intro' => [],
|
||||||
|
'pieCharts' => ['element' => '#pieCharts'],
|
||||||
|
'incomeAndExpensesChart' => ['element' => '#incomeAndExpensesChart', 'position' => 'top'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// transactions: create (also per type!)
|
||||||
|
'transactions_create' => [
|
||||||
|
'switch_box' => ['element' => '#switch-box'],
|
||||||
|
'ffInput_category' => ['element' => '#ffInput_category'],
|
||||||
|
],
|
||||||
|
'transactions_create_withdrawal' => [
|
||||||
|
'ffInput_budget' => ['element' => '#ffInput_budget_id'],
|
||||||
|
'currency_dropdown_amount' => ['element' => '#currency_dropdown_amount'],
|
||||||
|
],
|
||||||
|
'transactions_create_deposit' => [
|
||||||
|
'currency_dropdown_amount' => ['element' => '#currency_dropdown_amount'],
|
||||||
|
],
|
||||||
|
'transactions_create_transfer' => [
|
||||||
|
'ffInput_piggy_bank_id' => ['element' => '#ffInput_piggy_bank_id'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// piggies: index, create, show
|
||||||
|
'piggy-banks_index' => [
|
||||||
|
'saved' => ['element' => '.piggySaved'],
|
||||||
|
'button' => ['element' => '.piggyBar',],
|
||||||
|
'accountStatus' => ['element' => '#accountStatus', 'position' => 'top'],
|
||||||
|
],
|
||||||
|
'piggy-banks_create' => [
|
||||||
|
'name' => ['element' => '#ffInput_name'],
|
||||||
|
'date' => ['element' => '#ffInput_targetdate'],
|
||||||
|
|
||||||
|
],
|
||||||
|
'piggy-banks_show' => [
|
||||||
|
'intro' => [],
|
||||||
|
'piggyChart' => ['element' => '#piggyChart'],
|
||||||
|
'piggyDetails' => ['element' => '#piggyDetails'],
|
||||||
|
'piggyEvents' => ['element' => '#piggyEvents'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// bills: index, create, show
|
||||||
|
'bills_index' => [
|
||||||
|
'paid_in_period' => ['element' => '.paid_in_period'],
|
||||||
|
'expected_in_period' => ['element' => '.expected_in_period'],
|
||||||
|
],
|
||||||
|
'bills_create' => [
|
||||||
|
'name' => ['element' => '#name_holder'],
|
||||||
|
'match' => ['element' => '#match_holder'],
|
||||||
|
'amount_min_holder' => ['element' => '#amount_min_holder'],
|
||||||
|
'repeat_freq_holder' => ['element' => '#repeat_freq_holder'],
|
||||||
|
'skip_holder' => ['element' => '#skip_holder'],
|
||||||
|
],
|
||||||
|
'bills_show' => [
|
||||||
|
'billInfo' => ['element' => '#billInfo'],
|
||||||
|
'billButtons' => ['element' => '#billButtons'],
|
||||||
|
'billChart' => ['element' => '#billChart', 'position' => 'top'],
|
||||||
|
|
||||||
|
],
|
||||||
|
// rules: index, create-rule, edit-rule
|
||||||
|
'rules_index' => [
|
||||||
|
'intro' => [],
|
||||||
|
'new_rule_group' => ['element' => '#new_rule_group'],
|
||||||
|
'new_rule' => ['element' => '.new_rule'],
|
||||||
|
'prio_buttons' => ['element' => '.prio_buttons'],
|
||||||
|
'test_buttons' => ['element' => '.test_buttons'],
|
||||||
|
'rule-triggers' => ['element' => '.rule-triggers'],
|
||||||
|
'outro' => [],
|
||||||
|
],
|
||||||
|
'rules_create' => [
|
||||||
|
'mandatory' => ['element' => '#mandatory'],
|
||||||
|
'ruletriggerholder' => ['element' => '.rule-trigger-box'],
|
||||||
|
'test_rule_triggers' => ['element' => '.test_rule_triggers'],
|
||||||
|
'actions' => ['element' => '.rule-action-box', 'position' => 'top'],
|
||||||
|
],
|
||||||
|
// preferences: index
|
||||||
|
'preferences_index' => [
|
||||||
|
'tabs' => ['element' => '.nav-tabs'],
|
||||||
|
],
|
||||||
|
// currencies: index, create
|
||||||
|
'currencies_index' => [
|
||||||
|
'intro' => [],
|
||||||
|
'default' => ['element' => '.defaultCurrency'],
|
||||||
|
],
|
||||||
|
'currencies_create' => [
|
||||||
|
'code' => ['element' => '#ffInput_code',],
|
||||||
|
],
|
||||||
|
];
|
@ -156,6 +156,7 @@ return [
|
|||||||
'Preferences',
|
'Preferences',
|
||||||
'URL',
|
'URL',
|
||||||
'Config',
|
'Config',
|
||||||
|
'Request',
|
||||||
'ExpandedForm' => [
|
'ExpandedForm' => [
|
||||||
'is_safe' => [
|
'is_safe' => [
|
||||||
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
|
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
|
||||||
|
@ -16,10 +16,12 @@ return [
|
|||||||
'upgrade' =>
|
'upgrade' =>
|
||||||
[
|
[
|
||||||
'4.3' => 'Make sure you run the migrations and clear your cache. If you need more help, please check Github or the Firefly III website.',
|
'4.3' => 'Make sure you run the migrations and clear your cache. If you need more help, please check Github or the Firefly III website.',
|
||||||
|
'4.6.3' => 'This will be the last version to require PHP7.0. Future versions will require PHP7.1 minimum.',
|
||||||
],
|
],
|
||||||
'install' =>
|
'install' =>
|
||||||
[
|
[
|
||||||
'4.3' => 'Welcome to Firefly! Make sure you follow the installation guide. If you need more help, please check Github or the Firefly III website. The installation guide has a FAQ which you should check out as well.',
|
'4.3' => 'Welcome to Firefly! Make sure you follow the installation guide. If you need more help, please check Github or the Firefly III website. The installation guide has a FAQ which you should check out as well.',
|
||||||
|
'4.6.3' => 'This will be the last version to require PHP7.0. Future versions will require PHP7.1 minimum.',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
22
public/css/bootstrap-tour.min.css
vendored
22
public/css/bootstrap-tour.min.css
vendored
@ -1,22 +0,0 @@
|
|||||||
/* ========================================================================
|
|
||||||
* bootstrap-tour - v0.10.3
|
|
||||||
* http://bootstraptour.com
|
|
||||||
* ========================================================================
|
|
||||||
* Copyright 2012-2015 Ulrich Sossou
|
|
||||||
*
|
|
||||||
* ========================================================================
|
|
||||||
* Licensed under the MIT License (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ========================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
.tour-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1100;background-color:#000;opacity:.8;filter:alpha(opacity=80)}.tour-step-backdrop{position:relative;z-index:1101}.tour-step-backdrop>td{position:relative;z-index:1101}.tour-step-background{position:absolute!important;z-index:1100;background:inherit;border-radius:6px}.popover[class*=tour-]{z-index:1102}.popover[class*=tour-] .popover-navigation{padding:9px 14px;overflow:hidden}.popover[class*=tour-] .popover-navigation [data-role=end]{float:right}.popover[class*=tour-] .popover-navigation [data-role=prev],.popover[class*=tour-] .popover-navigation [data-role=next],.popover[class*=tour-] .popover-navigation [data-role=end]{cursor:pointer}.popover[class*=tour-] .popover-navigation [data-role=prev].disabled,.popover[class*=tour-] .popover-navigation [data-role=next].disabled,.popover[class*=tour-] .popover-navigation [data-role=end].disabled{cursor:default}.popover[class*=tour-].orphan{position:fixed;margin-top:0}.popover[class*=tour-].orphan .arrow{display:none}
|
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* See the LICENSE file for details.
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
/** global: Chart, defaultChartOptions, accounting, defaultPieOptions, noDataForChart */
|
/** global: Chart, defaultChartOptions, accounting, defaultPieOptions, noDataForChart, noDataForChart */
|
||||||
var allCharts = {};
|
var allCharts = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -38,7 +38,7 @@ var strokePointHighColors = [];
|
|||||||
|
|
||||||
|
|
||||||
for (var i = 0; i < colourSet.length; i++) {
|
for (var i = 0; i < colourSet.length; i++) {
|
||||||
fillColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.2)");
|
fillColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.5)");
|
||||||
strokePointHighColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.9)");
|
strokePointHighColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.9)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,8 @@ function colorizeData(data) {
|
|||||||
for (var i = 0; i < data.count; i++) {
|
for (var i = 0; i < data.count; i++) {
|
||||||
newData.labels = data.labels;
|
newData.labels = data.labels;
|
||||||
var dataset = data.datasets[i];
|
var dataset = data.datasets[i];
|
||||||
dataset.backgroundColor = fillColors[i];
|
dataset.fill = false;
|
||||||
|
dataset.backgroundColor = dataset.borderColor = fillColors[i];
|
||||||
newData.datasets.push(dataset);
|
newData.datasets.push(dataset);
|
||||||
}
|
}
|
||||||
return newData;
|
return newData;
|
||||||
@ -239,13 +240,14 @@ function pieChart(URI, container) {
|
|||||||
* @param colorData
|
* @param colorData
|
||||||
*/
|
*/
|
||||||
function drawAChart(URI, container, chartType, options, colorData) {
|
function drawAChart(URI, container, chartType, options, colorData) {
|
||||||
if ($('#' + container).length === 0) {
|
var containerObj = $('#' + container);
|
||||||
|
if (containerObj.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$.getJSON(URI).done(function (data) {
|
$.getJSON(URI).done(function (data) {
|
||||||
$('#' + container).removeClass('general-chart-error');
|
containerObj.removeClass('general-chart-error');
|
||||||
if (data.labels.length === 0) {
|
if (data.labels.length === 0) {
|
||||||
// remove the chart container + parent
|
// remove the chart container + parent
|
||||||
var holder = $('#' + container).parent().parent();
|
var holder = $('#' + container).parent().parent();
|
||||||
|
@ -15,6 +15,11 @@ $(function () {
|
|||||||
|
|
||||||
configAccounting(currencySymbol);
|
configAccounting(currencySymbol);
|
||||||
|
|
||||||
|
// on submit of form, disable any button in form:
|
||||||
|
$('form.form-horizontal').on('submit',function() {
|
||||||
|
$('button[type="submit"]').prop('disabled',true);
|
||||||
|
});
|
||||||
|
|
||||||
$.ajaxSetup({
|
$.ajaxSetup({
|
||||||
headers: {
|
headers: {
|
||||||
'X-CSRF-Token': $('meta[name="_token"]').attr('content')
|
'X-CSRF-Token': $('meta[name="_token"]').attr('content')
|
||||||
|
@ -11,27 +11,39 @@
|
|||||||
$(function () {
|
$(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
$('#help').click(showHelp);
|
$('#help').click(showHelp);
|
||||||
$(function () {
|
|
||||||
|
|
||||||
//$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function showHelp(e) {
|
function showHelp(e) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var target = $(e.target);
|
var target = $(e.target);
|
||||||
var route = target.data('route');
|
var route = target.data('route');
|
||||||
//
|
var specialPage = target.data('extra');
|
||||||
$('#helpBody').html('<i class="fa fa-refresh fa-spin"></i>');
|
|
||||||
$('#helpTitle').html('Please hold...');
|
|
||||||
|
|
||||||
|
if (typeof specialPage === 'undefined') {
|
||||||
|
specialPage = '';
|
||||||
|
}
|
||||||
|
$('#helpBody').html('<i class="fa fa-refresh fa-spin"></i>');
|
||||||
$('#helpModal').modal('show');
|
$('#helpModal').modal('show');
|
||||||
$('#helpTitle').html('Help for this page');
|
$('#helpTitle').html('Help for this page');
|
||||||
$.getJSON('help/' + encodeURI(route)).done(function (data) {
|
$.getJSON('help/' + encodeURI(route)).done(function (data) {
|
||||||
$('#helpBody').html(data);
|
$('#helpBody').html(data.html);
|
||||||
}).fail(function () {
|
}).fail(function () {
|
||||||
$('#helpBody').html('<p class="text-danger">No help text could be found.</p>');
|
$('#helpBody').html('<p class="text-danger">No help text could be found.</p>');
|
||||||
$('#helpTitle').html('Apologies');
|
$('#helpTitle').html('Apologies');
|
||||||
});
|
});
|
||||||
|
$('#reenableGuidance').unbind('click').click(function () {
|
||||||
|
enableGuidance(route, specialPage);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableGuidance(route, specialPage) {
|
||||||
|
$.post('json/intro/enable/' + route + '/' + specialPage).done(function (data) {
|
||||||
|
alert(data.message);
|
||||||
|
}).fail(function () {
|
||||||
|
alert('Could not re-enable introduction.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user