mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.7.4'
This commit is contained in:
commit
78a5dae2a0
@ -95,4 +95,5 @@ DEMO_PASSWORD=
|
||||
IS_DOCKER=true
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
TZ=${TZ}
|
||||
|
@ -98,4 +98,5 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
IS_HEROKU=false
|
||||
|
@ -98,4 +98,5 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
IS_HEROKU=true
|
||||
|
@ -98,4 +98,5 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=true
|
||||
BUNQ_USE_SANDBOX=false
|
||||
IS_HEROKU=false
|
||||
|
@ -94,4 +94,5 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
BUNQ_USE_SANDBOX=true
|
||||
IS_HEROKU=false
|
||||
|
22
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help Firefly III improve
|
||||
|
||||
---
|
||||
|
||||
**Bug description**
|
||||
I am running Firefly III version x.x.x
|
||||
|
||||
(please give a clear and concise description of what the bug is)
|
||||
|
||||
**Steps to reproduce**
|
||||
What do you need to do to trigger this bug?
|
||||
|
||||
**Extra info**
|
||||
Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom).
|
||||
|
||||
**Bonus points**
|
||||
Earn bonus points by:
|
||||
|
||||
- Post a stacktrace from your log files
|
||||
- Add a screenshot
|
25
.github/ISSUE_TEMPLATE/Custom.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE/Custom.md
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
name: I have a question or a problem
|
||||
about: Ask away
|
||||
|
||||
---
|
||||
|
||||
I am running Firefly III version x.x.x
|
||||
|
||||
**Description of my issue:**
|
||||
|
||||
|
||||
**Steps to reproduce**
|
||||
|
||||
(please include if this problem also exists on the demo site: https://demo.firefly-iii.org/ )
|
||||
|
||||
**Extra info**
|
||||
|
||||
Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom).
|
||||
|
||||
**Bonus points**
|
||||
Earn bonus points by:
|
||||
|
||||
- Post a stacktrace from your log files
|
||||
- Add a screenshot
|
||||
- Post nginx or Apache configuration
|
20
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea or feature for Firefly III
|
||||
|
||||
---
|
||||
|
||||
**Description**
|
||||
Please describe your feature request:
|
||||
|
||||
- I would like Firefly III to do X.
|
||||
- What if you would add Y?
|
||||
|
||||
**Solution**
|
||||
Describe what your feature would add to Firefly III.
|
||||
|
||||
**What are alternatives?**
|
||||
Please describe what alternatives currently exist.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
11
.github/issue_template.md
vendored
11
.github/issue_template.md
vendored
@ -1,11 +0,0 @@
|
||||
I am running Firefly III version x.x.x
|
||||
|
||||
#### Description of my issue:
|
||||
|
||||
#### Steps to reproduce
|
||||
|
||||
(please include if this problem also exists on the demo site)
|
||||
|
||||
#### Other important details (log files, system info):
|
||||
|
||||
Please click the version number in the right corner of any Firefly III page to get debug information.
|
@ -1,7 +1,31 @@
|
||||
# 4.7.4
|
||||
- [Issue 1409](https://github.com/firefly-iii/firefly-iii/issues/1409), add Indian Rupee and explain that users can do this themselves [issue 1413](https://github.com/firefly-iii/firefly-iii/issues/1413)
|
||||
- [Issue 1445](https://github.com/firefly-iii/firefly-iii/issues/1445), upgrade Curl in Docker image.
|
||||
- [Issue 1386](https://github.com/firefly-iii/firefly-iii/issues/1386), quick links to often used pages.
|
||||
- [Issue 1405](https://github.com/firefly-iii/firefly-iii/issues/1405), show proposed amount to piggy banks.
|
||||
- [Issue 1416](https://github.com/firefly-iii/firefly-iii/issues/1416), ability to delete lost attachments.
|
||||
- A completely rewritten import routine that can handle bunq (thanks everybody for testing!), CSV files and Spectre. Please make sure you read about this at http://bit.ly/FF3-new-import
|
||||
- [Issue 1392](https://github.com/firefly-iii/firefly-iii/issues/1392), explicitly mention rules are inactive (when they are).
|
||||
- [Issue 1406](https://github.com/firefly-iii/firefly-iii/issues/1406), bill conversion to rules will be smarter about the rules they create.
|
||||
- [Issue 1369](https://github.com/firefly-iii/firefly-iii/issues/1369), you can now properly order piggy banks again.
|
||||
- [Issue 1389](https://github.com/firefly-iii/firefly-iii/issues/1389), null-pointer in the import routine.
|
||||
- [Issue 1400](https://github.com/firefly-iii/firefly-iii/issues/1400), missing translation.
|
||||
- [Issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403), bill would always be marked as inactive in edit screen.
|
||||
- [Issue 1418](https://github.com/firefly-iii/firefly-iii/issues/1418), missing note text on bill page.
|
||||
- Export routine would break when encountering un-decryptable files.
|
||||
- [Issue 1425](https://github.com/firefly-iii/firefly-iii/issues/1425), empty fields when edit multiple transactions at once.
|
||||
- [Issue 1449](https://github.com/firefly-iii/firefly-iii/issues/1449), bad calculations in "budget left to spend" view.
|
||||
- [Issue 1451](https://github.com/firefly-iii/firefly-iii/issues/1451), same but in another view.
|
||||
- [Issue 1453](https://github.com/firefly-iii/firefly-iii/issues/1453), same as [issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403).
|
||||
- [Issue 1455](https://github.com/firefly-iii/firefly-iii/issues/1455), could add income to a budget.
|
||||
- [Issue 1442](https://github.com/firefly-iii/firefly-iii/issues/1442), issues with editing a split deposit.
|
||||
- [Issue 1452](https://github.com/firefly-iii/firefly-iii/issues/1452), date range problems with tags.
|
||||
- [Issue 1458](https://github.com/firefly-iii/firefly-iii/issues/1458), same for transactions.
|
||||
- [Issue 1415](https://github.com/firefly-iii/firefly-iii/issues/1415), will email you when OAuth2 keys are generated.
|
||||
|
||||
# 4.7.3.2
|
||||
- Forgot to increase the version number :(.
|
||||
|
||||
|
||||
# 4.7.3.1
|
||||
- Fixed a critical bug where the rules-engine would fire inadvertently.
|
||||
|
||||
|
@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 12,
|
||||
appMarketingVersion = (defaultText = "4.7.3.2"),
|
||||
appVersion = 13,
|
||||
appMarketingVersion = (defaultText = "4.7.4"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
|
31
Dockerfile
31
Dockerfile
@ -3,6 +3,8 @@ FROM php:7.1-apache
|
||||
|
||||
# set working dir
|
||||
ENV FIREFLY_PATH /var/www/firefly-iii
|
||||
ENV CURL_VERSION 7.60.0
|
||||
ENV OPENSSL_VERSION 1.1.1-pre6
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
@ -11,7 +13,8 @@ RUN apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
|
||||
zlib1g-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng12-dev \
|
||||
wget \
|
||||
libpng-dev \
|
||||
libicu-dev \
|
||||
libedit-dev \
|
||||
libtidy-dev \
|
||||
@ -24,6 +27,26 @@ RUN apt-get update -y && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Setup the Composer installer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Install latest curl
|
||||
RUN cd /tmp && \
|
||||
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||
tar -xvf openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||
cd openssl-${OPENSSL_VERSION} && \
|
||||
./config && \
|
||||
make && \
|
||||
make install
|
||||
|
||||
RUN cd /tmp && \
|
||||
wget https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.gz && \
|
||||
tar -xvf curl-${CURL_VERSION}.tar.gz && \
|
||||
cd curl-${CURL_VERSION} && \
|
||||
./configure --with-ssl && \
|
||||
make && \
|
||||
make install
|
||||
|
||||
# Install PHP exentions.
|
||||
RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql
|
||||
|
||||
@ -42,9 +65,6 @@ RUN a2enmod ssl
|
||||
# Create volumes for several directories:
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Setup the Composer installer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Enable default site (Firefly III)
|
||||
COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
@ -58,4 +78,5 @@ RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
EXPOSE 80
|
||||
|
||||
# Run entrypoint thing
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AboutController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AccountController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BillController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BillRequest;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Controller.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UserController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AccountRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BillRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
@ -80,4 +80,4 @@ class CurrencyRequest extends Request
|
||||
return $rules;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Request.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UserRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CreateExport.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CreateImport.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,15 +20,18 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Import\Storage\ImportArrayStorage;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\File\EncryptService;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
use Preferences;
|
||||
|
||||
@ -52,18 +55,17 @@ class CreateImport extends Command
|
||||
*/
|
||||
protected $signature
|
||||
= 'firefly:create-import
|
||||
{file : The file to import.}
|
||||
{configuration : The configuration file to use for the import.}
|
||||
{file? : The file to import.}
|
||||
{configuration? : The configuration file to use for the import.}
|
||||
{--type=csv : The file type of the import.}
|
||||
{--user= : The user ID that the import should import for.}
|
||||
{--provider=file : The file type of the import.}
|
||||
{--user=1 : The user ID that the import should import for.}
|
||||
{--token= : The user\'s access token.}
|
||||
{--start : Starts the job immediately.}';
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @noinspection MultipleReturnStatementsInspection
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function handle(): int
|
||||
@ -74,77 +76,155 @@ class CreateImport extends Command
|
||||
return 1;
|
||||
}
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = $this->argument('file');
|
||||
$configuration = $this->argument('configuration');
|
||||
$user = $userRepository->findNull((int)$this->option('user'));
|
||||
$cwd = getcwd();
|
||||
$type = strtolower($this->option('type'));
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
$file = (string)$this->argument('file');
|
||||
$configuration = (string)$this->argument('configuration');
|
||||
$user = $userRepository->findNull((int)$this->option('user'));
|
||||
$cwd = getcwd();
|
||||
$type = strtolower((string)$this->option('type'));
|
||||
$provider = strtolower((string)$this->option('provider'));
|
||||
$configurationData = [];
|
||||
|
||||
if (!$this->validArguments()) {
|
||||
$this->errorLine('Invalid arguments.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (\strlen($configuration) > 0) {
|
||||
$configurationData = json_decode(file_get_contents($configuration), true);
|
||||
if (null === $configurationData) {
|
||||
$this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
$configurationData = json_decode(file_get_contents($configuration), true);
|
||||
if (null === $configurationData) {
|
||||
$this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->infoLine(sprintf('Going to create a job to import file: %s', $file));
|
||||
$this->infoLine(sprintf('Using configuration file: %s', $configuration));
|
||||
$this->infoLine(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
||||
$this->infoLine(sprintf('Type of import: %s', $type));
|
||||
$this->infoLine(sprintf('Type of import: %s', $provider));
|
||||
|
||||
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||
$jobRepository = app(ImportJobRepositoryInterface::class);
|
||||
$jobRepository->setUser($user);
|
||||
$job = $jobRepository->create($type);
|
||||
$this->infoLine(sprintf('Created job "%s"', $job->key));
|
||||
$importJob = $jobRepository->create($provider);
|
||||
$this->infoLine(sprintf('Created job "%s"', $importJob->key));
|
||||
|
||||
/** @var EncryptService $service */
|
||||
$service = app(EncryptService::class);
|
||||
$service->encrypt($file, $job->key);
|
||||
|
||||
$this->infoLine('Stored import data...');
|
||||
|
||||
$jobRepository->setConfiguration($job, $configurationData);
|
||||
$jobRepository->updateStatus($job, 'configured');
|
||||
$this->infoLine('Stored configuration...');
|
||||
|
||||
if (true === $this->option('start')) {
|
||||
$this->infoLine('The import will start in a moment. This process is not visible...');
|
||||
Log::debug('Go for import!');
|
||||
|
||||
// normally would refer to other firefly:start-import but that doesn't seem to work all to well...
|
||||
|
||||
// start the actual routine:
|
||||
$type = 'csv' === $job->file_type ? 'file' : $job->file_type;
|
||||
$key = sprintf('import.routine.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
// make sure that job has no prerequisites.
|
||||
if ((bool)config(sprintf('import.has_prereq.%s', $provider))) {
|
||||
// make prerequisites thing.
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $provider));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('No class to handle prerequisites for "%s".', $provider)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setJob($job);
|
||||
$routine->run();
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser($user);
|
||||
if (!$object->isComplete()) {
|
||||
$this->errorLine(sprintf('Import provider "%s" has prerequisites that can only be filled in using the browser.', $provider));
|
||||
|
||||
// give feedback.
|
||||
/** @var MessageBag $error */
|
||||
foreach ($routine->getErrors() as $index => $error) {
|
||||
$this->errorLine(sprintf('Error importing line #%d: %s', $index, $error));
|
||||
return 1;
|
||||
}
|
||||
$this->infoLine(
|
||||
sprintf(
|
||||
'The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// store file as attachment.
|
||||
if (\strlen($file) > 0) {
|
||||
$messages = $jobRepository->storeCLIUpload($importJob, 'import_file', $file);
|
||||
if ($messages->count() > 0) {
|
||||
$this->errorLine($messages->first());
|
||||
|
||||
return 1;
|
||||
}
|
||||
$this->infoLine('File content saved.');
|
||||
}
|
||||
|
||||
$this->infoLine('Job configuration saved.');
|
||||
$jobRepository->setConfiguration($importJob, $configurationData);
|
||||
$jobRepository->setStatus($importJob, 'ready_to_run');
|
||||
|
||||
|
||||
if (true === $this->option('start')) {
|
||||
$this->infoLine('The has started. The process is not visible. Please wait.');
|
||||
Log::debug('Go for import!');
|
||||
|
||||
// run it!
|
||||
$key = sprintf('import.routine.%s', $provider);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$this->errorLine(sprintf('No routine for provider "%s"', $provider));
|
||||
|
||||
return 1;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// keep repeating this call until job lands on "provider_finished"
|
||||
$valid = ['provider_finished'];
|
||||
$count = 0;
|
||||
while (!\in_array($importJob->status, $valid, true) && $count < 6) {
|
||||
Log::debug(sprintf('Now in loop #%d.', $count + 1));
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setImportJob($importJob);
|
||||
try {
|
||||
$routine->run();
|
||||
} catch (FireflyException|Exception $e) {
|
||||
$message = 'The import routine crashed: ' . $e->getMessage();
|
||||
Log::error($message);
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
// set job errored out:
|
||||
$jobRepository->setStatus($importJob, 'error');
|
||||
$this->errorLine($message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
if ($importJob->status === 'provider_finished') {
|
||||
$this->infoLine('Import has finished. Please wait for storage of data.');
|
||||
// set job to be storing data:
|
||||
$jobRepository->setStatus($importJob, 'storing_data');
|
||||
|
||||
/** @var ImportArrayStorage $storage */
|
||||
$storage = app(ImportArrayStorage::class);
|
||||
$storage->setImportJob($importJob);
|
||||
|
||||
try {
|
||||
$storage->store();
|
||||
} catch (FireflyException|Exception $e) {
|
||||
$message = 'The import routine crashed: ' . $e->getMessage();
|
||||
Log::error($message);
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
// set job errored out:
|
||||
$jobRepository->setStatus($importJob, 'error');
|
||||
$this->errorLine($message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
// set storage to be finished:
|
||||
$jobRepository->setStatus($importJob, 'storage_finished');
|
||||
}
|
||||
|
||||
// give feedback:
|
||||
$this->infoLine('Job has finished.');
|
||||
if (null !== $importJob->tag) {
|
||||
$this->infoLine(sprintf('%d transaction(s) have been imported.', $importJob->tag->transactionJournals->count()));
|
||||
$this->infoLine(sprintf('You can find your transactions under tag "%s"', $importJob->tag->tag));
|
||||
}
|
||||
|
||||
if (null === $importJob->tag) {
|
||||
$this->errorLine('No transactions have been imported :(.');
|
||||
}
|
||||
if (\count($importJob->errors) > 0) {
|
||||
$this->infoLine(sprintf('%d error(s) occurred:', \count($importJob->errors)));
|
||||
foreach ($importJob->errors as $err) {
|
||||
$this->errorLine('- ' . $err);
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear cache for user:
|
||||
Preferences::setForUser($user, 'lastActivity', microtime());
|
||||
|
||||
@ -185,20 +265,28 @@ class CreateImport extends Command
|
||||
$cwd = getcwd();
|
||||
$validTypes = config('import.options.file.import_formats');
|
||||
$type = strtolower($this->option('type'));
|
||||
$provider = strtolower($this->option('provider'));
|
||||
$enabled = (bool)config(sprintf('import.enabled.%s', $provider));
|
||||
|
||||
if (!\in_array($type, $validTypes, true)) {
|
||||
if (false === $enabled) {
|
||||
$this->errorLine(sprintf('Provider "%s" is not enabled.', $provider));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($provider === 'file' && !\in_array($type, $validTypes, true)) {
|
||||
$this->errorLine(sprintf('Cannot import file of type "%s"', $type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($file)) {
|
||||
if ($provider === 'file' && !file_exists($file)) {
|
||||
$this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($configuration)) {
|
||||
if ($provider === 'file' && !file_exists($configuration)) {
|
||||
$this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return false;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* DecryptAttachment.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* EncryptFile.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Import.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ScanAttachments.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UpgradeDatabase.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use DB;
|
||||
@ -159,28 +161,41 @@ class UpgradeDatabase extends Command
|
||||
'order' => 2,
|
||||
]
|
||||
);
|
||||
|
||||
// add triggers for amounts:
|
||||
RuleTrigger::create(
|
||||
[
|
||||
'rule_id' => $rule->id,
|
||||
'trigger_type' => 'amount_less',
|
||||
'trigger_value' => round($bill->amount_max, $currency->decimal_places),
|
||||
'active' => 1,
|
||||
'stop_processing' => 0,
|
||||
'order' => 3,
|
||||
]
|
||||
);
|
||||
RuleTrigger::create(
|
||||
[
|
||||
'rule_id' => $rule->id,
|
||||
'trigger_type' => 'amount_more',
|
||||
'trigger_value' => round($bill->amount_min, $currency->decimal_places),
|
||||
'active' => 1,
|
||||
'stop_processing' => 0,
|
||||
'order' => 4,
|
||||
]
|
||||
);
|
||||
if ($bill->amount_max !== $bill->amount_min) {
|
||||
// add triggers for amounts:
|
||||
RuleTrigger::create(
|
||||
[
|
||||
'rule_id' => $rule->id,
|
||||
'trigger_type' => 'amount_less',
|
||||
'trigger_value' => round($bill->amount_max, $currency->decimal_places),
|
||||
'active' => 1,
|
||||
'stop_processing' => 0,
|
||||
'order' => 3,
|
||||
]
|
||||
);
|
||||
RuleTrigger::create(
|
||||
[
|
||||
'rule_id' => $rule->id,
|
||||
'trigger_type' => 'amount_more',
|
||||
'trigger_value' => round($bill->amount_min, $currency->decimal_places),
|
||||
'active' => 1,
|
||||
'stop_processing' => 0,
|
||||
'order' => 4,
|
||||
]
|
||||
);
|
||||
}
|
||||
if($bill->amount_max === $bill->amount_min) {
|
||||
RuleTrigger::create(
|
||||
[
|
||||
'rule_id' => $rule->id,
|
||||
'trigger_type' => 'amount_exactly',
|
||||
'trigger_value' => round($bill->amount_min, $currency->decimal_places),
|
||||
'active' => 1,
|
||||
'stop_processing' => 0,
|
||||
'order' => 3,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// create action
|
||||
RuleAction::create(
|
||||
@ -600,12 +615,16 @@ class UpgradeDatabase extends Command
|
||||
$opposing->transaction_currency_id = $currency->id;
|
||||
$transaction->save();
|
||||
$opposing->save();
|
||||
Log::debug(sprintf('Currency for account "%s" is %s, and currency for account "%s" is also
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Currency for account "%s" is %s, and currency for account "%s" is also
|
||||
%s, so %s #%d (#%d and #%d) has been verified to be to %s exclusively.',
|
||||
$opposing->account->name, $opposingCurrency->code,
|
||||
$transaction->account->name, $transaction->transactionCurrency->code,
|
||||
$journal->transactionType->type, $journal->id,
|
||||
$transaction->id, $opposing->id, $currency->code));
|
||||
$opposing->account->name, $opposingCurrency->code,
|
||||
$transaction->account->name, $transaction->transactionCurrency->code,
|
||||
$journal->transactionType->type, $journal->id,
|
||||
$transaction->id, $opposing->id, $currency->code
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UpgradeFireflyInstructions.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
@ -1,9 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UseEncryption.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -21,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* VerifiesAccessToken.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* VerifyDatabase.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Kernel.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AdminRequestedTestMessage.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\User;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Event.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RegisteredUser.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\User;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RequestedNewPassword.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\User;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RequestedVersionCheckStatus.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* StoredTransactionJournal.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UpdatedTransactionJournal.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UserChangedEmail.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\User;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* FireflyException.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Handler.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use ErrorException;
|
||||
@ -28,6 +30,7 @@ use FireflyIII\Jobs\MailError;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
@ -79,6 +82,11 @@ class Handler extends ExceptionHandler
|
||||
return response()->json(['message' => 'Unauthenticated', 'exception' => 'AuthenticationException'], 401);
|
||||
}
|
||||
|
||||
if ($exception instanceof OAuthServerException && $request->expectsJson()) {
|
||||
// somehow Laravel handler does not catch this:
|
||||
return response()->json(['message' => $exception->getMessage(), 'exception' => 'OAuthServerException'], 401);
|
||||
}
|
||||
|
||||
if ($request->expectsJson()) {
|
||||
$isDebug = config('app.debug', false);
|
||||
if ($isDebug) {
|
||||
@ -96,7 +104,7 @@ class Handler extends ExceptionHandler
|
||||
return response()->json(['message' => 'Internal Firefly III Exception. See log files.', 'exception' => \get_class($exception)], 500);
|
||||
}
|
||||
|
||||
if ($exception instanceof FireflyException || $exception instanceof ErrorException) {
|
||||
if ($exception instanceof FireflyException || $exception instanceof ErrorException || $exception instanceof OAuthServerException) {
|
||||
$isDebug = env('APP_DEBUG', false);
|
||||
|
||||
return response()->view('errors.FireflyException', ['exception' => $exception, 'debug' => $isDebug], 500);
|
||||
@ -120,8 +128,25 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
public function report(Exception $exception)
|
||||
{
|
||||
|
||||
$doMailError = env('SEND_ERROR_MESSAGE', true);
|
||||
if (($exception instanceof FireflyException || $exception instanceof ErrorException) && $doMailError) {
|
||||
if (
|
||||
// if the user wants us to mail:
|
||||
$doMailError === true &&
|
||||
((
|
||||
// and if is one of these error instances
|
||||
$exception instanceof FireflyException
|
||||
|| $exception instanceof ErrorException
|
||||
|| $exception instanceof OAuthServerException
|
||||
|
||||
)
|
||||
|| (
|
||||
// or this one, but it's a JSON exception.
|
||||
$exception instanceof AuthenticationException
|
||||
&& Request::expectsJson() === true
|
||||
))
|
||||
) {
|
||||
// then, send email
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
@ -139,6 +164,9 @@ class Handler extends ExceptionHandler
|
||||
'line' => $exception->getLine(),
|
||||
'code' => $exception->getCode(),
|
||||
'version' => config('firefly.version'),
|
||||
'url' => Request::fullUrl(),
|
||||
'userAgent' => Request::userAgent(),
|
||||
'json' => Request::acceptsJson(),
|
||||
];
|
||||
|
||||
// create job that will mail.
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NotImplementedException.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ValidationException.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AttachmentCollector.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use Carbon\Carbon;
|
||||
@ -94,7 +96,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
*/
|
||||
private function exportAttachment(Attachment $attachment): bool
|
||||
{
|
||||
$file = $attachment->fileName();
|
||||
$file = $attachment->fileName();
|
||||
$decrypted = false;
|
||||
if ($this->uploadDisk->exists($file)) {
|
||||
try {
|
||||
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
||||
@ -104,6 +107,9 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($decrypted === false) {
|
||||
return false;
|
||||
}
|
||||
$exportFile = $this->exportFileName($attachment);
|
||||
$this->exportDisk->put($exportFile, $decrypted);
|
||||
$this->getEntries()->push($exportFile);
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BasicCollector.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use FireflyIII\Models\ExportJob;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CollectorInterface.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use FireflyIII\Models\ExportJob;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UploadCollector.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Collector;
|
||||
|
||||
use Crypt;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Entry.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Entry;
|
||||
|
||||
use FireflyIII\Models\Transaction;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ExpandedProcessor.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export;
|
||||
|
||||
use Crypt;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BasicExporter.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
use FireflyIII\Models\ExportJob;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CsvExporter.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ExporterInterface.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
use FireflyIII\Models\ExportJob;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ProcessorInterface.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AccountFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AccountMetaFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BillFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BudgetFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CategoryFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* PiggyBankEventFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* PiggyBankFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TagFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionCurrencyFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
@ -68,7 +69,8 @@ class TransactionCurrencyFactory
|
||||
$currencyCode = (string)$currencyCode;
|
||||
$currencyId = (int)$currencyId;
|
||||
|
||||
if (\strlen($currencyCode) === 0 && (int)$currencyId === 0) {
|
||||
if ('' === $currencyCode && $currencyId === 0) {
|
||||
Log::warning('Cannot find anything on empty currency code and empty currency ID!');
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -78,6 +80,7 @@ class TransactionCurrencyFactory
|
||||
if (null !== $currency) {
|
||||
return $currency;
|
||||
}
|
||||
Log::warning(sprintf('Currency ID is %d but found nothing!', $currencyId));
|
||||
}
|
||||
// then by code:
|
||||
if (\strlen($currencyCode) > 0) {
|
||||
@ -85,7 +88,9 @@ class TransactionCurrencyFactory
|
||||
if (null !== $currency) {
|
||||
return $currency;
|
||||
}
|
||||
Log::warning(sprintf('Currency code is %d but found nothing!', $currencyCode));
|
||||
}
|
||||
Log::warning('Found nothing for currency.');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,16 +20,19 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Services\Internal\Support\TransactionServiceTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TransactionFactory
|
||||
@ -45,10 +48,21 @@ class TransactionFactory
|
||||
* @param array $data
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function create(array $data): Transaction
|
||||
public function create(array $data): ?Transaction
|
||||
{
|
||||
$currencyId = isset($data['currency']) ? $data['currency']->id : $data['currency_id'];
|
||||
Log::debug('Start of TransactionFactory::create()');
|
||||
$currencyId = $data['currency_id'] ?? null;
|
||||
$currencyId = isset($data['currency']) ? $data['currency']->id : $currencyId;
|
||||
if ('' === $data['amount']) {
|
||||
throw new FireflyException('Amount is an empty string, which Firefly III cannot handle. Apologies.'); // @codeCoverageIgnore
|
||||
}
|
||||
if (null === $currencyId) {
|
||||
throw new FireflyException('Cannot store transaction without currency information.'); // @codeCoverageIgnore
|
||||
}
|
||||
$data['foreign_amount'] = '' === (string)$data['foreign_amount'] ? null : $data['foreign_amount'];
|
||||
Log::debug(sprintf('Create transaction for account #%d ("%s") with amount %s', $data['account']->id, $data['account']->name, $data['amount']));
|
||||
|
||||
return Transaction::create(
|
||||
[
|
||||
@ -72,19 +86,23 @@ class TransactionFactory
|
||||
* @param array $data
|
||||
*
|
||||
* @return Collection
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function createPair(TransactionJournal $journal, array $data): Collection
|
||||
{
|
||||
Log::debug('Start of TransactionFactory::createPair()');
|
||||
// all this data is the same for both transactions:
|
||||
$currency = $this->findCurrency($data['currency_id'], $data['currency_code']);
|
||||
$description = $journal->description === $data['description'] ? null : $data['description'];
|
||||
|
||||
// type of source account depends on journal type:
|
||||
$sourceType = $this->accountType($journal, 'source');
|
||||
Log::debug(sprintf('Expect source account to be of type %s', $sourceType));
|
||||
$sourceAccount = $this->findAccount($sourceType, $data['source_id'], $data['source_name']);
|
||||
|
||||
// same for destination account:
|
||||
$destinationType = $this->accountType($journal, 'destination');
|
||||
Log::debug(sprintf('Expect source destination to be of type %s', $destinationType));
|
||||
$destinationAccount = $this->findAccount($destinationType, $data['destination_id'], $data['destination_name']);
|
||||
// first make a "negative" (source) transaction based on the data in the array.
|
||||
$source = $this->create(
|
||||
@ -125,7 +143,7 @@ class TransactionFactory
|
||||
}
|
||||
|
||||
// set budget:
|
||||
if ($journal->transactionType->type === TransactionType::TRANSFER) {
|
||||
if ($journal->transactionType->type !== TransactionType::WITHDRAWAL) {
|
||||
$data['budget_id'] = null;
|
||||
$data['budget_name'] = null;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionJournalFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
@ -51,6 +52,7 @@ class TransactionJournalFactory
|
||||
// store basic journal first.
|
||||
$type = $this->findTransactionType($data['type']);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
Log::debug(sprintf('Going to store a %s', $type->type));
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => $data['user'],
|
||||
@ -70,8 +72,10 @@ class TransactionJournalFactory
|
||||
$factory = app(TransactionFactory::class);
|
||||
$factory->setUser($this->user);
|
||||
|
||||
Log::debug(sprintf('Found %d transactions in array.', \count($data['transactions'])));
|
||||
/** @var array $trData */
|
||||
foreach ($data['transactions'] as $trData) {
|
||||
foreach ($data['transactions'] as $index => $trData) {
|
||||
Log::debug(sprintf('Now storing transaction %d of %d', $index + 1, \count($data['transactions'])));
|
||||
$factory->createPair($journal, $trData);
|
||||
}
|
||||
$journal->completed = true;
|
||||
@ -91,7 +95,7 @@ class TransactionJournalFactory
|
||||
|
||||
// store date meta fields (if present):
|
||||
$fields = ['sepa-cc', 'sepa-ct-op', 'sepa-ct-id', 'sepa-db', 'sepa-country', 'sepa-ep', 'sepa-ci', 'interest_date', 'book_date', 'process_date',
|
||||
'due_date', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id','importHash'];
|
||||
'due_date', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash','importHashV2', 'external_id'];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$this->storeMeta($journal, $data, $field);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionJournalMetaFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
@ -70,6 +71,7 @@ class TransactionJournalMetaFactory
|
||||
}
|
||||
|
||||
if (null === $entry) {
|
||||
Log::debug(sprintf('Going to create new meta-data entry to store "%s".', $data['name']));
|
||||
$entry = new TransactionJournalMeta();
|
||||
$entry->transactionJournal()->associate($data['journal']);
|
||||
$entry->name = $data['name'];
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionTypeFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
80
app/Handlers/Events/APIEventHandler.php
Normal file
80
app/Handlers/Events/APIEventHandler.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* APIEventHandler.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Mail\AccessTokenCreatedMail;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Laravel\Passport\Events\AccessTokenCreated;
|
||||
use Laravel\Passport\Token;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Request;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class APIEventHandler
|
||||
*/
|
||||
class APIEventHandler
|
||||
{
|
||||
/**
|
||||
* @param AccessTokenCreated $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function accessTokenCreated(AccessTokenCreated $event): bool
|
||||
{
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
$user = $repository->findNull((int)$event->userId);
|
||||
if (null === $user) {
|
||||
Log::error('Access Token generated but no user associated.');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$email = $user->email;
|
||||
$ipAddress = Request::ip();
|
||||
|
||||
Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s, IP is %s', $email, $ipAddress));
|
||||
try {
|
||||
Log::debug('Trying to send message...');
|
||||
Mail::to($email)->send(new AccessTokenCreatedMail($email, $ipAddress));
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
Log::debug('Send message failed! :(');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
Session::flash('error', 'Possible email error: ' . $e->getMessage());
|
||||
}
|
||||
Log::debug('If no error above this line, message was sent.');
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,8 @@ namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\MessageBag;
|
||||
@ -64,6 +66,26 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
$this->uploadDisk = Storage::disk('upload');
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachmentContent(Attachment $attachment): string
|
||||
{
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('at-%d.data', $attachment->id)));
|
||||
} catch (DecryptException|FileNotFoundException $e) {
|
||||
Log::error(sprintf('Could not decrypt data of attachment #%d', $attachment->id));
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
|
@ -39,6 +39,13 @@ interface AttachmentHelperInterface
|
||||
*/
|
||||
public function getAttachmentLocation(Attachment $attachment): string;
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachmentContent(Attachment $attachment): string;
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@ use FireflyIII\Helpers\Filter\NegativeAmountFilter;
|
||||
use FireflyIII\Helpers\Filter\OpposingAccountFilter;
|
||||
use FireflyIII\Helpers\Filter\PositiveAmountFilter;
|
||||
use FireflyIII\Helpers\Filter\SplitIndicatorFilter;
|
||||
use FireflyIII\Helpers\Filter\TransactionViewFilter;
|
||||
use FireflyIII\Helpers\Filter\TransferFilter;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
@ -60,6 +61,7 @@ use Steam;
|
||||
*/
|
||||
class JournalCollector implements JournalCollectorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
private $accountIds = [];
|
||||
/** @var int */
|
||||
@ -106,7 +108,8 @@ class JournalCollector implements JournalCollectorInterface
|
||||
];
|
||||
/** @var array */
|
||||
private $filters = [InternalTransferFilter::class];
|
||||
|
||||
/** @var bool */
|
||||
private $ignoreCache = false;
|
||||
/** @var bool */
|
||||
private $joinedBudget = false;
|
||||
/** @var bool */
|
||||
@ -257,12 +260,15 @@ class JournalCollector implements JournalCollectorInterface
|
||||
foreach ($this->filters as $filter) {
|
||||
$cache->addProperty((string)$filter);
|
||||
}
|
||||
if ($cache->has()) {
|
||||
if (false === $this->ignoreCache && $cache->has()) {
|
||||
Log::debug(sprintf('Return cache of query with ID "%s".', $key));
|
||||
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
}
|
||||
if (true === $this->ignoreCache) {
|
||||
Log::debug('Ignore cache in journal collector.');
|
||||
}
|
||||
/** @var Collection $set */
|
||||
$set = $this->query->get(array_values($this->fields));
|
||||
|
||||
@ -315,6 +321,16 @@ class JournalCollector implements JournalCollectorInterface
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function ignoreCache(): JournalCollectorInterface
|
||||
{
|
||||
$this->ignoreCache = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filter
|
||||
*
|
||||
@ -768,6 +784,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
NegativeAmountFilter::class => new NegativeAmountFilter,
|
||||
SplitIndicatorFilter::class => new SplitIndicatorFilter,
|
||||
CountAttachmentsFilter::class => new CountAttachmentsFilter,
|
||||
TransactionViewFilter::class => new TransactionViewFilter,
|
||||
];
|
||||
Log::debug(sprintf('Will run %d filters on the set.', \count($this->filters)));
|
||||
foreach ($this->filters as $enabled) {
|
||||
@ -784,7 +801,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function joinBudgetTables()
|
||||
private function joinBudgetTables(): void
|
||||
{
|
||||
if (!$this->joinedBudget) {
|
||||
// join some extra tables:
|
||||
@ -809,7 +826,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function joinCategoryTables()
|
||||
private function joinCategoryTables(): void
|
||||
{
|
||||
if (!$this->joinedCategory) {
|
||||
// join some extra tables:
|
||||
@ -839,7 +856,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function joinOpposingTables()
|
||||
private function joinOpposingTables(): void
|
||||
{
|
||||
if (!$this->joinedOpposing) {
|
||||
Log::debug('joinedOpposing is false');
|
||||
@ -871,7 +888,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function joinTagTables()
|
||||
private function joinTagTables(): void
|
||||
{
|
||||
if (!$this->joinedTag) {
|
||||
// join some extra tables:
|
||||
|
@ -78,6 +78,11 @@ interface JournalCollectorInterface
|
||||
*/
|
||||
public function getPaginatedJournals(): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function ignoreCache(): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $filter
|
||||
*
|
||||
|
80
app/Helpers/Filter/TransactionViewFilter.php
Normal file
80
app/Helpers/Filter/TransactionViewFilter.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionViewFilter.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Filter;
|
||||
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TransactionViewFilter.
|
||||
*
|
||||
* This filter removes the entry with a negative amount when it's a withdrawal
|
||||
* And the positive amount when it's a deposit or transfer
|
||||
*
|
||||
* This is used in the mass-edit routine.
|
||||
*
|
||||
*/
|
||||
class TransactionViewFilter implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function filter(Collection $set): Collection
|
||||
{
|
||||
return $set->filter(
|
||||
function (Transaction $transaction) {
|
||||
// remove if amount is less than zero and type is withdrawal.
|
||||
if ($transaction->transaction_type_type === TransactionType::WITHDRAWAL && 1 === bccomp($transaction->transaction_amount, '0')) {
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Filtered #%d because amount is %f and type is %s.', $transaction->id, $transaction->transaction_amount,
|
||||
$transaction->transaction_type_type
|
||||
)
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($transaction->transaction_type_type === TransactionType::DEPOSIT && -1 === bccomp($transaction->transaction_amount, '0')) {
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Filtered #%d because amount is %f and type is %s.', $transaction->id, $transaction->transaction_amount,
|
||||
$transaction->transaction_type_type
|
||||
)
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
Log::debug(
|
||||
sprintf('#%d: amount is %f and type is %s.', $transaction->id, $transaction->transaction_amount, $transaction->transaction_type_type)
|
||||
);
|
||||
|
||||
return $transaction;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -210,18 +210,7 @@ class AccountController extends Controller
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
|
||||
return view(
|
||||
'accounts.edit',
|
||||
compact(
|
||||
'account',
|
||||
'currency',
|
||||
'subTitle',
|
||||
'subTitleIcon',
|
||||
'what',
|
||||
'roles',
|
||||
'preFilled'
|
||||
)
|
||||
);
|
||||
return view('accounts.edit', compact('account', 'currency', 'subTitle', 'subTitleIcon', 'what', 'roles', 'preFilled'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,8 +286,10 @@ class AccountController extends Controller
|
||||
throw new FireflyException('End is after start!'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
||||
$what = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); // used for menu
|
||||
$today = new Carbon;
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||
$currencyId = (int)$this->repository->getMetaValue($account, 'currency_id');
|
||||
@ -320,7 +311,7 @@ class AccountController extends Controller
|
||||
|
||||
return view(
|
||||
'accounts.show',
|
||||
compact('account', 'showAll', 'currency', 'today', 'periods', 'subTitleIcon', 'transactions', 'subTitle', 'start', 'end', 'chartUri')
|
||||
compact('account', 'showAll', 'what', 'currency', 'today', 'periods', 'subTitleIcon', 'transactions', 'subTitle', 'start', 'end', 'chartUri')
|
||||
);
|
||||
}
|
||||
|
||||
@ -338,7 +329,7 @@ class AccountController extends Controller
|
||||
public function showAll(Request $request, Account $account)
|
||||
{
|
||||
if (AccountType::INITIAL_BALANCE === $account->accountType->type) {
|
||||
return $this->redirectToOriginalAccount($account);
|
||||
return $this->redirectToOriginalAccount($account); // @codeCoverageIgnore
|
||||
}
|
||||
$end = new Carbon;
|
||||
$today = new Carbon;
|
||||
|
@ -22,14 +22,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Requests\BillFormRequest;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
@ -50,6 +47,10 @@ class BillController extends Controller
|
||||
{
|
||||
/** @var AttachmentHelperInterface Helper for attachments. */
|
||||
private $attachments;
|
||||
/** @var BillRepositoryInterface */
|
||||
private $billRepository;
|
||||
/** @var RuleGroupRepositoryInterface */
|
||||
private $ruleGroupRepos;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -67,7 +68,9 @@ class BillController extends Controller
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
$this->billRepository = app(BillRepositoryInterface::class);
|
||||
$this->ruleGroupRepos = app(RuleGroupRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -75,21 +78,20 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
* @param Request $request
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function create(Request $request, CurrencyRepositoryInterface $repository)
|
||||
public function create(Request $request)
|
||||
{
|
||||
$periods = [];
|
||||
foreach (config('firefly.bill_periods') as $current) {
|
||||
/** @var array $billPeriods */
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = strtolower((string)trans('firefly.repeat_freq_' . $current));
|
||||
}
|
||||
$subTitle = trans('firefly.create_new_bill');
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$currencies = ExpandedForm::makeSelectList($repository->get());
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (true !== session('bills.create.fromStore')) {
|
||||
@ -97,7 +99,7 @@ class BillController extends Controller
|
||||
}
|
||||
$request->session()->forget('bills.create.fromStore');
|
||||
|
||||
return view('bills.create', compact('periods', 'subTitle', 'currencies', 'defaultCurrency'));
|
||||
return view('bills.create', compact('periods', 'subTitle', 'defaultCurrency'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,16 +117,15 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function destroy(Request $request, BillRepositoryInterface $repository, Bill $bill)
|
||||
public function destroy(Request $request, Bill $bill)
|
||||
{
|
||||
$name = $bill->name;
|
||||
$repository->destroy($bill);
|
||||
$this->billRepository->destroy($bill);
|
||||
|
||||
$request->session()->flash('success', (string)trans('firefly.deleted_bill', ['name' => $name]));
|
||||
Preferences::mark();
|
||||
@ -133,18 +134,21 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Request $request, CurrencyRepositoryInterface $repository, Bill $bill)
|
||||
public function edit(Request $request, Bill $bill)
|
||||
{
|
||||
$periods = [];
|
||||
foreach (config('firefly.bill_periods') as $current) {
|
||||
/** @var array $billPeriods */
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = trans('firefly.' . $current);
|
||||
}
|
||||
|
||||
$subTitle = trans('firefly.edit_bill', ['name' => $bill->name]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
@ -156,36 +160,28 @@ class BillController extends Controller
|
||||
$bill->amount_min = round($bill->amount_min, $currency->decimal_places);
|
||||
$bill->amount_max = round($bill->amount_max, $currency->decimal_places);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$currencies = ExpandedForm::makeSelectList($repository->get());
|
||||
|
||||
$preFilled = [
|
||||
'notes' => '',
|
||||
'notes' => $this->billRepository->getNoteText($bill),
|
||||
'transaction_currency_id' => $bill->transaction_currency_id,
|
||||
'active' => $bill->active,
|
||||
];
|
||||
|
||||
/** @var Note $note */
|
||||
$note = $bill->notes()->first();
|
||||
if (null !== $note) {
|
||||
$preFilled['notes'] = $note->text;
|
||||
}
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
|
||||
$request->session()->forget('bills.edit.fromUpdate');
|
||||
|
||||
return view('bills.edit', compact('subTitle', 'periods', 'bill', 'defaultCurrency', 'currencies'));
|
||||
return view('bills.edit', compact('subTitle', 'periods', 'bill', 'defaultCurrency', 'preFilled'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillRepositoryInterface $repository
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(BillRepositoryInterface $repository)
|
||||
public function index()
|
||||
{
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||
$paginator = $repository->getPaginator($pageSize);
|
||||
$paginator = $this->billRepository->getPaginator($pageSize);
|
||||
$parameters = new ParameterBag();
|
||||
$parameters->set('start', $start);
|
||||
$parameters->set('end', $end);
|
||||
@ -203,7 +199,7 @@ class BillController extends Controller
|
||||
);
|
||||
|
||||
// add info about rules:
|
||||
$rules = $repository->getRulesForBills($paginator->getCollection());
|
||||
$rules = $this->billRepository->getRulesForBills($paginator->getCollection());
|
||||
$bills = $bills->map(
|
||||
function (array $bill) use ($rules) {
|
||||
$bill['rules'] = $rules[$bill['id']] ?? [];
|
||||
@ -218,21 +214,20 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function rescan(Request $request, BillRepositoryInterface $repository, Bill $bill)
|
||||
public function rescan(Request $request, Bill $bill)
|
||||
{
|
||||
if (0 === (int)$bill->active) {
|
||||
$request->session()->flash('warning', (string)trans('firefly.cannot_scan_inactive_bill'));
|
||||
|
||||
return redirect(URL::previous());
|
||||
}
|
||||
$set = $repository->getRulesForBill($bill);
|
||||
$set = $this->billRepository->getRulesForBill($bill);
|
||||
$total = 0;
|
||||
foreach ($set as $rule) {
|
||||
// simply fire off all rules?
|
||||
@ -243,7 +238,7 @@ class BillController extends Controller
|
||||
$matcher->setRule($rule);
|
||||
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||
$total += $matchingTransactions->count();
|
||||
$repository->linkCollectionToBill($bill, $matchingTransactions);
|
||||
$this->billRepository->linkCollectionToBill($bill, $matchingTransactions);
|
||||
}
|
||||
|
||||
|
||||
@ -254,24 +249,23 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function show(Request $request, BillRepositoryInterface $repository, Bill $bill)
|
||||
public function show(Request $request, Bill $bill)
|
||||
{
|
||||
// add info about rules:
|
||||
$rules = $repository->getRulesForBill($bill);
|
||||
$rules = $this->billRepository->getRulesForBill($bill);
|
||||
$subTitle = $bill->name;
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
$year = $start->year;
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||
$yearAverage = $repository->getYearAverage($bill, $start);
|
||||
$overallAverage = $repository->getOverallAverage($bill);
|
||||
$yearAverage = $this->billRepository->getYearAverage($bill, $start);
|
||||
$overallAverage = $this->billRepository->getOverallAverage($bill);
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new DataArraySerializer());
|
||||
$manager->parseIncludes(['attachments', 'notes']);
|
||||
@ -296,16 +290,14 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillFormRequest $request
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param BillFormRequest $request
|
||||
*
|
||||
* @param RuleGroupRepositoryInterface $ruleGroupRepository
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(BillFormRequest $request, BillRepositoryInterface $repository, RuleGroupRepositoryInterface $ruleGroupRepository)
|
||||
public function store(BillFormRequest $request)
|
||||
{
|
||||
$billData = $request->getBillData();
|
||||
$bill = $repository->store($billData);
|
||||
$bill = $this->billRepository->store($billData);
|
||||
if (null === $bill) {
|
||||
$request->session()->flash('error', (string)trans('firefly.bill_store_error'));
|
||||
|
||||
@ -330,16 +322,16 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
// find first rule group, or create one:
|
||||
$count = $ruleGroupRepository->count();
|
||||
$count = $this->ruleGroupRepos->count();
|
||||
if ($count === 0) {
|
||||
$data = [
|
||||
'title' => (string)trans('firefly.rulegroup_for_bills_title'),
|
||||
'description' => (string)trans('firefly.rulegroup_for_bills_description'),
|
||||
];
|
||||
$group = $ruleGroupRepository->store($data);
|
||||
$group = $this->ruleGroupRepos->store($data);
|
||||
}
|
||||
if ($count > 0) {
|
||||
$group = $ruleGroupRepository->getActiveGroups(auth()->user())->first();
|
||||
$group = $this->ruleGroupRepos->getActiveGroups(auth()->user())->first();
|
||||
}
|
||||
|
||||
// redirect to page that will create a new rule.
|
||||
@ -349,16 +341,15 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillFormRequest $request
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
* @param BillFormRequest $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(BillFormRequest $request, BillRepositoryInterface $repository, Bill $bill)
|
||||
public function update(BillFormRequest $request, Bill $bill)
|
||||
{
|
||||
$billData = $request->getBillData();
|
||||
$bill = $repository->update($bill, $billData);
|
||||
$bill = $this->billRepository->update($bill, $billData);
|
||||
|
||||
$request->session()->flash('success', (string)trans('firefly.updated_bill', ['name' => $bill->name]));
|
||||
Preferences::mark();
|
||||
|
@ -87,6 +87,8 @@ class BudgetController extends Controller
|
||||
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
|
||||
$largeDiff = false;
|
||||
$warnText = '';
|
||||
$days = 0;
|
||||
$daysInMonth = 0;
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
$budgetLimit = null;
|
||||
}
|
||||
@ -94,13 +96,17 @@ class BudgetController extends Controller
|
||||
// if today is between start and end, use the diff in days between end and today (days left)
|
||||
// otherwise, use diff between start and end.
|
||||
$today = new Carbon;
|
||||
Log::debug(sprintf('Start is %s, end is %s, today is %s', $start->format('Y-m-d'), $end->format('Y-m-d'),$today->format('Y-m-d')));
|
||||
if ($today->gte($start) && $today->lte($end)) {
|
||||
$days = $end->diffInDays($today);
|
||||
$days = $end->diffInDays($today);
|
||||
$daysInMonth = $start->diffInDays($today);
|
||||
}
|
||||
if ($today->lte($start) || $today->gte($end)) {
|
||||
$days = $start->diffInDays($end);
|
||||
$days = $start->diffInDays($end);
|
||||
$daysInMonth = $start->diffInDays($end);
|
||||
}
|
||||
$days = $days === 0 ? 1 : $days;
|
||||
$days = $days === 0 ? 1 : $days;
|
||||
$daysInMonth = $daysInMonth === 0 ? 1 : $daysInMonth;
|
||||
|
||||
// calculate left in budget:
|
||||
$spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end);
|
||||
@ -146,6 +152,7 @@ class BudgetController extends Controller
|
||||
'large_diff' => $largeDiff,
|
||||
'left_per_day' => $leftPerDay,
|
||||
'warn_text' => $warnText,
|
||||
'daysInMonth' => $daysInMonth,
|
||||
|
||||
]
|
||||
);
|
||||
@ -229,22 +236,13 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function index(Request $request, string $moment = null)
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = session('start', new Carbon);
|
||||
$end = session('end', new Carbon);
|
||||
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||
|
||||
// if today is between start and end, use the diff in days between end and today (days left)
|
||||
// otherwise, use diff between start and end.
|
||||
$today = new Carbon;
|
||||
if ($today->gte($start) && $today->lte($end)) {
|
||||
$days = $end->diffInDays($today);
|
||||
}
|
||||
if ($today->lte($start) || $today->gte($end)) {
|
||||
$days = $start->diffInDays($end);
|
||||
}
|
||||
$days = $days === 0 ? 1 : $days;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = session('start', new Carbon);
|
||||
$end = session('end', new Carbon);
|
||||
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||
$days = 0;
|
||||
$daysInMonth = 0;
|
||||
|
||||
// make date if present:
|
||||
if (null !== $moment || '' !== (string)$moment) {
|
||||
@ -256,6 +254,22 @@ class BudgetController extends Controller
|
||||
Log::debug('start and end are already defined.');
|
||||
}
|
||||
}
|
||||
|
||||
// if today is between start and end, use the diff in days between end and today (days left)
|
||||
// otherwise, use diff between start and end.
|
||||
$today = new Carbon;
|
||||
if ($today->gte($start) && $today->lte($end)) {
|
||||
$days = $end->diffInDays($today);
|
||||
$daysInMonth = $start->diffInDays($today);
|
||||
}
|
||||
if ($today->lte($start) || $today->gte($end)) {
|
||||
$days = $start->diffInDays($end);
|
||||
$daysInMonth = $start->diffInDays($end);
|
||||
}
|
||||
$days = $days === 0 ? 1 : $days;
|
||||
$daysInMonth = $daysInMonth === 0 ? 1 : $daysInMonth;
|
||||
|
||||
|
||||
$next = clone $end;
|
||||
$next->addDay();
|
||||
$prev = clone $start;
|
||||
@ -312,7 +326,7 @@ class BudgetController extends Controller
|
||||
return view(
|
||||
'budgets.index', compact(
|
||||
'available', 'currentMonth', 'next', 'nextText', 'prev', 'allBudgets', 'prevText', 'periodStart', 'periodEnd', 'days', 'page',
|
||||
'budgetInformation',
|
||||
'budgetInformation', 'daysInMonth',
|
||||
'inactive', 'budgets', 'spent', 'budgeted', 'previousLoop', 'nextLoop', 'start', 'end'
|
||||
)
|
||||
);
|
||||
|
@ -66,6 +66,7 @@ class DebugController extends Controller
|
||||
$userAgent = $request->header('user-agent');
|
||||
$isSandstorm = var_export(env('IS_SANDSTORM', 'unknown'), true);
|
||||
$isDocker = var_export(env('IS_DOCKER', 'unknown'), true);
|
||||
$toSandbox = var_export(env('BUNQ_USE_SANDBOX', 'unknown'), true);
|
||||
$trustedProxies = env('TRUSTED_PROXIES', '(none)');
|
||||
$displayErrors = ini_get('display_errors');
|
||||
$errorReporting = $this->errorReporting((int)ini_get('error_reporting'));
|
||||
@ -96,40 +97,24 @@ class DebugController extends Controller
|
||||
if (null !== $logFile) {
|
||||
try {
|
||||
$logContent = file_get_contents($logFile);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// don't care
|
||||
Log::debug(sprintf('Could not read log file. %s', $e->getMessage()));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
}
|
||||
// last few lines
|
||||
$logContent = 'Truncated from this point <----|' . substr($logContent, -4096);
|
||||
$logContent = 'Truncated from this point <----|' . substr($logContent, -8192);
|
||||
|
||||
return view(
|
||||
'debug',
|
||||
compact(
|
||||
'phpVersion',
|
||||
'extensions', 'localeAttempts',
|
||||
'appEnv',
|
||||
'appDebug',
|
||||
'appLog',
|
||||
'appLogLevel',
|
||||
'now',
|
||||
'packages',
|
||||
'drivers',
|
||||
'currentDriver',
|
||||
'userAgent',
|
||||
'displayErrors',
|
||||
'errorReporting',
|
||||
'phpOs',
|
||||
'interface',
|
||||
'logContent',
|
||||
'cacheDriver',
|
||||
'isDocker',
|
||||
'isSandstorm',
|
||||
'trustedProxies'
|
||||
)
|
||||
'debug', compact(
|
||||
'phpVersion', 'extensions', 'localeAttempts', 'appEnv', 'appDebug', 'appLog', 'appLogLevel', 'now', 'packages', 'drivers', 'currentDriver',
|
||||
'userAgent', 'displayErrors', 'errorReporting', 'phpOs', 'interface', 'logContent', 'cacheDriver', 'isDocker', 'isSandstorm', 'trustedProxies',
|
||||
'toSandbox'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -23,12 +23,10 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Export\ProcessorInterface;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Requests\ExportFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface;
|
||||
@ -107,12 +105,11 @@ class ExportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountRepositoryInterface $repository
|
||||
* @param ExportJobRepositoryInterface $jobs
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(AccountRepositoryInterface $repository, ExportJobRepositoryInterface $jobs)
|
||||
public function index(ExportJobRepositoryInterface $jobs)
|
||||
{
|
||||
// create new export job.
|
||||
$job = $jobs->create();
|
||||
@ -120,15 +117,12 @@ class ExportController extends Controller
|
||||
$jobs->cleanup();
|
||||
|
||||
// does the user have shared accounts?
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$accountList = ExpandedForm::makeSelectList($accounts);
|
||||
$checked = array_keys($accountList);
|
||||
$formats = array_keys(config('firefly.export_formats'));
|
||||
$defaultFormat = Preferences::get('export_format', config('firefly.default_export_format'))->data;
|
||||
$first = session('first')->format('Y-m-d');
|
||||
$today = Carbon::create()->format('Y-m-d');
|
||||
|
||||
return view('export.index', compact('job', 'checked', 'accountList', 'formats', 'defaultFormat', 'first', 'today'));
|
||||
return view('export.index', compact('job', 'formats', 'defaultFormat', 'first', 'today'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,10 +133,12 @@ class HomeController extends Controller
|
||||
Log::debug('Call twig:clean...');
|
||||
try {
|
||||
Artisan::call('twig:clean');
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
// dont care
|
||||
// don't care
|
||||
Log::debug('Called twig:clean.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
Log::debug('Call view:clear...');
|
||||
Artisan::call('view:clear');
|
||||
Log::debug('Done! Redirecting...');
|
||||
|
@ -1,147 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ConfigurationController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Import\Configuration\ConfiguratorInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the job. This method is returned to until job is deemed "configured".
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index(ImportJob $job)
|
||||
{
|
||||
// create configuration class:
|
||||
$configurator = $this->makeConfigurator($job);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->isJobConfigured()) {
|
||||
$this->repository->updateStatus($job, 'configured');
|
||||
|
||||
return redirect(route('import.status', [$job->key]));
|
||||
}
|
||||
|
||||
$this->repository->updateStatus($job, 'configuring');
|
||||
|
||||
$view = $configurator->getNextView();
|
||||
$data = $configurator->getNextData();
|
||||
$subTitle = trans('firefly.import_config_bread_crumb');
|
||||
$subTitleIcon = 'fa-wrench';
|
||||
|
||||
return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the configuration. Returns to "configure" method until job is configured.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function post(Request $request, ImportJob $job)
|
||||
{
|
||||
Log::debug('Now in postConfigure()', ['job' => $job->key]);
|
||||
$configurator = $this->makeConfigurator($job);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->isJobConfigured()) {
|
||||
return redirect(route('import.status', [$job->key]));
|
||||
}
|
||||
$data = $request->all();
|
||||
$configurator->configureJob($data);
|
||||
|
||||
// get possible warning from configurator:
|
||||
$warning = $configurator->getWarningMessage();
|
||||
|
||||
if (\strlen($warning) > 0) {
|
||||
$request->session()->flash('warning', $warning);
|
||||
}
|
||||
|
||||
// return to configure
|
||||
return redirect(route('import.configure', [$job->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return ConfiguratorInterface
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function makeConfigurator(ImportJob $job): ConfiguratorInterface
|
||||
{
|
||||
$type = $job->file_type;
|
||||
$key = sprintf('import.configuration.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find configurator class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
}
|
||||
Log::debug(sprintf('Going to create class "%s"', $className));
|
||||
/** @var ConfiguratorInterface $configurator */
|
||||
$configurator = app($className);
|
||||
$configurator->setJob($job);
|
||||
|
||||
return $configurator;
|
||||
}
|
||||
}
|
@ -24,17 +24,14 @@ namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use View;
|
||||
|
||||
|
||||
/**
|
||||
* Class FileController.
|
||||
*/
|
||||
@ -43,6 +40,9 @@ class IndexController extends Controller
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/** @var UserRepositoryInterface */
|
||||
public $userRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -54,33 +54,96 @@ class IndexController extends Controller
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new import job for $bank with the default (global) job configuration.
|
||||
* Creates a new import job for $importProvider.
|
||||
*
|
||||
* @param string $bank
|
||||
* @param string $importProvider
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function create(string $bank)
|
||||
public function create(string $importProvider)
|
||||
{
|
||||
if (true === !config(sprintf('import.enabled.%s', $bank))) {
|
||||
throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); // @codeCoverageIgnore
|
||||
Log::debug(sprintf('Will create job for provider "%s"', $importProvider));
|
||||
// can only create "fake" for demo user.
|
||||
$providers = array_keys($this->getProviders());
|
||||
if (!\in_array($importProvider, $providers, true)) {
|
||||
Log::error(sprintf('%s-provider is disabled. Cannot create job.', $importProvider));
|
||||
session()->flash('warning', trans('import.cannot_create_for_provider', ['provider' => $importProvider]));
|
||||
|
||||
return redirect(route('import.index'));
|
||||
}
|
||||
|
||||
$importJob = $this->repository->create($bank);
|
||||
$importJob = $this->repository->create($importProvider);
|
||||
Log::debug(sprintf('Created job #%d for provider %s', $importJob->id, $importProvider));
|
||||
|
||||
$hasPreReq = (bool)config(sprintf('import.has_prereq.%s', $importProvider));
|
||||
$hasConfig = (bool)config(sprintf('import.has_job_config.%s', $importProvider));
|
||||
// if job provider has no prerequisites:
|
||||
if ($hasPreReq === false) {
|
||||
Log::debug('Provider has no prerequisites. Continue.');
|
||||
// if job provider also has no configuration:
|
||||
if ($hasConfig === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug('Provider needs no configuration for job. Job is ready to start.');
|
||||
$this->repository->updateStatus($importJob, 'ready_to_run');
|
||||
Log::debug('Redirect to status-page.');
|
||||
|
||||
return redirect(route('import.job.status.index', [$importJob->key]));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// update job to say "has_prereq".
|
||||
$this->repository->setStatus($importJob, 'has_prereq');
|
||||
|
||||
// redirect to job configuration.
|
||||
Log::debug('Redirect to configuration.');
|
||||
|
||||
return redirect(route('import.job.configuration.index', [$importJob->key]));
|
||||
}
|
||||
Log::debug('Job provider has prerequisites.');
|
||||
// if need to set prerequisites, do that first.
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $importProvider));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('No class to handle prerequisites for "%s".', $importProvider)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var PrerequisitesInterface $providerPre */
|
||||
$providerPre = app($class);
|
||||
$providerPre->setUser(auth()->user());
|
||||
|
||||
if (!$providerPre->isComplete()) {
|
||||
Log::debug('Job provider prerequisites are not yet filled in. Redirect to prerequisites-page.');
|
||||
|
||||
// redirect to global prerequisites
|
||||
return redirect(route('import.prerequisites.index', [$importProvider, $importJob->key]));
|
||||
}
|
||||
Log::debug('Prerequisites are complete.');
|
||||
|
||||
// update job to say "has_prereq".
|
||||
$this->repository->setStatus($importJob, 'has_prereq');
|
||||
if ($hasConfig === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug('Provider has no configuration. Job is ready to start.');
|
||||
$this->repository->updateStatus($importJob, 'ready_to_run');
|
||||
Log::debug('Redirect to status-page.');
|
||||
|
||||
return redirect(route('import.job.status.index', [$importJob->key]));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
Log::debug('Job has configuration. Redirect to job-config.');
|
||||
|
||||
// Otherwise just redirect to job configuration.
|
||||
return redirect(route('import.job.configuration.index', [$importJob->key]));
|
||||
|
||||
// from here, always go to configure step.
|
||||
return redirect(route('import.configure', [$importJob->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,22 +153,18 @@ class IndexController extends Controller
|
||||
*
|
||||
* @return LaravelResponse
|
||||
*/
|
||||
public function download(ImportJob $job)
|
||||
public function download(ImportJob $job): LaravelResponse
|
||||
{
|
||||
Log::debug('Now in download()', ['job' => $job->key]);
|
||||
$config = $job->configuration;
|
||||
|
||||
$config = $this->repository->getConfiguration($job);
|
||||
// This is CSV import specific:
|
||||
$config['column-roles-complete'] = false;
|
||||
$config['column-mapping-complete'] = false;
|
||||
$config['initial-config-complete'] = false;
|
||||
$config['has-file-upload'] = false;
|
||||
$config['delimiter'] = "\t" === $config['delimiter'] ? 'tab' : $config['delimiter'];
|
||||
unset($config['stage']);
|
||||
|
||||
$result = json_encode($config, JSON_PRETTY_PRINT);
|
||||
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
|
||||
$config['delimiter'] = $config['delimiter'] ?? ',';
|
||||
$config['delimiter'] = "\t" === $config['delimiter'] ? 'tab' : $config['delimiter'];
|
||||
|
||||
// this prevents private information from escaping
|
||||
$config['column-mapping-config'] = [];
|
||||
$result = json_encode($config, JSON_PRETTY_PRINT);
|
||||
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($result, 200);
|
||||
$response->header('Content-disposition', 'attachment; filename=' . $name)
|
||||
@ -127,78 +186,60 @@ class IndexController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = trans('firefly.import_index_sub_title');
|
||||
$providers = $this->getProviders();
|
||||
$subTitle = trans('import.index_breadcrumb');
|
||||
$subTitleIcon = 'fa-home';
|
||||
$routines = config('import.enabled');
|
||||
|
||||
return view('import.index', compact('subTitle', 'subTitleIcon', 'routines'));
|
||||
return view('import.index', compact('subTitle', 'subTitleIcon', 'providers'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return array
|
||||
*/
|
||||
public function reset(Request $request, string $bank)
|
||||
private function getProviders(): array
|
||||
{
|
||||
if ($bank === 'bunq') {
|
||||
// remove bunq related preferences.
|
||||
Preferences::delete('bunq_api_key');
|
||||
Preferences::delete('bunq_server_public_key');
|
||||
Preferences::delete('bunq_private_key');
|
||||
Preferences::delete('bunq_public_key');
|
||||
Preferences::delete('bunq_installation_token');
|
||||
Preferences::delete('bunq_installation_id');
|
||||
Preferences::delete('bunq_device_server_id');
|
||||
Preferences::delete('external_ip');
|
||||
// get and filter all import routines:
|
||||
/** @var array $config */
|
||||
$providerNames = array_keys(config('import.enabled'));
|
||||
$providers = [];
|
||||
$isDemoUser = $this->userRepository->hasRole(auth()->user(), 'demo');
|
||||
$isDebug = (bool)config('app.debug');
|
||||
foreach ($providerNames as $providerName) {
|
||||
//Log::debug(sprintf('Now with provider %s', $providerName));
|
||||
// only consider enabled providers
|
||||
$enabled = (bool)config(sprintf('import.enabled.%s', $providerName));
|
||||
$allowedForDemo = (bool)config(sprintf('import.allowed_for_demo.%s', $providerName));
|
||||
$allowedForUser = (bool)config(sprintf('import.allowed_for_user.%s', $providerName));
|
||||
if ($enabled === false) {
|
||||
//Log::debug('Provider is not enabled. NEXT!');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isDemoUser === true && $allowedForDemo === false) {
|
||||
//Log::debug('User is demo and this provider is not allowed for demo user. NEXT!');
|
||||
continue;
|
||||
}
|
||||
if ($isDemoUser === false && $allowedForUser === false && $isDebug === false) {
|
||||
//Log::debug('User is not demo and this provider is not allowed for such users. NEXT!');
|
||||
continue; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$providers[$providerName] = [
|
||||
'has_prereq' => (bool)config('import.has_prereq.' . $providerName),
|
||||
];
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $providerName));
|
||||
$result = false;
|
||||
if ($class !== '' && class_exists($class)) {
|
||||
//Log::debug('Will not check prerequisites.');
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
$result = $object->isComplete();
|
||||
}
|
||||
$providers[$providerName]['prereq_complete'] = $result;
|
||||
}
|
||||
Log::debug(sprintf('Enabled providers: %s', json_encode(array_keys($providers))));
|
||||
|
||||
if ($bank === 'spectre') {
|
||||
// remove spectre related preferences:
|
||||
Preferences::delete('spectre_client_id');
|
||||
Preferences::delete('spectre_app_secret');
|
||||
Preferences::delete('spectre_service_secret');
|
||||
Preferences::delete('spectre_app_id');
|
||||
Preferences::delete('spectre_secret');
|
||||
Preferences::delete('spectre_private_key');
|
||||
Preferences::delete('spectre_public_key');
|
||||
Preferences::delete('spectre_customer');
|
||||
}
|
||||
|
||||
Preferences::mark();
|
||||
$request->session()->flash('info', (string)trans('firefly.settings_reset_for_' . $bank));
|
||||
|
||||
return redirect(route('import.index'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function start(ImportJob $job)
|
||||
{
|
||||
$type = $job->file_type;
|
||||
$key = sprintf('import.routine.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setJob($job);
|
||||
$result = $routine->run();
|
||||
|
||||
if ($result) {
|
||||
return response()->json(['run' => 'ok']);
|
||||
}
|
||||
|
||||
throw new FireflyException('Job did not complete successfully. Please review the log files.');
|
||||
return $providers;
|
||||
}
|
||||
}
|
||||
|
184
app/Http/Controllers/Import/JobConfigurationController.php
Normal file
184
app/Http/Controllers/Import/JobConfigurationController.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* JobConfigurationController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Import\JobConfiguration\JobConfigurationInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class JobConfigurationController
|
||||
*/
|
||||
class JobConfigurationController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the job. This method is returned to until job is deemed "configured".
|
||||
*
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index(ImportJob $importJob)
|
||||
{
|
||||
Log::debug('Now in JobConfigurationController::index()');
|
||||
// catch impossible status:
|
||||
$allowed = ['has_prereq', 'need_job_config'];
|
||||
if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) {
|
||||
Log::debug(sprintf('Job has state "%s", but we only accept %s', $importJob->status, json_encode($allowed)));
|
||||
session()->flash('error', trans('import.bad_job_status', ['status' => $importJob->status]));
|
||||
|
||||
return redirect(route('import.index'));
|
||||
}
|
||||
Log::debug(sprintf('Now in JobConfigurationController::index() with job "%s" and status "%s"', $importJob->key, $importJob->status));
|
||||
|
||||
// if provider has no config, just push it through:
|
||||
$importProvider = $importJob->provider;
|
||||
if (!(bool)config(sprintf('import.has_job_config.%s', $importProvider))) {
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug('Job needs no config, is ready to run!');
|
||||
$this->repository->updateStatus($importJob, 'ready_to_run');
|
||||
|
||||
return redirect(route('import.job.status.index', [$importJob->key]));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// create configuration class:
|
||||
$configurator = $this->makeConfigurator($importJob);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->configurationComplete()) {
|
||||
Log::debug('Config is complete, set status to ready_to_run.');
|
||||
$this->repository->updateStatus($importJob, 'ready_to_run');
|
||||
|
||||
return redirect(route('import.job.status.index', [$importJob->key]));
|
||||
}
|
||||
|
||||
$view = $configurator->getNextView();
|
||||
$data = $configurator->getNextData();
|
||||
$subTitle = trans('import.job_configuration_breadcrumb', ['key' => $importJob->key]);
|
||||
$subTitleIcon = 'fa-wrench';
|
||||
|
||||
return view($view, compact('data', 'importJob', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the configuration. Returns to "configure" method until job is configured.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function post(Request $request, ImportJob $importJob)
|
||||
{
|
||||
// catch impossible status:
|
||||
$allowed = ['has_prereq', 'need_job_config'];
|
||||
if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) {
|
||||
session()->flash('error', trans('import.bad_job_status', ['status' => $importJob->status]));
|
||||
|
||||
return redirect(route('import.index'));
|
||||
}
|
||||
|
||||
Log::debug('Now in postConfigure()', ['job' => $importJob->key]);
|
||||
$configurator = $this->makeConfigurator($importJob);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->configurationComplete()) {
|
||||
$this->repository->updateStatus($importJob, 'ready_to_run');
|
||||
|
||||
return redirect(route('import.job.status.index', [$importJob->key]));
|
||||
}
|
||||
|
||||
// uploaded files are attached to the job.
|
||||
// the configurator can then handle them.
|
||||
$result = new MessageBag;
|
||||
|
||||
/** @var UploadedFile $upload */
|
||||
foreach ($request->allFiles() as $name => $upload) {
|
||||
$result = $this->repository->storeFileUpload($importJob, $name, $upload);
|
||||
}
|
||||
$data = $request->all();
|
||||
$messages = $configurator->configureJob($data);
|
||||
$result->merge($messages);
|
||||
|
||||
if ($messages->count() > 0) {
|
||||
$request->session()->flash('warning', $messages->first());
|
||||
}
|
||||
|
||||
// return to configure
|
||||
return redirect(route('import.job.configuration.index', [$importJob->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JobConfigurationInterface
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function makeConfigurator(ImportJob $importJob): JobConfigurationInterface
|
||||
{
|
||||
$key = sprintf('import.configuration.%s', $importJob->provider);
|
||||
$className = (string)config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find configurator class for job with provider "%s".', $importJob->provider)); // @codeCoverageIgnore
|
||||
}
|
||||
Log::debug(sprintf('Going to create class "%s"', $className));
|
||||
/** @var JobConfigurationInterface $configurator */
|
||||
$configurator = app($className);
|
||||
$configurator->setImportJob($importJob);
|
||||
|
||||
return $configurator;
|
||||
}
|
||||
}
|
232
app/Http/Controllers/Import/JobStatusController.php
Normal file
232
app/Http/Controllers/Import/JobStatusController.php
Normal file
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* JobStatusController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Import\Storage\ImportArrayStorage;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class JobStatusController
|
||||
*/
|
||||
class JobStatusController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function index(ImportJob $importJob)
|
||||
{
|
||||
$subTitleIcon = 'fa-gear';
|
||||
$subTitle = trans('import.job_status_breadcrumb', ['key' => $importJob->key]);
|
||||
|
||||
return view('import.status', compact('importJob', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function json(ImportJob $importJob): JsonResponse
|
||||
{
|
||||
$count = \count($importJob->transactions);
|
||||
$json = [
|
||||
'status' => $importJob->status,
|
||||
'errors' => $importJob->errors,
|
||||
'count' => $count,
|
||||
'tag_id' => $importJob->tag_id,
|
||||
'tag_name' => null === $importJob->tag_id ? null : $importJob->tag->tag,
|
||||
'report_txt' => trans('import.unknown_import_result'),
|
||||
'download_config' => false,
|
||||
'download_config_text' => '',
|
||||
];
|
||||
|
||||
if ($importJob->provider === 'file') {
|
||||
$json['download_config'] = true;
|
||||
$json['download_config_text']
|
||||
= trans('import.should_download_config', ['route' => route('import.job.download', [$importJob->key])]) . ' '
|
||||
. trans('import.share_config_file');
|
||||
}
|
||||
|
||||
// if count is zero:
|
||||
if (null !== $importJob->tag_id) {
|
||||
$count = $importJob->tag->transactionJournals->count();
|
||||
}
|
||||
if ($count === 0) {
|
||||
$json['report_txt'] = trans('import.result_no_transactions');
|
||||
}
|
||||
if ($count === 1 && null !== $importJob->tag_id) {
|
||||
$json['report_txt'] = trans(
|
||||
'import.result_one_transaction', ['route' => route('tags.show', [$importJob->tag_id, 'all']), 'tag' => $importJob->tag->tag]
|
||||
);
|
||||
}
|
||||
if ($count > 1 && null !== $importJob->tag_id) {
|
||||
$json['report_txt'] = trans(
|
||||
'import.result_many_transactions',
|
||||
['count' => $count, 'route' => route('tags.show', [$importJob->tag_id, 'all']), 'tag' => $importJob->tag->tag]
|
||||
);
|
||||
}
|
||||
|
||||
return response()->json($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function start(ImportJob $importJob): JsonResponse
|
||||
{
|
||||
// catch impossible status:
|
||||
$allowed = ['ready_to_run', 'need_job_config', 'error']; // todo remove error
|
||||
|
||||
if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) {
|
||||
Log::error('Job is not ready.');
|
||||
$this->repository->setStatus($importJob, 'error');
|
||||
|
||||
return response()->json(
|
||||
['status' => 'NOK', 'message' => sprintf('JobStatusController::start expects status "ready_to_run" instead of "%s".', $importJob->status)]
|
||||
);
|
||||
}
|
||||
$importProvider = $importJob->provider;
|
||||
$key = sprintf('import.routine.%s', $importProvider);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
return response()->json(
|
||||
['status' => 'NOK', 'message' => sprintf('Cannot find import routine class for job of type "%s".', $importProvider)]
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setImportJob($importJob);
|
||||
try {
|
||||
$routine->run();
|
||||
} catch (FireflyException|Exception $e) {
|
||||
$message = 'The import routine crashed: ' . $e->getMessage();
|
||||
Log::error($message);
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
// set job errored out:
|
||||
$this->repository->setStatus($importJob, 'error');
|
||||
|
||||
return response()->json(['status' => 'NOK', 'message' => $message]);
|
||||
}
|
||||
|
||||
// expect nothing from routine, just return OK to user.
|
||||
return response()->json(['status' => 'OK', 'message' => 'stage_finished']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store does three things:
|
||||
*
|
||||
* - Store the transactions.
|
||||
* - Add them to a tag.
|
||||
*
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(ImportJob $importJob): JsonResponse
|
||||
{
|
||||
// catch impossible status:
|
||||
$allowed = ['provider_finished', 'storing_data'];
|
||||
if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) {
|
||||
Log::error('Job is not ready.');
|
||||
|
||||
return response()->json(
|
||||
['status' => 'NOK', 'message' => sprintf('JobStatusController::start expects status "provider_finished" instead of "%s".', $importJob->status)]
|
||||
);
|
||||
}
|
||||
|
||||
// set job to be storing data:
|
||||
$this->repository->setStatus($importJob, 'storing_data');
|
||||
|
||||
try {
|
||||
$this->storeTransactions($importJob);
|
||||
} catch (FireflyException $e) {
|
||||
$message = 'The import storage routine crashed: ' . $e->getMessage();
|
||||
Log::error($message);
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
// set job errored out:
|
||||
$this->repository->setStatus($importJob, 'error');
|
||||
|
||||
return response()->json(['status' => 'NOK', 'message' => $message]);
|
||||
}
|
||||
// set storage to be finished:
|
||||
$this->repository->setStatus($importJob, 'storage_finished');
|
||||
|
||||
|
||||
// expect nothing from routine, just return OK to user.
|
||||
return response()->json(['status' => 'OK', 'message' => 'storage_finished']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function storeTransactions(ImportJob $importJob): void
|
||||
{
|
||||
/** @var ImportArrayStorage $storage */
|
||||
$storage = app(ImportArrayStorage::class);
|
||||
$storage->setImportJob($importJob);
|
||||
try {
|
||||
$storage->store();
|
||||
} catch (FireflyException|Exception $e) {
|
||||
throw new FireflyException($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -24,8 +24,9 @@ namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
@ -35,6 +36,9 @@ use Log;
|
||||
class PrerequisitesController extends Controller
|
||||
{
|
||||
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -46,48 +50,59 @@ class PrerequisitesController extends Controller
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
app('view')->share('subTitleIcon', 'fa-check');
|
||||
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Once there are no prerequisites, this method will create an importjob object and
|
||||
* redirect the user to a view where this object can be used by a bank specific
|
||||
* class to process.
|
||||
* This method will process and store import provider global prerequisites
|
||||
* such as API keys.
|
||||
*
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse
|
||||
* @param string $importProvider
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index(string $bank)
|
||||
public function index(string $importProvider, ImportJob $importJob = null)
|
||||
{
|
||||
if (true === !config(sprintf('import.enabled.%s', $bank))) {
|
||||
throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); // @codeCoverageIgnore
|
||||
}
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $bank));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('No class to handle "%s".', $bank)); // @codeCoverageIgnore
|
||||
// catch impossible status:
|
||||
$allowed = ['new'];
|
||||
if (null !== $importJob && !in_array($importJob->status, $allowed)) {
|
||||
Log::error(sprintf('Job has state "%s" but this Prerequisites::index() only accepts %s', $importJob->status, json_encode($allowed)));
|
||||
session()->flash('error', trans('import.bad_job_status', ['status' => $importJob->status]));
|
||||
|
||||
return redirect(route('import.index'));
|
||||
}
|
||||
|
||||
app('view')->share('subTitle', trans('import.prerequisites_breadcrumb_' . $importProvider));
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $importProvider));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('No class to handle prerequisites for "%s".', $importProvider)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
|
||||
if ($object->hasPrerequisites()) {
|
||||
$view = $object->getView();
|
||||
$parameters = ['title' => (string)trans('firefly.import_index_title'), 'mainTitleIcon' => 'fa-archive'];
|
||||
$parameters = array_merge($object->getViewParameters(), $parameters);
|
||||
if (null !== $importJob && $object->isComplete()) {
|
||||
// update job:
|
||||
$this->repository->setStatus($importJob, 'has_prereq');
|
||||
|
||||
return view($view, $parameters);
|
||||
// redirect to job config:
|
||||
return redirect(route('import.job.configuration.index', [$importJob->key]));
|
||||
}
|
||||
|
||||
// if no (more) prerequisites, return to create a job:
|
||||
return redirect(route('import.create-job', [$bank]));
|
||||
|
||||
$view = $object->getView();
|
||||
$parameters = ['title' => (string)trans('firefly.import_index_title'), 'mainTitleIcon' => 'fa-archive', 'importJob' => $importJob];
|
||||
$parameters = array_merge($object->getViewParameters(), $parameters);
|
||||
|
||||
return view($view, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,42 +113,63 @@ class PrerequisitesController extends Controller
|
||||
*
|
||||
* @see PrerequisitesInterface::storePrerequisites
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $bank
|
||||
* @param Request $request
|
||||
* @param string $importProvider
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function post(Request $request, string $bank)
|
||||
public function post(Request $request, string $importProvider, ImportJob $importJob = null)
|
||||
{
|
||||
Log::debug(sprintf('Now in postPrerequisites for %s', $bank));
|
||||
Log::debug(sprintf('Now in postPrerequisites for %s', $importProvider));
|
||||
|
||||
if (true === !config(sprintf('import.enabled.%s', $bank))) {
|
||||
throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); // @codeCoverageIgnore
|
||||
// catch impossible status:
|
||||
$allowed = ['new'];
|
||||
if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) {
|
||||
Log::error(sprintf('Job has state "%s" but this Prerequisites::post() only accepts %s', $importJob->status, json_encode($allowed)));
|
||||
session()->flash('error', trans('import.bad_job_status', ['status' => $importJob->status]));
|
||||
|
||||
return redirect(route('import.index'));
|
||||
}
|
||||
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $bank));
|
||||
|
||||
$class = (string)config(sprintf('import.prerequisites.%s', $importProvider));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('Cannot find class %s', $class)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
if (!$object->hasPrerequisites()) {
|
||||
Log::debug(sprintf('No more prerequisites for %s, move to form.', $bank));
|
||||
|
||||
return redirect(route('import.create-job', [$bank]));
|
||||
}
|
||||
Log::debug('Going to store entered prerequisites.');
|
||||
// store post data
|
||||
$result = $object->storePrerequisites($request);
|
||||
$data = $request->all();
|
||||
$result = $object->storePrerequisites($data);
|
||||
Log::debug(sprintf('Result of storePrerequisites has message count: %d', $result->count()));
|
||||
|
||||
if ($result->count() > 0) {
|
||||
$request->session()->flash('error', $result->first());
|
||||
|
||||
// redirect back to job, if has job:
|
||||
return redirect(route('import.prerequisites.index', [$importProvider, $importJob->key ?? '']))->withInput();
|
||||
}
|
||||
|
||||
return redirect(route('import.prerequisites', [$bank]));
|
||||
// session flash!
|
||||
$request->session()->flash('success', (string)trans('import.prerequisites_saved_for_' . $importProvider));
|
||||
|
||||
// if has job, redirect to global config for provider
|
||||
// if no job, back to index!
|
||||
if (null === $importJob) {
|
||||
return redirect(route('import.index'));
|
||||
}
|
||||
|
||||
// update job:
|
||||
$this->repository->setStatus($importJob, 'has_prereq');
|
||||
|
||||
// redirect to job config:
|
||||
return redirect(route('import.job.configuration.index', [$importJob->key]));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,125 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class StatusController
|
||||
*/
|
||||
class StatusController extends Controller
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*/
|
||||
public function index(ImportJob $job)
|
||||
{
|
||||
$statuses = ['configured', 'running', 'finished', 'error'];
|
||||
if (!\in_array($job->status, $statuses)) {
|
||||
return redirect(route('import.configure', [$job->key]));
|
||||
}
|
||||
$subTitle = trans('import.status_sub_title');
|
||||
$subTitleIcon = 'fa-star';
|
||||
|
||||
return view('import.status', compact('job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show status of import job in JSON.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function json(ImportJob $job)
|
||||
{
|
||||
$result = [
|
||||
'started' => false,
|
||||
'finished' => false,
|
||||
'running' => false,
|
||||
'errors' => array_values($job->extended_status['errors']),
|
||||
'percentage' => 0,
|
||||
'show_percentage' => false,
|
||||
'steps' => $job->extended_status['steps'],
|
||||
'done' => $job->extended_status['done'],
|
||||
'statusText' => trans('import.status_job_' . $job->status),
|
||||
'status' => $job->status,
|
||||
'finishedText' => '',
|
||||
];
|
||||
|
||||
if (0 !== $job->extended_status['steps']) {
|
||||
$result['percentage'] = round(($job->extended_status['done'] / $job->extended_status['steps']) * 100, 0);
|
||||
$result['show_percentage'] = true;
|
||||
}
|
||||
if ('finished' === $job->status) {
|
||||
$result['finished'] = true;
|
||||
$tagId = (int)$job->extended_status['tag'];
|
||||
if ($tagId !== 0) {
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$tag = $repository->find($tagId);
|
||||
$count = $tag->transactionJournals()->count();
|
||||
$result['finishedText'] = trans(
|
||||
'import.status_finished_job', ['count' => $count, 'link' => route('tags.show', [$tag->id, 'all']), 'tag' => $tag->tag]
|
||||
);
|
||||
}
|
||||
|
||||
if ($tagId === 0) {
|
||||
$result['finishedText'] = trans('import.status_finished_no_tag'); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
if ('running' === $job->status) {
|
||||
$result['started'] = true;
|
||||
$result['running'] = true;
|
||||
}
|
||||
$result['percentage'] = $result['percentage'] > 100 ? 100 : $result['percentage'];
|
||||
Log::debug(sprintf('JOB STATUS: %d/%d', $result['done'], $result['steps']));
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Log;
|
||||
use Preferences;
|
||||
|
||||
@ -68,9 +69,9 @@ class JavascriptController extends Controller
|
||||
/**
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return Response
|
||||
*/
|
||||
public function currencies(CurrencyRepositoryInterface $repository)
|
||||
public function currencies(CurrencyRepositoryInterface $repository): Response
|
||||
{
|
||||
$currencies = $repository->get();
|
||||
$data = ['currencies' => []];
|
||||
@ -102,7 +103,8 @@ class JavascriptController extends Controller
|
||||
}
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $currencyRepository->findNull($currencyId);
|
||||
if (0 === $currencyId) {
|
||||
if (null === $currency) {
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class AutoCompleteController.
|
||||
@ -47,7 +48,7 @@ class AutoCompleteController extends Controller
|
||||
*
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function allAccounts(AccountRepositoryInterface $repository)
|
||||
{
|
||||
@ -64,9 +65,9 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* @param JournalCollectorInterface $collector
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function allTransactionJournals(JournalCollectorInterface $collector)
|
||||
public function allTransactionJournals(JournalCollectorInterface $collector): JsonResponse
|
||||
{
|
||||
$collector->setLimit(250)->setPage(1);
|
||||
$return = array_unique($collector->getJournals()->pluck('description')->toArray());
|
||||
@ -80,9 +81,9 @@ class AutoCompleteController extends Controller
|
||||
*
|
||||
* @param BillRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function bills(BillRepositoryInterface $repository)
|
||||
public function bills(BillRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$return = array_unique(
|
||||
$repository->getActiveBills()->pluck('name')->toArray()
|
||||
@ -95,7 +96,7 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function budgets(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
@ -110,7 +111,7 @@ class AutoCompleteController extends Controller
|
||||
*
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function categories(CategoryRepositoryInterface $repository)
|
||||
{
|
||||
@ -123,7 +124,7 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function currencyNames(CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
@ -138,7 +139,7 @@ class AutoCompleteController extends Controller
|
||||
*
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function expenseAccounts(AccountRepositoryInterface $repository)
|
||||
{
|
||||
@ -163,7 +164,7 @@ class AutoCompleteController extends Controller
|
||||
* @param JournalCollectorInterface $collector
|
||||
* @param TransactionJournal $except
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse|mixed
|
||||
* @return JsonResponse|mixed
|
||||
*/
|
||||
public function journalsWithId(JournalCollectorInterface $collector, TransactionJournal $except)
|
||||
{
|
||||
@ -195,7 +196,7 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function revenueAccounts(AccountRepositoryInterface $repository)
|
||||
{
|
||||
@ -220,7 +221,7 @@ class AutoCompleteController extends Controller
|
||||
*
|
||||
* @param TagRepositoryInterface $tagRepository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function tags(TagRepositoryInterface $tagRepository)
|
||||
{
|
||||
@ -234,7 +235,7 @@ class AutoCompleteController extends Controller
|
||||
* @param JournalCollectorInterface $collector
|
||||
* @param string $what
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactionJournals(JournalCollectorInterface $collector, string $what)
|
||||
{
|
||||
@ -251,7 +252,7 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* @param JournalRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactionTypes(JournalRepositoryInterface $repository)
|
||||
{
|
||||
|
@ -30,6 +30,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
@ -215,6 +216,7 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->piggyRepos->correctOrder();
|
||||
$collection = $this->piggyRepos->getPiggyBanks();
|
||||
$total = $collection->count();
|
||||
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||
@ -261,27 +263,6 @@ class PiggyBankController extends Controller
|
||||
return view('piggy-banks.index', compact('piggyBanks', 'accounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function order(Request $request)
|
||||
{
|
||||
$data = $request->get('order');
|
||||
|
||||
// set all users piggy banks to zero:
|
||||
$this->piggyRepos->reset();
|
||||
|
||||
if (\is_array($data)) {
|
||||
foreach ($data as $order => $id) {
|
||||
$this->piggyRepos->setOrder((int)$id, $order + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['result' => 'ok']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param PiggyBank $piggyBank
|
||||
@ -402,6 +383,20 @@ class PiggyBankController extends Controller
|
||||
return view('piggy-banks.remove-mobile', compact('piggyBank', 'repetition', 'currency'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$newOrder = (int)$request->get('order');
|
||||
$this->piggyRepos->setOrder($piggyBank, $newOrder);
|
||||
|
||||
return response()->json(['data' => 'OK']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
@ -409,11 +404,17 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function show(PiggyBank $piggyBank)
|
||||
{
|
||||
$note = $piggyBank->notes()->first();
|
||||
$events = $this->piggyRepos->getEvents($piggyBank);
|
||||
$subTitle = $piggyBank->name;
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Carbon::now()->endOfMonth());
|
||||
// transform piggies using the transformer:
|
||||
$parameters = new ParameterBag;
|
||||
$parameters->set('end', $end);
|
||||
$transformer = new PiggyBankTransformer(new ParameterBag);
|
||||
$piggy = $transformer->transform($piggyBank);
|
||||
$events = $this->piggyRepos->getEvents($piggyBank);
|
||||
$subTitle = $piggyBank->name;
|
||||
|
||||
return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle', 'note'));
|
||||
return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle', 'piggy'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,7 +424,7 @@ class ProfileController extends Controller
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function createOAuthKeys()
|
||||
private function createOAuthKeys(): void
|
||||
{
|
||||
$rsa = new RSA();
|
||||
$keys = $rsa->createKey(4096);
|
||||
@ -437,11 +437,13 @@ class ProfileController extends Controller
|
||||
if (file_exists($publicKey) || file_exists($privateKey)) {
|
||||
return;
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::alert('NO OAuth keys were found. They have been created.');
|
||||
|
||||
file_put_contents($publicKey, array_get($keys, 'publickey'));
|
||||
file_put_contents($privateKey, array_get($keys, 'privatekey'));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
/**
|
||||
* @return string
|
||||
|
@ -102,7 +102,6 @@ class RuleController extends Controller
|
||||
$preFilled = [
|
||||
'strict' => true,
|
||||
];
|
||||
$groups = ExpandedForm::makeSelectList($this->ruleGroupRepos->get());
|
||||
$oldTriggers = [];
|
||||
$oldActions = [];
|
||||
$returnToBill = false;
|
||||
@ -150,7 +149,7 @@ class RuleController extends Controller
|
||||
return view(
|
||||
'rules.rule.create',
|
||||
compact(
|
||||
'subTitleIcon', 'oldTriggers', 'returnToBill', 'groups', 'preFilled', 'bill', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroup',
|
||||
'subTitleIcon', 'oldTriggers', 'returnToBill', 'preFilled', 'bill', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroup',
|
||||
'subTitle'
|
||||
)
|
||||
);
|
||||
@ -212,7 +211,6 @@ class RuleController extends Controller
|
||||
*/
|
||||
public function edit(Request $request, Rule $rule)
|
||||
{
|
||||
$ruleGroups = ExpandedForm::makeSelectList($this->ruleGroupRepos->get());
|
||||
$triggerCount = 0;
|
||||
$actionCount = 0;
|
||||
$oldActions = [];
|
||||
@ -243,7 +241,7 @@ class RuleController extends Controller
|
||||
}
|
||||
session()->forget('rules.edit.fromUpdate');
|
||||
|
||||
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroups'));
|
||||
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -333,14 +331,11 @@ class RuleController extends Controller
|
||||
public function selectTransactions(Rule $rule)
|
||||
{
|
||||
// does the user have shared accounts?
|
||||
$accounts = $this->accountRepos->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'));
|
||||
return view('rules.rule.select-transactions', compact( 'first', 'today', 'rule', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,12 +352,12 @@ class RuleController extends Controller
|
||||
|
||||
// redirect to show bill.
|
||||
if ($request->get('return_to_bill') === 'true' && (int)$request->get('bill_id') > 0) {
|
||||
return redirect(route('bills.show', [(int)$request->get('bill_id')]));
|
||||
return redirect(route('bills.show', [(int)$request->get('bill_id')])); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// redirect to new bill creation.
|
||||
if ((int)$request->get('bill_id') > 0) {
|
||||
return redirect($this->getPreviousUri('bills.create.uri'));
|
||||
return redirect($this->getPreviousUri('bills.create.uri')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
||||
@ -408,10 +403,12 @@ class RuleController extends Controller
|
||||
$matcher->setTriggers($triggers);
|
||||
try {
|
||||
$matchingTransactions = $matcher->findTransactionsByTriggers();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (FireflyException $exception) {
|
||||
Log::error(sprintf('Could not grab transactions in testTriggers(): %s', $exception->getMessage()));
|
||||
Log::error($exception->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
|
||||
// Warn the user if only a subset of transactions is returned
|
||||
@ -427,10 +424,12 @@ class RuleController extends Controller
|
||||
$view = 'ERROR, see logs.';
|
||||
try {
|
||||
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $exception) {
|
||||
Log::error(sprintf('Could not render view in testTriggers(): %s', $exception->getMessage()));
|
||||
Log::error($exception->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return response()->json(['html' => $view, 'warning' => $warning]);
|
||||
}
|
||||
@ -466,10 +465,12 @@ class RuleController extends Controller
|
||||
$matcher->setRule($rule);
|
||||
try {
|
||||
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (FireflyException $exception) {
|
||||
Log::error(sprintf('Could not grab transactions in testTriggersByRule(): %s', $exception->getMessage()));
|
||||
Log::error($exception->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// Warn the user if only a subset of transactions is returned
|
||||
$warning = '';
|
||||
@ -484,10 +485,12 @@ class RuleController extends Controller
|
||||
$view = 'ERROR, see logs.';
|
||||
try {
|
||||
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $exception) {
|
||||
Log::error(sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage()));
|
||||
Log::error($exception->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return response()->json(['html' => $view, 'warning' => $warning]);
|
||||
}
|
||||
@ -592,10 +595,12 @@ class RuleController extends Controller
|
||||
'count' => 1,
|
||||
]
|
||||
)->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $e) {
|
||||
Log::error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $actions;
|
||||
}
|
||||
@ -625,10 +630,12 @@ class RuleController extends Controller
|
||||
'count' => $count,
|
||||
]
|
||||
)->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $e) {
|
||||
Log::debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
++$index;
|
||||
}
|
||||
|
||||
@ -660,10 +667,12 @@ class RuleController extends Controller
|
||||
'count' => $count,
|
||||
]
|
||||
)->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $e) {
|
||||
Log::debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
++$index;
|
||||
}
|
||||
}
|
||||
@ -696,10 +705,12 @@ class RuleController extends Controller
|
||||
'count' => $count,
|
||||
]
|
||||
)->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $e) {
|
||||
Log::debug(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
++$newIndex;
|
||||
}
|
||||
|
||||
@ -732,10 +743,12 @@ class RuleController extends Controller
|
||||
'count' => $count,
|
||||
]
|
||||
)->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $e) {
|
||||
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
++$newIndex;
|
||||
}
|
||||
|
||||
@ -791,10 +804,12 @@ class RuleController extends Controller
|
||||
'count' => 4,
|
||||
]
|
||||
)->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $e) {
|
||||
Log::debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
|
||||
Log::debug($e->getTraceAsString());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $triggers;
|
||||
}
|
||||
|
@ -23,11 +23,9 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Http\Requests\RuleGroupFormRequest;
|
||||
use FireflyIII\Http\Requests\SelectTransactionsRequest;
|
||||
use FireflyIII\Jobs\ExecuteRuleGroupOnExistingTransactions;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
@ -75,22 +73,18 @@ class RuleGroupController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RuleGroupRepositoryInterface $repository
|
||||
* @param RuleGroup $ruleGroup
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||
public function delete(RuleGroup $ruleGroup)
|
||||
{
|
||||
$subTitle = trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]);
|
||||
|
||||
$ruleGroupList = ExpandedForm::makeSelectListWithEmpty($repository->get());
|
||||
unset($ruleGroupList[$ruleGroup->id]);
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('rule-groups.delete.uri');
|
||||
|
||||
return view('rules.rule-group.delete', compact('ruleGroup', 'subTitle', 'ruleGroupList'));
|
||||
return view('rules.rule-group.delete', compact('ruleGroup', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,11 +129,17 @@ class RuleGroupController extends Controller
|
||||
{
|
||||
$subTitle = trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]);
|
||||
|
||||
$preFilled = [
|
||||
'active' => $ruleGroup->active,
|
||||
];
|
||||
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('rule-groups.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUri('rule-groups.edit.uri');
|
||||
}
|
||||
session()->forget('rule-groups.edit.fromUpdate');
|
||||
session()->flash('preFilled', $preFilled);
|
||||
|
||||
return view('rules.rule-group.edit', compact('ruleGroup', 'subTitle'));
|
||||
}
|
||||
@ -179,22 +179,17 @@ class RuleGroupController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountRepositoryInterface $repository
|
||||
* @param RuleGroup $ruleGroup
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function selectTransactions(AccountRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||
public function selectTransactions(RuleGroup $ruleGroup)
|
||||
{
|
||||
// does the user have shared accounts?
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, 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_group_selection', ['title' => $ruleGroup->title]);
|
||||
$first = session('first')->format('Y-m-d');
|
||||
$today = Carbon::create()->format('Y-m-d');
|
||||
$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('first', 'today', 'ruleGroup', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,6 +33,7 @@ use Log;
|
||||
use phpseclib\Crypt\RSA;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class InstallController
|
||||
*/
|
||||
class InstallController extends Controller
|
||||
|
@ -31,19 +31,10 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class TagController.
|
||||
*
|
||||
* Remember: a balancingAct takes at most one expense and one transfer.
|
||||
* an advancePayment takes at most one expense, infinite deposits and NO transfers.
|
||||
*
|
||||
* transaction can only have one advancePayment OR balancingAct.
|
||||
* Other attempts to put in such a tag are blocked.
|
||||
* also show an error when editing a tag and it becomes either
|
||||
* of these two types. Or rather, block editing of the tag.
|
||||
*/
|
||||
class TagController extends Controller
|
||||
{
|
||||
@ -79,7 +70,6 @@ class TagController extends Controller
|
||||
{
|
||||
$subTitle = trans('firefly.new_tag');
|
||||
$subTitleIcon = 'fa-tag';
|
||||
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (true !== session('tags.create.fromStore')) {
|
||||
@ -87,7 +77,7 @@ class TagController extends Controller
|
||||
}
|
||||
session()->forget('tags.create.fromStore');
|
||||
|
||||
return view('tags.create', compact('subTitle', 'subTitleIcon', 'apiKey'));
|
||||
return view('tags.create', compact('subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,7 +108,7 @@ class TagController extends Controller
|
||||
$this->repository->destroy($tag);
|
||||
|
||||
session()->flash('success', (string)trans('firefly.deleted_tag', ['tag' => $tagName]));
|
||||
Preferences::mark();
|
||||
app('preferences')->mark();
|
||||
|
||||
return redirect($this->getPreviousUri('tags.delete.uri'));
|
||||
}
|
||||
@ -134,7 +124,6 @@ class TagController extends Controller
|
||||
{
|
||||
$subTitle = trans('firefly.edit_tag', ['tag' => $tag->tag]);
|
||||
$subTitleIcon = 'fa-tag';
|
||||
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('tags.edit.fromUpdate')) {
|
||||
@ -142,7 +131,7 @@ class TagController extends Controller
|
||||
}
|
||||
session()->forget('tags.edit.fromUpdate');
|
||||
|
||||
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'apiKey'));
|
||||
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,27 +144,18 @@ class TagController extends Controller
|
||||
public function index(TagRepositoryInterface $repository)
|
||||
{
|
||||
// start with oldest tag
|
||||
$oldestTag = $repository->oldestTag();
|
||||
/** @var Carbon $start */
|
||||
$start = new Carbon;
|
||||
if (null !== $oldestTag) {
|
||||
/** @var Carbon $start */
|
||||
$start = $oldestTag->date; // @codeCoverageIgnore
|
||||
}
|
||||
if (null === $oldestTag) {
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('first');
|
||||
}
|
||||
|
||||
$now = new Carbon;
|
||||
$oldestTagDate = null === $repository->oldestTag() ? clone session('first') : $repository->oldestTag()->date;
|
||||
$newestTagDate = null === $repository->newestTag() ? new Carbon : $repository->newestTag()->date;
|
||||
$oldestTagDate->startOfYear();
|
||||
$newestTagDate->endOfYear();
|
||||
$clouds = [];
|
||||
$clouds['no-date'] = $repository->tagCloud(null);
|
||||
|
||||
while ($now > $start) {
|
||||
$year = $now->year;
|
||||
while ($newestTagDate > $oldestTagDate) {
|
||||
$year = $newestTagDate->year;
|
||||
$clouds[$year] = $repository->tagCloud($year);
|
||||
|
||||
$now->subYear();
|
||||
$newestTagDate->subYear();
|
||||
}
|
||||
$count = $repository->count();
|
||||
|
||||
@ -196,12 +176,11 @@ class TagController extends Controller
|
||||
$subTitle = $tag->tag;
|
||||
$subTitleIcon = 'fa-tag';
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||
$range = app('preferences')->get('viewRange', '1M')->data;
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
|
||||
$path = route('tags.show', [$tag->id]);
|
||||
|
||||
// prep for "all" view.
|
||||
@ -213,7 +192,7 @@ class TagController extends Controller
|
||||
}
|
||||
|
||||
// prep for "specific date" view.
|
||||
if (\strlen($moment) > 0 && 'all' !== $moment) {
|
||||
if ('all' !== $moment && \strlen($moment) > 0) {
|
||||
$start = new Carbon($moment);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
@ -226,7 +205,7 @@ class TagController extends Controller
|
||||
}
|
||||
|
||||
// prep for current period
|
||||
if (0 === \strlen($moment)) {
|
||||
if ('' === $moment) {
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||
/** @var Carbon $end */
|
||||
@ -261,7 +240,7 @@ class TagController extends Controller
|
||||
$this->repository->store($data);
|
||||
|
||||
session()->flash('success', (string)trans('firefly.created_tag', ['tag' => $data['tag']]));
|
||||
Preferences::mark();
|
||||
app('preferences')->mark();
|
||||
|
||||
if (1 === (int)$request->get('create_another')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
@ -286,7 +265,7 @@ class TagController extends Controller
|
||||
$this->repository->update($tag, $data);
|
||||
|
||||
session()->flash('success', (string)trans('firefly.updated_tag', ['tag' => $data['tag']]));
|
||||
Preferences::mark();
|
||||
app('preferences')->mark();
|
||||
|
||||
if (1 === (int)$request->get('return_to_edit')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
@ -308,9 +287,11 @@ class TagController extends Controller
|
||||
private function getPeriodOverview(Tag $tag): Collection
|
||||
{
|
||||
// get first and last tag date from tag:
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = app('navigation')->startOfPeriod($this->repository->firstUseDate($tag), $range);
|
||||
$end = app('navigation')->startOfPeriod($this->repository->lastUseDate($tag), $range);
|
||||
$range = app('preferences')->get('viewRange', '1M')->data;
|
||||
$end = app('navigation')->endOfX($this->repository->lastUseDate($tag), $range, null);
|
||||
$start = $this->repository->firstUseDate($tag);
|
||||
|
||||
|
||||
// properties for entries with their amounts.
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
@ -323,22 +304,23 @@ class TagController extends Controller
|
||||
}
|
||||
|
||||
$collection = new Collection;
|
||||
|
||||
$currentEnd = clone $end;
|
||||
// while end larger or equal to start
|
||||
while ($end >= $start) {
|
||||
$currentEnd = app('navigation')->endOfPeriod($end, $range);
|
||||
while ($currentEnd >= $start) {
|
||||
$currentStart = app('navigation')->startOfPeriod($currentEnd, $range);
|
||||
|
||||
// get expenses and what-not in this period and this tag.
|
||||
$arr = [
|
||||
'string' => $end->format('Y-m-d'),
|
||||
'name' => app('navigation')->periodShow($end, $range),
|
||||
'name' => app('navigation')->periodShow($currentEnd, $range),
|
||||
'date' => clone $end,
|
||||
'spent' => $this->repository->spentInPeriod($tag, $end, $currentEnd),
|
||||
'earned' => $this->repository->earnedInPeriod($tag, $end, $currentEnd),
|
||||
'spent' => $this->repository->spentInPeriod($tag, $currentStart, $currentEnd),
|
||||
'earned' => $this->repository->earnedInPeriod($tag, $currentStart, $currentEnd),
|
||||
];
|
||||
$collection->push($arr);
|
||||
|
||||
$end = app('navigation')->subtractPeriod($end, $range, 1);
|
||||
$currentEnd = clone $currentStart;
|
||||
$currentEnd->subDay();
|
||||
}
|
||||
$cache->store($collection);
|
||||
|
||||
|
@ -107,7 +107,7 @@ class LinkController extends Controller
|
||||
|
||||
return redirect(route('transactions.show', [$journal->id]));
|
||||
}
|
||||
$other = $this->journalRepository->find($linkInfo['transaction_journal_id']);
|
||||
$other = $this->journalRepository->findNull($linkInfo['transaction_journal_id']);
|
||||
$alreadyLinked = $this->repository->findLink($journal, $other);
|
||||
|
||||
if ($other->id === $journal->id) {
|
||||
|
@ -25,6 +25,7 @@ namespace FireflyIII\Http\Controllers\Transaction;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\NegativeAmountFilter;
|
||||
use FireflyIII\Helpers\Filter\TransactionViewFilter;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
|
||||
use FireflyIII\Http\Requests\MassEditJournalRequest;
|
||||
@ -145,22 +146,24 @@ class MassController extends Controller
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setJournals($journals);
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
$transactions = $collector->getJournals();
|
||||
$collector->addFilter(TransactionViewFilter::class);
|
||||
$collection = $collector->getJournals();
|
||||
|
||||
// add some filters:
|
||||
|
||||
|
||||
// transform to array
|
||||
$journals = $transactions->map(
|
||||
$transactions = $collection->map(
|
||||
function (Transaction $transaction) use ($transformer) {
|
||||
$result = $transformer->transform($transaction);
|
||||
|
||||
return $result;
|
||||
$transaction= $transformer->transform($transaction);
|
||||
// make sure amount is positive:
|
||||
$transaction['amount'] = app('steam')->positive((string)$transaction['amount']);
|
||||
$transaction['foreign_amount'] = app('steam')->positive((string)$transaction['foreign_amount']);
|
||||
return $transaction;
|
||||
}
|
||||
);
|
||||
|
||||
return view('transactions.mass.edit', compact('journals', 'subTitle', 'accounts', 'budgets'));
|
||||
return view('transactions.mass.edit', compact('transactions', 'subTitle', 'accounts', 'budgets'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,8 +29,6 @@ use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\SplitJournalFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
@ -100,22 +98,18 @@ class SplitController extends Controller
|
||||
if ($this->isOpeningBalance($journal)) {
|
||||
return $this->redirectToAccount($journal); // @codeCoverageIgnore
|
||||
}
|
||||
// basic fields:
|
||||
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
|
||||
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
|
||||
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
|
||||
$currencies = $this->currencies->get();
|
||||
// lists and collections
|
||||
$currencies = $this->currencies->get();
|
||||
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
|
||||
|
||||
// other fields
|
||||
$optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
|
||||
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
|
||||
$preFilled = $this->arrayFromJournal($request, $journal);
|
||||
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
$accountList = $this->accounts->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
||||
$accountArray = [];
|
||||
// account array to display currency info:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$accountArray[$account->id] = $account;
|
||||
$accountArray[$account->id]['currency_id'] = (int)$this->accounts->getMetaValue($account, 'currency_id');
|
||||
}
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('transactions.edit-split.fromUpdate')) {
|
||||
@ -126,7 +120,7 @@ class SplitController extends Controller
|
||||
return view(
|
||||
'transactions.split.edit', compact(
|
||||
'subTitleIcon', 'currencies', 'optionalFields', 'preFilled', 'subTitle', 'uploadSize', 'budgets',
|
||||
'journal', 'accountArray'
|
||||
'journal'
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -146,8 +140,7 @@ class SplitController extends Controller
|
||||
|
||||
// keep current bill:
|
||||
$data['bill_id'] = $journal->bill_id;
|
||||
|
||||
$journal = $this->repository->update($journal, $data);
|
||||
$journal = $this->repository->update($journal, $data);
|
||||
|
||||
/** @var array $files */
|
||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||
@ -283,9 +276,9 @@ class SplitController extends Controller
|
||||
}
|
||||
// take some info from first transaction, that should at least exist.
|
||||
$array[$index] = $row;
|
||||
$array[$index]['currency_id'] = $array[0]['transaction_currency_id'];
|
||||
$array[$index]['currency_code'] = $array[0]['transaction_currency_code'] ?? '';
|
||||
$array[$index]['currency_symbol'] = $array[0]['transaction_currency_symbol'] ?? '';
|
||||
$array[$index]['currency_id'] = $array[0]['currency_id'];
|
||||
$array[$index]['currency_code'] = $array[0]['currency_code'] ?? '';
|
||||
$array[$index]['currency_symbol'] = $array[0]['currency_symbol'] ?? '';
|
||||
$array[$index]['foreign_amount'] = round($array[0]['foreign_destination_amount'] ?? '0', 12);
|
||||
$array[$index]['foreign_currency_id'] = $array[0]['foreign_currency_id'];
|
||||
$array[$index]['foreign_currency_code'] = $array[0]['foreign_currency_code'];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user