Merge branch 'release/4.7.7'

This commit is contained in:
James Cole
2018-09-29 12:27:03 +02:00
296 changed files with 11127 additions and 1520 deletions

View File

@@ -12,6 +12,9 @@ I am running Firefly III version x.x.x
**Steps to reproduce**
What do you need to do to trigger this bug?
**Expected behavior**
What do you expect to see after those steps?
**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).
@@ -19,4 +22,4 @@ Please add extra info here, such as OS, browser, and the output from the /debug
Earn bonus points by:
- Post a stacktrace from your log files
- Add a screenshot
- Add a screenshot

View File

@@ -1,3 +1,44 @@
# 4.7.7
- [Issue 954](https://github.com/firefly-iii/firefly-iii/issues/954) Some additional view chart ranges
- [Issue 1710](https://github.com/firefly-iii/firefly-iii/issues/1710) Added a new currency ([hamuz](https://github.com/hamuz))
- Transactions will now store (in the database) how they were created.
- [Issue 907](https://github.com/firefly-iii/firefly-iii/issues/907) Better and more options on the transaction list.
- [Issue 1450](https://github.com/firefly-iii/firefly-iii/issues/1450) Add a rule to change the type of a transaction automagically
- [Issue 1701](https://github.com/firefly-iii/firefly-iii/issues/1701) Fix reference to PHP executable ([hertzg](https://github.com/hertzg))
- Budget limits have currency information, for future expansion.
- Some charts and pages can handle multiple currencies better.
- New GA code for those who use it.
- The credit card liability type has been removed.
- [Issue 896](https://github.com/firefly-iii/firefly-iii/issues/896) Better redirection when coming from deleted objects.
- [Issue 1519](https://github.com/firefly-iii/firefly-iii/issues/1519) Fix autocomplete tags
- [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Some fixes for the bunq api calls
- [Issue 1650](https://github.com/firefly-iii/firefly-iii/issues/1650) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz))
- [Issue 1658](https://github.com/firefly-iii/firefly-iii/issues/1658) Make font heavy again.
- [Issue 1660](https://github.com/firefly-iii/firefly-iii/issues/1660) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz))
- [Issue 1667](https://github.com/firefly-iii/firefly-iii/issues/1667) Fix pie charts
- [Issue 1668](https://github.com/firefly-iii/firefly-iii/issues/1668) YNAB iso_code fix
- [Issue 1670](https://github.com/firefly-iii/firefly-iii/issues/1670) Fix piggy bank API error
- [Issue 1671](https://github.com/firefly-iii/firefly-iii/issues/1671) More options for liability accounts.
- [Issue 1673](https://github.com/firefly-iii/firefly-iii/issues/1673) Fix reconciliation issues.
- [Issue 1675](https://github.com/firefly-iii/firefly-iii/issues/1675) Wrong sum in tag report.
- [Issue 1679](https://github.com/firefly-iii/firefly-iii/issues/1679) Change type of a transaction wouldn't trigger rules.
- [Issue 1682](https://github.com/firefly-iii/firefly-iii/issues/1682) Add liability accounts to transaction conversion
- [Issue 1683](https://github.com/firefly-iii/firefly-iii/issues/1683) See matching transaction showed transfers twice.
- [Issue 1685](https://github.com/firefly-iii/firefly-iii/issues/1685) fix autocomplete for rules
- [Issue 1690](https://github.com/firefly-iii/firefly-iii/issues/1690) Missing highlighted button in intro popup
- [Issue 1691](https://github.com/firefly-iii/firefly-iii/issues/1691) No mention of liabilities in demo text
- [Issue 1695](https://github.com/firefly-iii/firefly-iii/issues/1695) Small fixes in bills pages.
- [Issue 1708](https://github.com/firefly-iii/firefly-iii/issues/1708) Fix by [mathieupost](https://github.com/mathieupost) for bunq
- [Issue 1709](https://github.com/firefly-iii/firefly-iii/issues/1709) Fix oauth buttons
- [Issue 1712](https://github.com/firefly-iii/firefly-iii/issues/1712) Double slash fix by [hamuz](https://github.com/hamuz)
- [Issue 1719](https://github.com/firefly-iii/firefly-iii/issues/1719) Add missing accounts to API
- [Issue 1720](https://github.com/firefly-iii/firefly-iii/issues/1720) Fix validation for transaction type.
- [Issue 1723](https://github.com/firefly-iii/firefly-iii/issues/1723) API broken for currency exchange rates.
- [Issue 1728](https://github.com/firefly-iii/firefly-iii/issues/1728) Fix problem with transaction factory.
- [Issue 1729](https://github.com/firefly-iii/firefly-iii/issues/1729) Fix bulk transaction editor
- [Issue 1731](https://github.com/firefly-iii/firefly-iii/issues/1731) API failure for budget limits.
- Secure headers now allow Mapbox and the 2FA QR code.
# 4.7.6.2
- Docker file builds again.
- Fix CSS of OAuth2 authorization view.
@@ -44,11 +85,12 @@
- [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku.
- [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals.
- [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue.
- Users can no longer give expenses a budget.
- Users can no longer give income a budget.
- Fix bug in Spectre import.
- Heroku would not make you owner.
- Add `.htaccess` files to all public directories.
- New secure headers will make Firefly III slightly more secure.
- The rule "tester" will now also take the "strict"-checkbox into account.
# 4.7.5.3
- [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget.

View File

@@ -37,15 +37,15 @@ HOME=/etc/mysql /usr/bin/mysql_install_db --force
# Spawn mysqld, php
HOME=/etc/mysql /usr/sbin/mysqld &
/usr/sbin/php-fpm7.1 --nodaemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf &
/usr/sbin/php-fpm7.2 --nodaemonize --fpm-config /etc/php/7.2/fpm/php-fpm.conf &
# Wait until mysql and php have bound their sockets, indicating readiness
while [ ! -e /var/run/mysqld/mysqld.sock ] ; do
echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock"
sleep .5
done
while [ ! -e /var/run/php7.1-fpm.sock ] ; do
echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock"
while [ ! -e /var/run/php7.2-fpm.sock ] ; do
echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock"
sleep .5
done

File diff suppressed because it is too large Load Diff

View File

@@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
manifest = (
appTitle = (defaultText = "Firefly III"),
appVersion = 16,
appMarketingVersion = (defaultText = "4.7.6.2"),
appVersion = 17,
appMarketingVersion = (defaultText = "4.7.7"),
actions = [
# Define your "new document" handlers here.

View File

@@ -53,7 +53,7 @@ http {
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php7.1-fpm.sock;
fastcgi_pass unix:/var/run/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

View File

@@ -38,37 +38,37 @@ echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sou
# install packages.
apt-get update
apt-get install -y nginx php7.1-fpm php7.1-mysql php7.1-gd php7.1-cli php7.1-curl git php7.1-dev php7.1-zip php7.1-intl php7.1-dom php7.1-mbstring php7.1-bcmath mysql-server
apt-get install -y nginx php7.2-fpm php7.2-mysql php7.2-gd php7.2-cli php7.2-curl git php7.2-dev php7.2-zip php7.2-intl php7.2-dom php7.2-mbstring php7.2-bcmath mysql-server
service nginx stop
service php7.1-fpm stop
service php7.2-fpm stop
service mysql stop
systemctl disable nginx
systemctl disable php7.1-fpm
systemctl disable php7.2-fpm
systemctl disable mysql
# make php.ini display errors:
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.1/fpm/php.ini
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.2/fpm/php.ini
# patch /etc/php/7.1/fpm/pool.d/www.conf to not change uid/gid to www-data
# patch /etc/php/7.2/fpm/pool.d/www.conf to not change uid/gid to www-data
sed --in-place='' \
--expression='s/^listen.owner = www-data/;listen.owner = www-data/' \
--expression='s/^listen.group = www-data/;listen.group = www-data/' \
/etc/php/7.1/fpm/pool.d/www.conf
# patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile
/etc/php/7.2/fpm/pool.d/www.conf
# patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile
sed --in-place='' \
--expression='s/^pid =/;pid =/' \
/etc/php/7.1/fpm/php-fpm.conf
/etc/php/7.2/fpm/php-fpm.conf
# move sock file to better dir:
sed --in-place='' \
--expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \
/etc/php/7.1/fpm/pool.d/www.conf
--expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \
/etc/php/7.2/fpm/pool.d/www.conf
# patch /etc/php/7.1/fpm/pool.d/www.conf to no clear environment variables
# patch /etc/php/7.2/fpm/pool.d/www.conf to no clear environment variables
# so we can pass in SANDSTORM=1 to apps
sed --in-place='' \
--expression='s/^;clear_env = no/clear_env=no/' \
/etc/php/7.1/fpm/pool.d/www.conf
/etc/php/7.2/fpm/pool.d/www.conf
# patch mysql conf to not change uid, and to use /var/tmp over /tmp
# for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195
sed --in-place='' \

View File

@@ -1,6 +1,6 @@
language: php
php:
- 7.1.18
- 7.2
cache:
directories:

View File

@@ -1,4 +1,4 @@
FROM php:7.1-apache
FROM php:7.2-apache
# If building on a RPi, use --build-arg cores=3 to use all cores when compiling
# to speed up the image build

View File

@@ -213,14 +213,13 @@ class AccountController extends Controller
$types = [
'all' => [AccountType::DEFAULT, AccountType::CASH, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE,
AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION,
AccountType::LOAN,],
AccountType::LOAN,AccountType::DEBT, AccountType::MORTGAGE],
'asset' => [AccountType::DEFAULT, AccountType::ASSET,],
'cash' => [AccountType::CASH,],
'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY,],
'revenue' => [AccountType::REVENUE,],
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,
AccountType::LOAN,],
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, AccountType::LOAN,],
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,],
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION],
'liability' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
'liabilities' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
'cc' => [AccountType::CREDITCARD],

View File

@@ -25,6 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\TransactionRequest;
use FireflyIII\Events\StoredTransactionJournal;
use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Helpers\Filter\InternalTransferFilter;
@@ -192,6 +194,8 @@ class TransactionController extends Controller
$data['user'] = auth()->user()->id;
$journal = $repository->store($data);
event(new StoredTransactionJournal($journal, 0));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
@@ -241,6 +245,8 @@ class TransactionController extends Controller
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
event(new UpdatedTransactionJournal($journal));
// add include parameter:
$include = $request->get('include') ?? '';
$manager->parseIncludes($include);

View File

@@ -50,14 +50,17 @@ class PiggyBankRequest extends Request
*/
public function getAll(): array
{
$current = $this->string('current_amount');
$current = '' === $current ? '0' : $current;
return [
'name' => $this->string('name'),
'account_id' => $this->integer('account_id'),
'targetamount' => $this->string('target_amount'),
'current_amount' => $this->string('current_amount'),
'current_amount' => $current,
'start_date' => $this->date('start_date'),
'target_date' => $this->date('target_date'),
'notes' => $this->string('notes'),
'notes' => $this->string('notes'),
];
}
@@ -74,7 +77,7 @@ class PiggyBankRequest extends Request
'target_amount' => 'required|numeric|more:0',
'current_amount' => 'numeric|more:0|lte:target_amount',
'start_date' => 'date|nullable',
'target_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
];

View File

@@ -73,6 +73,7 @@ class TransactionRequest extends Request
'invoice_date' => $this->date('invoice_date'),
'internal_reference' => $this->string('internal_reference'),
'notes' => $this->string('notes'),
'original-source' => sprintf('api-v%s', config('firefly.api_version')),
'transactions' => $this->getTransactionData(),
];

View File

@@ -35,6 +35,7 @@ use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Bill;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\Note;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Rule;
@@ -63,6 +64,7 @@ use UnexpectedValueException;
* Upgrade user database.
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*
* @codeCoverageIgnore
*/
class UpgradeDatabase extends Command
@@ -95,6 +97,8 @@ class UpgradeDatabase extends Command
$this->migrateNotes();
$this->migrateAttachmentData();
$this->migrateBillsToRules();
$this->budgetLimitCurrency();
$this->removeCCLiabilities();
$this->info('Firefly III database is up to date.');
@@ -435,6 +439,31 @@ class UpgradeDatabase extends Command
);
}
/**
*
*/
private function budgetLimitCurrency(): void
{
$budgetLimits = BudgetLimit::get();
/** @var BudgetLimit $budgetLimit */
foreach ($budgetLimits as $budgetLimit) {
if (null === $budgetLimit->transaction_currency_id) {
$budget = $budgetLimit->budget;
if (null !== $budget) {
$user = $budget->user;
if (null !== $user) {
$currency = \Amount::getDefaultCurrencyByUser($user);
$budgetLimit->transaction_currency_id = $currency->id;
$budgetLimit->save();
$this->line(
sprintf('Budget limit #%d (part of budget "%s") now has a currency setting (%s).', $budgetLimit->id, $budget->name, $currency->name)
);
}
}
}
}
}
private function createNewTypes(): void
{
// create transaction type "Reconciliation".
@@ -507,6 +536,28 @@ class UpgradeDatabase extends Command
}
}
/**
*
*/
private function removeCCLiabilities(): void
{
$ccType = AccountType::where('type', AccountType::CREDITCARD)->first();
$debtType =AccountType::where('type', AccountType::DEBT)->first();
if(null === $ccType || null === $debtType) {
return;
}
/** @var Collection $accounts */
$accounts = Account::where('account_type_id', $ccType->id)->get();
foreach($accounts as $account) {
$account->account_type_id = $debtType->id;
$account->save();
$this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id));
}
if($accounts->count() > 0) {
$this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards');
}
}
/**
* This method makes sure that the transaction journal uses the currency given in the transaction.
*

View File

@@ -41,10 +41,21 @@ use Log;
*/
class AccountFactory
{
use AccountServiceTrait;
/** @var User */
private $user;
use AccountServiceTrait;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param array $data
*
@@ -141,17 +152,23 @@ class AccountFactory
*/
public function findOrCreate(string $accountName, string $accountType): Account
{
Log::debug(sprintf('Searching for "%s" of type "%s"', $accountName, $accountType));
$type = AccountType::whereType($accountType)->first();
$accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']);
$return = null;
Log::debug(sprintf('Account type is #%d', $type->id));
/** @var Account $object */
foreach ($accounts as $object) {
if ($object->name === $accountName) {
Log::debug(sprintf('Found account #%d "%s".', $object->id, $object->name));
$return = $object;
break;
}
}
if (null === $return) {
Log::debug('Found nothing. Will create a new one.');
$return = $this->create(
[
'user_id' => $this->user->id,

View File

@@ -34,7 +34,15 @@ use Log;
*/
class AccountMetaFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param array $data
*

View File

@@ -26,12 +26,22 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Note;
use FireflyIII\User;
use Log;
/**
* Class AttachmentFactory
*/
class AttachmentFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var User */
private $user;

View File

@@ -36,6 +36,16 @@ use Log;
*/
class BillFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
use BillServiceTrait;
/** @var User */
private $user;

View File

@@ -27,12 +27,23 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\Budget;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
/**
* Class BudgetFactory.
*/
class BudgetFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var User */
private $user;

View File

@@ -34,6 +34,16 @@ use Log;
*/
class CategoryFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var User */
private $user;

View File

@@ -37,6 +37,16 @@ use Log;
*/
class PiggyBankEventFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param TransactionJournal $journal
* @param PiggyBank|null $piggyBank

View File

@@ -26,12 +26,23 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\PiggyBank;
use FireflyIII\User;
use Log;
/**
* Class PiggyBankFactory
*/
class PiggyBankFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var User */
private $user;

View File

@@ -39,6 +39,16 @@ use Log;
*/
class RecurrenceFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
use TransactionTypeTrait, TransactionServiceTrait, RecurringTransactionTrait;
/** @var User */

View File

@@ -27,12 +27,23 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\Tag;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
/**
* Class TagFactory
*/
class TagFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var Collection */
private $tags;
/** @var User */

View File

@@ -36,6 +36,16 @@ use Log;
*/
class TransactionCurrencyFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param array $data
*

View File

@@ -40,6 +40,16 @@ use Log;
*/
class TransactionFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
use TransactionServiceTrait;
/** @var User */
@@ -98,6 +108,7 @@ class TransactionFactory
{
Log::debug('Start of TransactionFactory::createPair()', $data);
// all this data is the same for both transactions:
Log::debug('Searching for currency info.');
$currency = $this->findCurrency($data['currency_id'], $data['currency_code']);
$description = $journal->description === $data['description'] ? null : $data['description'];
@@ -154,6 +165,7 @@ class TransactionFactory
}
// set foreign currency
Log::debug('Trying to find foreign currency information.');
$foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']);
$this->setForeignCurrency($source, $foreign);
$this->setForeignCurrency($dest, $foreign);

View File

@@ -36,10 +36,21 @@ use Log;
*/
class TransactionJournalFactory
{
use JournalServiceTrait, TransactionTypeTrait;
/** @var User The user */
private $user;
use JournalServiceTrait, TransactionTypeTrait;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Store a new transaction journal.
*
@@ -57,13 +68,15 @@ class TransactionJournalFactory
$type = $this->findTransactionType($data['type']);
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
Log::debug(sprintf('Going to store a %s', $type->type));
$journal = TransactionJournal::create(
$description = app('steam')->cleanString($data['description']);
$description = str_replace(["\n", "\t", "\r"], "\x20", $description);
$journal = TransactionJournal::create(
[
'user_id' => $data['user'],
'transaction_type_id' => $type->id,
'bill_id' => null,
'transaction_currency_id' => $defaultCurrency->id,
'description' => $data['description'],
'description' => $description,
'date' => $data['date']->format('Y-m-d'),
'order' => 0,
'tag_count' => 0,
@@ -104,7 +117,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', 'recurrence_id', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash', 'importHashV2',
'external_id', 'sepa-batch-id'];
'external_id', 'sepa-batch-id', 'original-source'];
foreach ($fields as $field) {
$this->storeMeta($journal, $data, $field);

View File

@@ -34,6 +34,16 @@ use Log;
*/
class TransactionJournalMetaFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param array $data
*

View File

@@ -26,12 +26,22 @@ declare(strict_types=1);
namespace FireflyIII\Factory;
use FireflyIII\Models\TransactionType;
use Log;
/**
* Class TransactionTypeFactory
*/
class TransactionTypeFactory
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param string $type
*

View File

@@ -23,12 +23,22 @@ declare(strict_types=1);
namespace FireflyIII\Generator\Chart\Basic;
use FireflyIII\Support\ChartColour;
use Log;
/**
* Class ChartJsGenerator.
*/
class ChartJsGenerator implements GeneratorInterface
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Will generate a Chart JS compatible array from the given input. Expects this format.
*

View File

@@ -42,6 +42,7 @@ use Throwable;
/**
* Class MonthReportGenerator.
*
* @codeCoverageIgnore
*/
class MonthReportGenerator extends Support implements ReportGeneratorInterface
@@ -66,6 +67,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
{
$this->expenses = new Collection;
$this->income = new Collection;
$this->tags = new Collection;
}
/**
@@ -218,8 +220,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
$collector->addFilter(OpposingAccountFilter::class);
$collector->addFilter(PositiveAmountFilter::class);
$transactions = $collector->getTransactions();
$transactions = $collector->getTransactions();
$this->expenses = $transactions;
return $transactions;
@@ -260,6 +261,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
*/
protected function summarizeByTag(Collection $collection): array
{
$tagIds = array_map('\intval', $this->tags->pluck('id')->toArray());
$result = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
@@ -267,9 +269,11 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
$journalTags = $journal->tags;
/** @var Tag $journalTag */
foreach ($journalTags as $journalTag) {
$journalTagId = $journalTag->id;
$result[$journalTagId] = $result[$journalTagId] ?? '0';
$result[$journalTagId] = bcadd($transaction->transaction_amount, $result[$journalTagId]);
$journalTagId = (int)$journalTag->id;
if (\in_array($journalTagId, $tagIds, true)) {
$result[$journalTagId] = $result[$journalTagId] ?? '0';
$result[$journalTagId] = bcadd($transaction->transaction_amount, $result[$journalTagId]);
}
}
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Attachments;
use Crypt;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Attachment;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Eloquent\Model;
@@ -63,8 +64,13 @@ class AttachmentHelper implements AttachmentHelperInterface
$this->messages = new MessageBag;
$this->attachments = new Collection;
$this->uploadDisk = Storage::disk('upload');
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Returns the content of an attachment.
*
@@ -177,13 +183,17 @@ class AttachmentHelper implements AttachmentHelperInterface
/**
* Save attachments that get uploaded with models, through the app.
*
* @param Model $model
* @param object $model
* @param array|null $files
*
* @return bool
* @throws \Illuminate\Contracts\Encryption\EncryptException
*/
public function saveAttachmentsForModel(Model $model, ?array $files): bool
public function saveAttachmentsForModel(object $model, ?array $files): bool
{
if(!($model instanceof Model)) {
return false;
}
Log::debug(sprintf('Now in saveAttachmentsForModel for model %s', \get_class($model)));
if (\is_array($files)) {
Log::debug('$files is an array.');
@@ -236,6 +246,7 @@ class AttachmentHelper implements AttachmentHelperInterface
*
* @return Attachment|null
* @throws \Illuminate\Contracts\Encryption\EncryptException
* @throws FireflyException
*/
protected function processFile(UploadedFile $file, Model $model): ?Attachment
{
@@ -257,6 +268,11 @@ class AttachmentHelper implements AttachmentHelperInterface
$fileObject = $file->openFile('r');
$fileObject->rewind();
if(0 === $file->getSize()) {
throw new FireflyException('Cannot upload empty or non-existent file.');
}
$content = $fileObject->fread($file->getSize());
$encrypted = Crypt::encrypt($content);
Log::debug(sprintf('Full file length is %d and upload size is %d.', \strlen($content), $file->getSize()));

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Attachments;
use FireflyIII\Models\Attachment;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
@@ -84,10 +83,10 @@ interface AttachmentHelperInterface
/**
* Save attachments that got uploaded.
*
* @param Model $model
* @param object $model
* @param null|array $files
*
* @return bool
*/
public function saveAttachmentsForModel(Model $model, ?array $files): bool;
public function saveAttachmentsForModel(object $model, ?array $files): bool;
}

View File

@@ -38,6 +38,7 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
/**
* Class MetaPieChart.
@@ -88,6 +89,11 @@ class MetaPieChart implements MetaPieChartInterface
$this->budgets = new Collection;
$this->categories = new Collection;
$this->tags = new Collection;
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**

View File

@@ -24,6 +24,7 @@ namespace FireflyIII\Helpers\Collection;
use Carbon\Carbon;
use FireflyIII\Models\Bill as BillModel;
use FireflyIII\Models\TransactionCurrency;
/**
* Class BillLine.
@@ -42,6 +43,8 @@ class BillLine
protected $max;
/** @var string What was the min amount. */
protected $min;
/** @var TransactionCurrency The transaction currency */
private $currency;
/** @var Carbon Latest date that payment is expected. */
private $endOfPayDate;
/** @var Carbon Date of last hit */
@@ -99,6 +102,22 @@ class BillLine
$this->bill = $bill;
}
/**
* @return TransactionCurrency
*/
public function getCurrency(): TransactionCurrency
{
return $this->currency;
}
/**
* @param TransactionCurrency $currency
*/
public function setCurrency(TransactionCurrency $currency): void
{
$this->currency = $currency;
}
/**
* End of pay date getter.
*

View File

@@ -57,6 +57,16 @@ use Log;
*/
class TransactionCollector implements TransactionCollectorInterface
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var array */
private $accountIds = [];

View File

@@ -25,7 +25,7 @@ namespace FireflyIII\Helpers\Filter;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
use Log;
/**
* Class TransferFilter.
*
@@ -49,6 +49,7 @@ class TransferFilter implements FilterInterface
/** @var Transaction $transaction */
foreach ($set as $transaction) {
if (TransactionType::TRANSFER !== $transaction->transaction_type_type) {
Log::debug(sprintf('Transaction #%d is not a transfer, add it.', $transaction->id));
$new->push($transaction);
continue;
}
@@ -60,6 +61,7 @@ class TransferFilter implements FilterInterface
sort($accountIds);
sort($transactionIds);
$key = $journalId . '-' . implode(',', $transactionIds) . '-' . implode(',', $accountIds) . '-' . $amount;
Log::debug(sprintf('Current transaction key is "%s"', $key));
if (!isset($count[$key])) {
// not yet counted? add to new set and count it:
$new->push($transaction);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers;
use Carbon\Carbon;
use Log;
/**
* Class FiscalHelper.
@@ -38,6 +39,10 @@ class FiscalHelper implements FiscalHelperInterface
public function __construct()
{
$this->useCustomFiscalYear = app('preferences')->get('customFiscalYear', false)->data;
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**

View File

@@ -40,6 +40,16 @@ class Help implements HelpInterface
/** @var string The user agent. */
protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36';
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Get from cache.
*

View File

@@ -51,6 +51,11 @@ class BalanceReportHelper implements BalanceReportHelperInterface
public function __construct(BudgetRepositoryInterface $budgetRepository)
{
$this->budgetRepository = $budgetRepository;
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**

View File

@@ -27,6 +27,7 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
/**
* Class BudgetReportHelper.
@@ -46,6 +47,11 @@ class BudgetReportHelper implements BudgetReportHelperInterface
public function __construct(BudgetRepositoryInterface $repository)
{
$this->repository = $repository;
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**

View File

@@ -48,6 +48,16 @@ class NetWorth implements NetWorthInterface
/** @var User */
private $user;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Returns the user's net worth in an array with the following layout:
*

View File

@@ -30,7 +30,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
/**
* Class PopupReport.
*
@@ -38,6 +38,16 @@ use Illuminate\Support\Collection;
*/
class PopupReport implements PopupReportInterface
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Collect the tranactions for one account and one budget.
*

View File

@@ -32,7 +32,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
/**
* Class ReportHelper.
*
@@ -52,6 +52,12 @@ class ReportHelper implements ReportHelperInterface
public function __construct(BudgetRepositoryInterface $budgetRepository)
{
$this->budgetRepository = $budgetRepository;
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
@@ -92,6 +98,7 @@ class ReportHelper implements ReportHelperInterface
$billLine = new BillLine;
$billLine->setBill($bill);
$billLine->setCurrency($bill->transactionCurrency);
$billLine->setPayDate($payDate);
$billLine->setEndOfPayDate($endOfPayPeriod);
$billLine->setMin((string)$bill->amount_min);

View File

@@ -29,6 +29,7 @@ use FireflyIII\Http\Requests\AccountFormRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Http\Request;
use Log;
/**
*
@@ -82,12 +83,10 @@ class CreateController extends Controller
$debt = $this->repository->getAccountTypeByType(AccountType::DEBT);
$loan = $this->repository->getAccountTypeByType(AccountType::LOAN);
$mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE);
$creditCard = $this->repository->getAccountTypeByType(AccountType::CREDITCARD);
$liabilityTypes = [
$debt->id => (string)trans('firefly.account_type_' . AccountType::DEBT),
$loan->id => (string)trans('firefly.account_type_' . AccountType::LOAN),
$mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE),
$creditCard->id => (string)trans('firefly.account_type_' . AccountType::CREDITCARD),
];
asort($liabilityTypes);
@@ -132,6 +131,8 @@ class CreateController extends Controller
$request->session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name]));
app('preferences')->mark();
// update preferences if necessary:
$frontPage = app('preferences')->get('frontPageAccounts', [])->data;
if (AccountType::ASSET === $account->accountType->type && \count($frontPage) > 0) {

View File

@@ -90,12 +90,10 @@ class EditController extends Controller
$debt = $this->repository->getAccountTypeByType(AccountType::DEBT);
$loan = $this->repository->getAccountTypeByType(AccountType::LOAN);
$mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE);
$creditCard = $this->repository->getAccountTypeByType(AccountType::CREDITCARD);
$liabilityTypes = [
$debt->id => (string)trans('firefly.account_type_' . AccountType::DEBT),
$loan->id => (string)trans('firefly.account_type_' . AccountType::LOAN),
$mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE),
$creditCard->id => (string)trans('firefly.account_type_' . AccountType::CREDITCARD),
];
asort($liabilityTypes);

View File

@@ -64,8 +64,8 @@ class LinkController extends Controller
$subTitleIcon = 'fa-link';
// put previous url in session if not redirect from store (not "create another").
if (true !== session('link_types.create.fromStore')) {
$this->rememberPreviousUri('link_types.create.uri');
if (true !== session('link-types.create.fromStore')) {
$this->rememberPreviousUri('link-types.create.uri');
}
return view('admin.link.create', compact('subTitle', 'subTitleIcon'));
@@ -100,7 +100,7 @@ class LinkController extends Controller
}
}
// put previous url in session
$this->rememberPreviousUri('link_types.delete.uri');
$this->rememberPreviousUri('link-types.delete.uri');
return view('admin.link.delete', compact('linkType', 'subTitle', 'moveTo', 'count'));
}
@@ -123,7 +123,7 @@ class LinkController extends Controller
$request->session()->flash('success', (string)trans('firefly.deleted_link_type', ['name' => $name]));
app('preferences')->mark();
return redirect($this->getPreviousUri('link_types.delete.uri'));
return redirect($this->getPreviousUri('link-types.delete.uri'));
}
/**
@@ -145,10 +145,10 @@ class LinkController extends Controller
$subTitleIcon = 'fa-link';
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('link_types.edit.fromUpdate')) {
$this->rememberPreviousUri('link_types.edit.uri'); // @codeCoverageIgnore
if (true !== session('link-types.edit.fromUpdate')) {
$this->rememberPreviousUri('link-types.edit.uri'); // @codeCoverageIgnore
}
$request->session()->forget('link_types.edit.fromUpdate');
$request->session()->forget('link-types.edit.fromUpdate');
return view('admin.link.edit', compact('subTitle', 'subTitleIcon', 'linkType'));
}
@@ -207,10 +207,10 @@ class LinkController extends Controller
];
$linkType = $repository->store($data);
$request->session()->flash('success', (string)trans('firefly.stored_new_link_type', ['name' => $linkType->name]));
$redirect = redirect($this->getPreviousUri('link_types.create.uri'));
$redirect = redirect($this->getPreviousUri('link-types.create.uri'));
if (1 === (int)$request->get('create_another')) {
// set value so create routine will not overwrite URL:
$request->session()->put('link_types.create.fromStore', true);
$request->session()->put('link-types.create.fromStore', true);
$redirect = redirect(route('admin.links.create'))->withInput();
}
@@ -245,10 +245,10 @@ class LinkController extends Controller
$request->session()->flash('success', (string)trans('firefly.updated_link_type', ['name' => $linkType->name]));
app('preferences')->mark();
$redirect = redirect($this->getPreviousUri('link_types.edit.uri'));
$redirect = redirect($this->getPreviousUri('link-types.edit.uri'));
if (1 === (int)$request->get('return_to_edit')) {
// set value so edit routine will not overwrite URL:
$request->session()->put('link_types.edit.fromUpdate', true);
$request->session()->put('link-types.edit.fromUpdate', true);
$redirect = redirect(route('admin.links.edit', [$linkType->id]))->withInput(['return_to_edit' => 1]);
}

View File

@@ -88,7 +88,7 @@ class ShowController extends Controller
'firefly.without_budget_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
$periods = $this->getBudgetPeriodOverview();
$periods = $this->getBudgetPeriodOverview($end);
$page = (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;

View File

@@ -94,7 +94,7 @@ class ShowController extends Controller
$subTitleIcon = 'fa-bar-chart';
$page = (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
$periods = $this->getCategoryPeriodOverview($category, $start);
$periods = $this->getCategoryPeriodOverview($category, $end);
$path = route('categories.show', [$category->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$subTitle = trans(
'firefly.journals_in_period_for_category',

View File

@@ -210,23 +210,25 @@ class AccountController extends Controller
$budgetIds[] = $budgetId;
if (!isset($result[$combi])) {
$result[$combi] = [
'total' => '0',
'budget_id' => $budgetId,
'currency' => $currencyName,
'total' => '0',
'budget_id' => $budgetId,
'currency' => $currencyName,
'currency_symbol' => $transaction->transaction_currency_symbol,
];
}
$result[$combi]['total'] = bcadd($transaction->transaction_amount, $result[$combi]['total']);
}
$names = $this->getBudgetNames($budgetIds);
foreach ($result as $row) {
$budgetId = $row['budget_id'];
$name = $names[$budgetId];
$label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency']]);
$chartData[$label] = $row['total'];
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol']];
}
$data = $this->generator->pieChart($chartData);
$data = $this->generator->multiCurrencyPieChart($chartData);
$cache->store($data);
return response()->json($data);
@@ -276,6 +278,7 @@ class AccountController extends Controller
$result = [];
$chartData = [];
$categoryIds = [];
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$jrnlCatId = (int)$transaction->transaction_journal_category_id;
@@ -286,24 +289,25 @@ class AccountController extends Controller
$categoryIds[] = $categoryId;
if (!isset($result[$combi])) {
$result[$combi] = [
'total' => '0',
'category_id' => $categoryId,
'currency' => $currencyName,
'total' => '0',
'category_id' => $categoryId,
'currency' => $currencyName,
'currency_symbol' => $transaction->transaction_currency_symbol,
];
}
$result[$combi]['total'] = bcadd($transaction->transaction_amount, $result[$combi]['total']);
}
$names = $this->getCategoryNames(array_keys($result));
$names = $this->getCategoryNames($categoryIds);
foreach ($result as $row) {
$categoryId = $row['category_id'];
$name = $names[$categoryId] ?? '(unknown)';
$label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency']]);
$chartData[$label] = $row['total'];
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol']];
}
$data = $this->generator->pieChart($chartData);
$data = $this->generator->multiCurrencyPieChart($chartData);
$cache->store($data);
return response()->json($data);
@@ -371,7 +375,7 @@ class AccountController extends Controller
$cache->addProperty($end);
$cache->addProperty('chart.account.income-category');
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
//return response()->json($cache->get()); // @codeCoverageIgnore
}
// grab all journals:
@@ -381,6 +385,7 @@ class AccountController extends Controller
$transactions = $collector->getTransactions();
$result = [];
$chartData = [];
$categoryIds = [];
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$jrnlCatId = (int)$transaction->transaction_journal_category_id;
@@ -391,22 +396,23 @@ class AccountController extends Controller
$categoryIds[] = $categoryId;
if (!isset($result[$combi])) {
$result[$combi] = [
'total' => '0',
'category_id' => $categoryId,
'currency' => $currencyName,
'total' => '0',
'category_id' => $categoryId,
'currency' => $currencyName,
'currency_symbol' => $transaction->transaction_currency_symbol,
];
}
$result[$combi]['total'] = bcadd($transaction->transaction_amount, $result[$combi]['total']);
}
$names = $this->getCategoryNames(array_keys($result));
$names = $this->getCategoryNames($categoryIds);
foreach ($result as $row) {
$categoryId = $row['category_id'];
$name = $names[$categoryId] ?? '(unknown)';
$label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency']]);
$chartData[$label] = $row['total'];
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol']];
}
$data = $this->generator->pieChart($chartData);
$data = $this->generator->multiCurrencyPieChart($chartData);
$cache->store($data);
return response()->json($data);

View File

@@ -47,6 +47,8 @@ class JobStatusController extends Controller
public function __construct()
{
parent::__construct();
// set time limit to zero to prevent timeouts.
set_time_limit(0);
$this->middleware(
function ($request, $next) {

View File

@@ -36,8 +36,10 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* TODO refactor so each auto-complete thing is a function call because lots of code duplication.
* Class AutoCompleteController.
*
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
@@ -49,18 +51,40 @@ class AutoCompleteController extends Controller
/**
* Returns a JSON list of all accounts.
*
* @param Request $request
* @param AccountRepositoryInterface $repository
*
* @return JsonResponse
*/
public function allAccounts(AccountRepositoryInterface $repository): JsonResponse
public function allAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
{
$return = array_unique(
$repository->getAccountsByType(
[AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET]
)->pluck('name')->toArray()
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-all-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = array_values(
array_unique(
$repository->getAccountsByType(
[AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET]
)->pluck('name')->toArray()
)
);
sort($return);
if ('' !== $search) {
$return = array_values(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
);
}
$cache->store($return);
return response()->json($return);
}
@@ -68,15 +92,86 @@ class AutoCompleteController extends Controller
/**
* List of all journals.
*
* @param Request $request
* @param TransactionCollectorInterface $collector
*
* @return JsonResponse
*/
public function allTransactionJournals(TransactionCollectorInterface $collector): JsonResponse
public function allTransactionJournals(Request $request, TransactionCollectorInterface $collector): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-all-journals');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$collector->setLimit(250)->setPage(1);
$return = array_unique($collector->getTransactions()->pluck('description')->toArray());
sort($return);
$return = array_values(array_unique($collector->getTransactions()->pluck('description')->toArray()));
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
/**
* List of revenue accounts.
*
* @param Request $request
* @param AccountRepositoryInterface $repository
*
* @return JsonResponse
*/
public function assetAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-asset-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$set = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$filtered = $set->filter(
function (Account $account) {
if (true === $account->active) {
return $account;
}
return false; // @codeCoverageIgnore
}
);
$return = array_values(array_unique($filtered->pluck('name')->toArray()));
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
@@ -84,16 +179,37 @@ class AutoCompleteController extends Controller
/**
* Returns a JSON list of all bills.
*
* @param Request $request
* @param BillRepositoryInterface $repository
*
* @return JsonResponse
*/
public function bills(BillRepositoryInterface $repository): JsonResponse
public function bills(Request $request, BillRepositoryInterface $repository): JsonResponse
{
$return = array_unique(
$repository->getActiveBills()->pluck('name')->toArray()
);
sort($return);
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-bills');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = array_unique($repository->getActiveBills()->pluck('name')->toArray());
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
@@ -101,14 +217,37 @@ class AutoCompleteController extends Controller
/**
* List of budgets.
*
* @param Request $request
* @param BudgetRepositoryInterface $repository
*
* @return JsonResponse
*/
public function budgets(BudgetRepositoryInterface $repository): JsonResponse
public function budgets(Request $request, BudgetRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-budgets');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = array_unique($repository->getBudgets()->pluck('name')->toArray());
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
@@ -116,14 +255,34 @@ class AutoCompleteController extends Controller
/**
* Returns a list of categories.
*
* @param Request $request
* @param CategoryRepositoryInterface $repository
*
* @return JsonResponse
*/
public function categories(CategoryRepositoryInterface $repository): JsonResponse
public function categories(Request $request, CategoryRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-categories');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = array_unique($repository->getCategories()->pluck('name')->toArray());
sort($return);
if ('' !== $search) {
$return = array_values(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
);
}
$cache->store($return);
return response()->json($return);
}
@@ -131,27 +290,62 @@ class AutoCompleteController extends Controller
/**
* List of currency names.
*
* @param Request $request
* @param CurrencyRepositoryInterface $repository
*
* @return JsonResponse
*/
public function currencyNames(CurrencyRepositoryInterface $repository): JsonResponse
public function currencyNames(Request $request, CurrencyRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-currency-names');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = $repository->get()->pluck('name')->toArray();
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param Request $request
* @param AccountRepositoryInterface $repository
*
* @return JsonResponse
*/
public function expenseAccounts(AccountRepositoryInterface $repository): JsonResponse
public function expenseAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-expense-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$set = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]);
$filtered = $set->filter(
function (Account $account) {
@@ -166,27 +360,43 @@ class AutoCompleteController extends Controller
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
/**
* List of journals with their ID.
*
* @param Request $request
* @param TransactionCollectorInterface $collector
* @param TransactionJournal $except
* @param TransactionJournal $except
*
* @return JsonResponse
*/
public function journalsWithId(TransactionCollectorInterface $collector, TransactionJournal $except): JsonResponse
public function journalsWithId(Request $request, TransactionCollectorInterface $collector, TransactionJournal $except): JsonResponse
{
$cache = new CacheProperties;
$cache->addProperty('recent-journals-id');
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-expense-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
return response()->json($cache->get());
}
// find everything:
$collector->setLimit(400)->setPage(1);
$set = $collector->getTransactions()->pluck('description', 'journal_id')->toArray();
$return = [];
@@ -200,6 +410,21 @@ class AutoCompleteController extends Controller
}
}
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (array $array) use ($search) {
$value = $array['name'];
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
@@ -208,12 +433,23 @@ class AutoCompleteController extends Controller
/**
* List of revenue accounts.
*
* @param Request $request
* @param AccountRepositoryInterface $repository
*
* @return JsonResponse
*/
public function revenueAccounts(AccountRepositoryInterface $repository): JsonResponse
public function revenueAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-revenue-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$set = $repository->getAccountsByType([AccountType::REVENUE]);
$filtered = $set->filter(
function (Account $account) {
@@ -227,34 +463,82 @@ class AutoCompleteController extends Controller
$return = array_unique($filtered->pluck('name')->toArray());
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param Request $request
* @param TagRepositoryInterface $tagRepository
*
* @return JsonResponse
*/
public function tags(TagRepositoryInterface $tagRepository): JsonResponse
public function tags(Request $request, TagRepositoryInterface $tagRepository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-revenue-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = array_unique($tagRepository->get()->pluck('tag')->toArray());
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
/**
* List of journals by type.
*
* @param Request $request
* @param TransactionCollectorInterface $collector
* @param string $what
* @param string $what
*
* @return JsonResponse
*/
public function transactionJournals(TransactionCollectorInterface $collector, string $what): JsonResponse
public function transactionJournals(Request $request, TransactionCollectorInterface $collector, string $what): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-revenue-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$type = config('firefly.transactionTypesByWhat.' . $what);
$types = [$type];
@@ -262,21 +546,60 @@ class AutoCompleteController extends Controller
$return = array_unique($collector->getTransactions()->pluck('description')->toArray());
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
/**
* List if transaction types.
*
* @param Request $request
* @param JournalRepositoryInterface $repository
*
* @return JsonResponse
*/
public function transactionTypes(JournalRepositoryInterface $repository): JsonResponse
public function transactionTypes(Request $request, JournalRepositoryInterface $repository): JsonResponse
{
$search = (string)$request->get('search');
$cache = new CacheProperties;
$cache->addProperty('ac-revenue-accounts');
// very unlikely a user will actually search for this string.
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
$cache->addProperty($key);
if ($cache->has()) {
return response()->json($cache->get());
}
// find everything:
$return = array_unique($repository->getTransactionTypes()->pluck('type')->toArray());
sort($return);
if ('' !== $search) {
$return = array_values(
array_unique(
array_filter(
$return, function (string $value) use ($search) {
return !(false === stripos($value, $search));
}, ARRAY_FILTER_USE_BOTH
)
)
);
}
$cache->store($return);
return response()->json($return);
}
}

View File

@@ -152,7 +152,7 @@ class SelectController extends Controller
$limit = (int)config('firefly.test-triggers.limit');
$range = (int)config('firefly.test-triggers.range');
$matchingTransactions = new Collection;
$strict = $request->get('strict') === '1';
$strict = '1' === $request->get('strict');
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setLimit($limit);

View File

@@ -22,6 +22,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Transaction;
use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
@@ -161,9 +162,14 @@ class ConvertController extends Controller
$errors = $this->repository->convert($journal, $destinationType, $source, $destination);
if ($errors->count() > 0) {
Log::error('Errors while converting: ', $errors->toArray());
return redirect(route('transactions.convert.index', [strtolower($destinationType->type), $journal->id]))->withErrors($errors)->withInput();
}
// Success? Fire rules!
event(new UpdatedTransactionJournal($journal));
session()->flash('success', (string)trans('firefly.converted_to_' . $destinationType->type));
return redirect(route('transactions.show', [$journal->id]));

View File

@@ -24,7 +24,9 @@ namespace FireflyIII\Http\Controllers\Transaction;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Helpers\Filter\InternalTransferFilter;
use FireflyIII\Helpers\Filter\TransactionViewFilter;
use FireflyIII\Helpers\Filter\TransferFilter;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
use FireflyIII\Http\Requests\MassEditJournalRequest;
@@ -147,6 +149,9 @@ class MassController extends Controller
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
$collector->setJournals($journals);
$collector->addFilter(TransactionViewFilter::class);
$collector->addFilter(TransferFilter::class);
$collection = $collector->getTransactions();
$transactions = $collection->map(
function (Transaction $transaction) use ($transformer) {

View File

@@ -68,7 +68,7 @@ class Authenticate
*/
public function handle($request, Closure $next, ...$guards)
{
$this->authenticate($guards);
$this->authenticate($request, $guards);
return $next($request);
}
@@ -86,7 +86,7 @@ class Authenticate
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
protected function authenticate(array $guards)
protected function authenticate($request, array $guards)
{
if (empty($guards)) {

View File

@@ -33,6 +33,8 @@ use Log;
/**
* Class Installer
* @codeCoverageIgnore
*
*/
class Installer
{
@@ -48,6 +50,7 @@ class Installer
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
*/
public function handle($request, Closure $next)
{

View File

@@ -60,7 +60,7 @@ class IsDemoUser
return response()->redirectTo($previous);
}
return response()->redirectTo(route('index'));
return response()->redirectTo(route('index')); // @codeCoverageIgnore
}
return $next($request);

View File

@@ -108,9 +108,11 @@ class Range
private function loseItAll(Request $request): void
{
if ('sqlite' === getenv('DB_CONNECTION') && true === getenv('IS_DOCKER')) {
// @codeCoverageIgnoreStart
$request->session()->flash(
'error', 'You seem to be using SQLite in a Docker container. Don\'t do this. If the container restarts all your data will be gone.'
);
// @codeCoverageIgnoreEnd
}
}

View File

@@ -87,6 +87,7 @@ class Sandstorm
* @param string $email
*
* @return User
* @codeCoverageIgnore
*/
private function createUser(string $email): User
{

View File

@@ -47,7 +47,7 @@ class SecureHeaders
$google = '';
$analyticsId = env('ANALYTICS_ID', '');
if ('' !== $analyticsId) {
$google = 'https://www.google-analytics.com/analytics.js';
$google = 'www.googletagmanager.com/gtag/js'; // @codeCoverageIgnore
}
$csp = [
"default-src 'none'",
@@ -57,7 +57,7 @@ class SecureHeaders
"form-action 'self'",
"font-src 'self'",
"connect-src 'self'",
"img-src 'self' data:",
"img-src 'self' data: https://api.tiles.mapbox.com",
];
$featurePolicies = [

View File

@@ -75,6 +75,7 @@ class JournalFormRequest extends Request
'piggy_bank_name' => null,
'bill_id' => null,
'bill_name' => null,
'original-source' => sprintf('gui-v%s', config('firefly.version')),
// transaction data:
'transactions' => [
@@ -274,7 +275,12 @@ class JournalFormRequest extends Request
$selectedCurrency = (int)($data['amount_currency_id_amount'] ?? 0);
$accountCurrency = (int)($data['destination_account_currency'] ?? 0);
$nativeAmount = (string)($data['native_amount'] ?? '');
Log::debug('Now in validateDeposit.');
Log::debug(sprintf('SelectedCurrency is "%s", accountCurrency is "%s", native amount is "%s".', $selectedCurrency, $accountCurrency, $nativeAmount));
if ($selectedCurrency !== $accountCurrency && '' === $nativeAmount && 0 !== $selectedCurrency && 0 !== $accountCurrency) {
Log::debug('Adding an error about missing native amount.');
$validator->errors()->add('native_amount', (string)trans('validation.numeric_native'));
return;

View File

@@ -208,8 +208,10 @@ class ReportFormRequest extends Request
$repository = app(TagRepositoryInterface::class);
$set = $this->get('tag');
$collection = new Collection;
Log::debug('Set is:', $set ?? []);
if (\is_array($set)) {
foreach ($set as $tagTag) {
Log::debug(sprintf('Now searching for "%s"', $tagTag));
$tag = $repository->findByTag($tagTag);
if (null !== $tag) {
$collection->push($tag);

View File

@@ -27,6 +27,7 @@ use Illuminate\Foundation\Http\FormRequest;
/**
* Class Request.
* @codeCoverageIgnore
*
* @SuppressWarnings(PHPMD.NumberOfChildren)
*/
@@ -91,58 +92,7 @@ class Request extends FormRequest
*/
public function string(string $field): string
{
$string = $this->get($field) ?? '';
$search = [
"\u{0001}", // start of heading
"\u{0002}", // start of text
"\u{0003}", // end of text
"\u{0004}", // end of transmission
"\u{0005}", // enquiry
"\u{0006}", // ACK
"\u{0007}", // BEL
"\u{0008}", // backspace
"\u{000E}", // shift out
"\u{000F}", // shift in
"\u{0010}", // data link escape
"\u{0011}", // DC1
"\u{0012}", // DC2
"\u{0013}", // DC3
"\u{0014}", // DC4
"\u{0015}", // NAK
"\u{0016}", // SYN
"\u{0017}", // ETB
"\u{0018}", // CAN
"\u{0019}", // EM
"\u{001A}", // SUB
"\u{001B}", // escape
"\u{001C}", // file separator
"\u{001D}", // group separator
"\u{001E}", // record separator
"\u{001F}", // unit separator
"\u{007F}", // DEL
"\u{00A0}", // non-breaking space
"\u{1680}", // ogham space mark
"\u{180E}", // mongolian vowel separator
"\u{2000}", // en quad
"\u{2001}", // em quad
"\u{2002}", // en space
"\u{2003}", // em space
"\u{2004}", // three-per-em space
"\u{2005}", // four-per-em space
"\u{2006}", // six-per-em space
"\u{2007}", // figure space
"\u{2008}", // punctuation space
"\u{2009}", // thin space
"\u{200A}", // hair space
"\u{200B}", // zero width space
"\u{202F}", // narrow no-break space
"\u{3000}", // ideographic space
"\u{FEFF}", // zero width no -break space
];
$replace = "\x20"; // plain old normal space
$string = str_replace($search, $replace, $string);
return trim($string);
return app('steam')->cleanString((string)($this->get($field) ?? ''));
}
/**

View File

@@ -23,7 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Requests;
/**
* Class RuleFormRequest.
* Class TestRuleFormRequest.
*
* @codeCoverageIgnore
*/

View File

@@ -91,11 +91,13 @@ class Amount implements ConverterInterface
return $value;
}
// @codeCoverageIgnoreStart
Log::debug(sprintf('Final value is: "%s"', $value));
$formatted = sprintf('%01.12f', $value);
Log::debug(sprintf('Is formatted to : "%s"', $formatted));
return $formatted;
// @codeCoverageIgnoreEnd
}
/**

View File

@@ -0,0 +1,46 @@
<?php
/**
* AmountNegated.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\Import\Converter;
/**
* Class AmountNegated
*/
class AmountNegated implements ConverterInterface
{
/**
* Negate amount.
*
* @param $value
*
* @return string
*/
public function convert($value): string
{
/** @var ConverterInterface $converter */
$converter = app(Amount::class);
$result = $converter->convert($value);
$result = bcmul($result, '-1');
return $result;
}
}

View File

@@ -40,7 +40,12 @@ class AssetAccountIbans implements MapperInterface
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$set = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$set = $accountRepository->getAccountsByType(
[AccountType::DEFAULT, AccountType::ASSET,
AccountType::LOAN, AccountType::DEBT,
AccountType::CREDITCARD, AccountType::MORTGAGE,
]
);
$topList = [];
$list = [];
@@ -49,10 +54,22 @@ class AssetAccountIbans implements MapperInterface
$iban = $account->iban ?? '';
$accountId = (int)$account->id;
if (\strlen($iban) > 0) {
$topList[$accountId] = $account->iban . ' (' . $account->name . ')';
$name = $account->iban . ' (' . $account->name . ')';
// is a liability?
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
}
$topList[$accountId] = $name;
}
if ('' === $iban) {
$list[$accountId] = $account->name;
$name = $account->name;
// is a liability?
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
}
$list[$accountId] = $name;
}
}
/** @noinspection AdditionOperationOnArraysInspection */

View File

@@ -40,7 +40,7 @@ class AssetAccounts implements MapperInterface
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$set = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$set = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE,]);
$list = [];
/** @var Account $account */
@@ -51,6 +51,12 @@ class AssetAccounts implements MapperInterface
if (\strlen($iban) > 0) {
$name .= ' (' . $iban . ')';
}
// is a liability?
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
$name = trans('import.import_liability_select') . ': ' . $name;
}
$list[$accountId] = $name;
}
asort($list);

View File

@@ -44,7 +44,8 @@ class OpposingAccountIbans implements MapperInterface
[
AccountType::DEFAULT, AccountType::ASSET,
AccountType::EXPENSE, AccountType::BENEFICIARY,
AccountType::REVENUE,
AccountType::REVENUE, AccountType::LOAN, AccountType::DEBT,
AccountType::CREDITCARD, AccountType::MORTGAGE,
]
);
$topList = [];
@@ -55,10 +56,23 @@ class OpposingAccountIbans implements MapperInterface
$iban = $account->iban ?? '';
$accountId = (int)$account->id;
if (\strlen($iban) > 0) {
$topList[$accountId] = $account->iban . ' (' . $account->name . ')';
$name = $account->iban . ' (' . $account->name . ')';
// is a liability?
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
}
$topList[$accountId] = $name;
}
if ('' === $iban) {
$list[$accountId] = $account->name;
$name = $account->name;
// is a liability?
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
}
$list[$accountId] = $name;
}
}
/** @noinspection AdditionOperationOnArraysInspection */

View File

@@ -44,7 +44,8 @@ class OpposingAccounts implements MapperInterface
[
AccountType::DEFAULT, AccountType::ASSET,
AccountType::EXPENSE, AccountType::BENEFICIARY,
AccountType::REVENUE,
AccountType::REVENUE, AccountType::LOAN, AccountType::DEBT,
AccountType::CREDITCARD, AccountType::MORTGAGE,
]
);
$list = [];
@@ -57,6 +58,10 @@ class OpposingAccounts implements MapperInterface
if (\strlen($iban) > 0) {
$name .= ' (' . $iban . ')';
}
// is a liability?
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
$name = trans('import.import_liability_select') . ': ' . $name;
}
$list[$accountId] = $name;
}
asort($list);

View File

@@ -123,23 +123,6 @@ class YnabRoutine implements RoutineInterface
return;
}
// if ('match_accounts' === $this->importJob->stage) {
// // $this->repository->setStatus($this->importJob, 'running');
// /** @var StageGetBudgetsHandler $handler */
// $handler = app(StageGetBudgetsHandler::class);
// $handler->setImportJob($this->importJob);
// $handler->run();
// $this->repository->setStage($this->importJob, 'get_transactions');
// }
//
// if ('get_transactions' === $this->importJob->stage) {
// // $this->repository->setStatus($this->importJob, 'running');
// /** @var StageGetBudgetsHandler $handler */
// $handler = app(StageGetBudgetsHandler::class);
// $handler->setImportJob($this->importJob);
// $handler->run();
// $this->repository->setStage($this->importJob, 'get_transactions');
// }
throw new FireflyException(sprintf('YNAB import routine cannot handle stage "%s"', $this->importJob->stage));
}
}

View File

@@ -190,7 +190,7 @@ class ImportArrayStorage
*/
private function getHash(array $transaction): string
{
unset($transaction['importHashV2']);
unset($transaction['importHashV2'], $transaction['original-source']);
$json = json_encode($transaction);
if (false === $json) {
/** @noinspection ForgottenDebugOutputInspection */

View File

@@ -238,7 +238,7 @@ class CreateRecurringTransactions implements ShouldQueue
/** @var RecurrenceTransaction $transaction */
foreach ($transactions as $index => $transaction) {
$single = [
'currency_id' => $transaction->transaction_currency_id,
'currency_id' => (int)$transaction->transaction_currency_id,
'currency_code' => null,
'description' => null,
'amount' => $transaction->amount,

View File

@@ -39,6 +39,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property string $amount
* @property int $budget_id
* @property string spent
* @property int $transaction_currency_id
*/
class BudgetLimit extends Model
{
@@ -89,4 +90,13 @@ class BudgetLimit extends Model
{
return $this->belongsTo(Budget::class);
}
/**
* @codeCoverageIgnore
* @return BelongsTo
*/
public function transactionCurrency(): BelongsTo
{
return $this->belongsTo(TransactionCurrency::class);
}
}

View File

@@ -24,8 +24,10 @@ namespace FireflyIII\Repositories\Account;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
@@ -68,18 +70,28 @@ class AccountTasker implements AccountTaskerInterface
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
/** @var CurrencyRepositoryInterface $currencyRepository */
$currencyRepository = app(CurrencyRepositoryInterface::class);
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
$return = [
'currencies' => [],
'start' => '0',
'end' => '0',
'difference' => '0',
'accounts' => [],
];
/** @var Account $account */
foreach ($accounts as $account) {
$id = $account->id;
$entry = [
$id = $account->id;
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
$currency = $currencyRepository->findNull($currencyId);
$return['currencies'][] = $currencyId;
$entry = [
'name' => $account->name,
'id' => $account->id,
'currency' => $currency ?? $defaultCurrency,
'start_balance' => '0',
'end_balance' => '0',
];
@@ -100,7 +112,7 @@ class AccountTasker implements AccountTaskerInterface
$return['accounts'][$id] = $entry;
}
$return['currencies'] = count(array_unique($return['currencies']));
$return['difference'] = bcsub($return['end'], $return['start']);
return $return;
@@ -206,29 +218,51 @@ class AccountTasker implements AccountTaskerInterface
*/
private function groupByOpposing(Collection $transactions): array
{
$expenses = [];
// join the result together:
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
$currencies = [$defaultCurrency->id => $defaultCurrency,];
$expenses = [];
$countAccounts = []; // if count remains 0 use original name, not the name with the currency.
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$opposingId = $transaction->opposing_account_id;
$name = $transaction->opposing_account_name;
if (!isset($expenses[$opposingId])) {
$expenses[$opposingId] = [
'id' => $opposingId,
'name' => $name,
'sum' => '0',
'average' => '0',
'count' => 0,
$opposingId = (int)$transaction->opposing_account_id;
$currencyId = (int)$transaction->transaction_currency_id;
$key = sprintf('%s-%s', $opposingId, $currencyId);
$name = sprintf('%s (%s)', $transaction->opposing_account_name, $transaction->transaction_currency_code);
$countAccounts[$opposingId] = isset($countAccounts[$opposingId]) ? $countAccounts[$opposingId] + 1 : 1;
if (!isset($expenses[$key])) {
$currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->findNull($currencyId);
$expenses[$key] = [
'id' => $opposingId,
'name' => $name,
'original' => $transaction->opposing_account_name,
'sum' => '0',
'average' => '0',
'currencies' => [],
'single_currency' => $currencies[$currencyId],
'count' => 0,
];
}
$expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount);
++$expenses[$opposingId]['count'];
$expenses[$key]['currencies'][] = (int)$transaction->transaction_currency_id;
$expenses[$key]['sum'] = bcadd($expenses[$key]['sum'], $transaction->transaction_amount);
++$expenses[$key]['count'];
}
// do averages:
$keys = array_keys($expenses);
foreach ($keys as $key) {
$opposingId = $expenses[$key]['id'];
if(1===$countAccounts[$opposingId]) {
$expenses[$key]['name'] = $expenses[$key]['original'];
}
if ($expenses[$key]['count'] > 1) {
$expenses[$key]['average'] = bcdiv($expenses[$key]['sum'], (string)$expenses[$key]['count']);
}
$expenses[$key]['currencies'] = \count(array_unique($expenses[$key]['currencies']));
$expenses[$key]['all_currencies'] = \count($currencies);
}
return $expenses;

View File

@@ -148,7 +148,7 @@ class BillRepository implements BillRepositoryInterface
public function getBillsForAccounts(Collection $accounts): Collection
{
$fields = ['bills.id', 'bills.created_at', 'bills.updated_at', 'bills.deleted_at', 'bills.user_id', 'bills.name', 'bills.match', 'bills.amount_min',
'bills.amount_max', 'bills.date', 'bills.repeat_freq', 'bills.skip', 'bills.automatch', 'bills.active', 'bills.name_encrypted',
'bills.amount_max', 'bills.date','bills.transaction_currency_id', 'bills.repeat_freq', 'bills.skip', 'bills.automatch', 'bills.active', 'bills.name_encrypted',
'bills.match_encrypted',];
$ids = $accounts->pluck('id')->toArray();
$set = $this->user->bills()

View File

@@ -315,6 +315,7 @@ class BudgetRepository implements BudgetRepositoryInterface
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->with(['budget'])
->where('budgets.user_id', $this->user->id)
->whereNull('budgets.deleted_at')
->get(['budget_limits.*']);
return $set;
@@ -323,6 +324,7 @@ class BudgetRepository implements BudgetRepositoryInterface
if (null === $start xor null === $end) {
$query = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->with(['budget'])
->whereNull('budgets.deleted_at')
->where('budgets.user_id', $this->user->id);
if (null !== $end) {
// end date must be before $end.
@@ -340,6 +342,7 @@ class BudgetRepository implements BudgetRepositoryInterface
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->with(['budget'])
->where('budgets.user_id', $this->user->id)
->whereNull('budgets.deleted_at')
->where(
function (Builder $q5) use ($start, $end) {
$q5->where(

View File

@@ -83,14 +83,37 @@ class CategoryRepository implements CategoryRepositoryInterface
* @return string
*/
public function earnedInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string
{
$set = $this->earnedInPeriodCollection($categories, $accounts, $start, $end);
return (string)$set->sum('transaction_amount');
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function earnedInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection
{
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
$collector->setUser($this->user);
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($accounts)->setCategories($categories);
$set = $collector->getTransactions();
if (0 !== $accounts->count()) {
$collector->setAccounts($accounts);
}
return (string)$set->sum('transaction_amount');
if (0 === $accounts->count()) {
$collector->setAllAssetAccounts();
}
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setCategories($categories);
return $collector->getTransactions();
}
/**
@@ -182,6 +205,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $set;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Category $category
* @param Collection $accounts
@@ -212,7 +237,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $lastJournalDate;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
* @param Collection $accounts
@@ -258,6 +282,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $data;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Carbon $start
@@ -296,7 +322,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $result;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
* @param Collection $accounts
@@ -383,6 +408,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $result;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param User $user
*/
@@ -401,6 +428,23 @@ class CategoryRepository implements CategoryRepositoryInterface
* @return string
*/
public function spentInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string
{
$set = $this->spentInPeriodCollection($categories, $accounts, $start, $end);
return (string)$set->sum('transaction_amount');
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function spentInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection
{
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
@@ -414,13 +458,9 @@ class CategoryRepository implements CategoryRepositoryInterface
$collector->setAllAssetAccounts();
}
$set = $collector->getTransactions();
return (string)$set->sum('transaction_amount');
return $collector->getTransactions();
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* A very cryptic method name that means:
*

View File

@@ -51,6 +51,17 @@ interface CategoryRepositoryInterface
*/
public function earnedInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string;
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function earnedInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection;
/**
* Find a category.
*
@@ -158,6 +169,17 @@ interface CategoryRepositoryInterface
*/
public function spentInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string;
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function spentInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection;
/** @noinspection MoreThanThreeArgumentsInspection */
/**

View File

@@ -342,6 +342,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface
* @param UploadedFile $file
*
* @return MessageBag
* @throws FireflyException
*/
public function storeFileUpload(ImportJob $job, string $name, UploadedFile $file): MessageBag
{
@@ -374,6 +375,12 @@ class ImportJobRepository implements ImportJobRepositoryInterface
$attachment->save();
$fileObject = $file->openFile('r');
$fileObject->rewind();
if(0 === $file->getSize()) {
throw new FireflyException('Cannot upload empty or non-existent file.');
}
$content = $fileObject->fread($file->getSize());
$encrypted = Crypt::encrypt($content);
$this->uploadDisk->put($attachment->fileName(), $encrypted);

View File

@@ -64,8 +64,10 @@ class FixerIOv2 implements ExchangeRateInterface
$exchangeRate->user()->associate($this->user);
$exchangeRate->fromCurrency()->associate($fromCurrency);
$exchangeRate->toCurrency()->associate($toCurrency);
$exchangeRate->date = $date;
$exchangeRate->rate = $rate;
$exchangeRate->date = $date;
$exchangeRate->rate = $rate;
$exchangeRate->updated_at = new Carbon;
$exchangeRate->created_at = new Carbon;
// get API key
$apiKey = env('FIXER_API_KEY', '');

View File

@@ -34,6 +34,16 @@ use RuntimeException;
*/
class IpifyOrg implements IPRetrievalInterface
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Returns the user's IP address.
*

View File

@@ -37,6 +37,16 @@ use Log;
*/
class AccountDestroyService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param Account $account
* @param Account|null $moveTo

View File

@@ -33,6 +33,16 @@ use Log;
*/
class BillDestroyService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param Bill $bill
*/

View File

@@ -32,6 +32,16 @@ use Log;
*/
class CategoryDestroyService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param Category $category
*/

View File

@@ -32,6 +32,16 @@ use Log;
*/
class CurrencyDestroyService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param TransactionCurrency $currency
*/

View File

@@ -35,6 +35,16 @@ use Log;
*/
class JournalDestroyService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param TransactionJournal $journal
*/

View File

@@ -34,6 +34,16 @@ use Log;
*/
class RecurrenceDestroyService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Delete recurrence.
*

View File

@@ -33,6 +33,16 @@ use Log;
*/
class EncryptService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param string $file
* @param string $key

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Support;
use Exception;
use FireflyIII\Factory\BillFactory;
use FireflyIII\Factory\TagFactory;
use FireflyIII\Factory\TransactionJournalMetaFactory;
@@ -128,7 +129,11 @@ trait JournalServiceTrait
}
$note = $journal->notes()->first();
if (null !== $note) {
$note->delete();
try {
$note->delete();
} catch (Exception $e) {
Log::debug(sprintf('Journal service trait could not delete note: %s', $e->getMessage()));
}
}

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Models\Account;
use FireflyIII\Services\Internal\Support\AccountServiceTrait;
use Log;
/**
* Class AccountUpdateService
@@ -32,7 +33,15 @@ use FireflyIII\Services\Internal\Support\AccountServiceTrait;
class AccountUpdateService
{
use AccountServiceTrait;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Update account data.

View File

@@ -25,7 +25,7 @@ namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Models\Bill;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
use Log;
/**
* @codeCoverageIgnore
* Class BillUpdateService
@@ -34,6 +34,16 @@ class BillUpdateService
{
use BillServiceTrait;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param Bill $bill
* @param array $data

View File

@@ -24,13 +24,23 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Models\Category;
use Log;
/**
* Class CategoryUpdateService
*/
class CategoryUpdateService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param Category $category
* @param array $data

View File

@@ -24,12 +24,22 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Models\TransactionCurrency;
use Log;
/**
* Class CurrencyUpdateService
*/
class CurrencyUpdateService
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param TransactionCurrency $currency
* @param array $data

View File

@@ -30,7 +30,6 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
use Illuminate\Support\Collection;
use Log;
/**
* Class to centralise code that updates a journal given the input by system.
*
@@ -39,6 +38,16 @@ use Log;
class JournalUpdateService
{
use JournalServiceTrait;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* @param TransactionJournal $journal

View File

@@ -26,7 +26,7 @@ namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Models\Transaction;
use FireflyIII\Services\Internal\Support\TransactionServiceTrait;
use FireflyIII\User;
use Log;
/**
* Class TransactionUpdateService
*/
@@ -34,6 +34,16 @@ class TransactionUpdateService
{
use TransactionServiceTrait;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/** @var User */
private $user;

View File

@@ -33,6 +33,16 @@ use RuntimeException;
*/
class PwndVerifierV2 implements Verifier
{
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === env('APP_ENV')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
}
}
/**
* Verify the given password against (some) service.
*

View File

@@ -50,16 +50,19 @@ class GetBudgetsRequest extends YnabRequest
Log::debug(sprintf('URI is %s', $uri));
$result = $this->authenticatedGetRequest($uri, []);
//Log::debug('Raw GetBudgetsRequest result', $result);
Log::debug('Raw GetBudgetsRequest result', $result);
// expect data in [data][budgets]
$rawBudgets = $result['data']['budgets'] ?? [];
$freshBudgets = [];
foreach ($rawBudgets as $rawBudget) {
Log::debug(sprintf('Raw content of budget is: %s', json_encode($rawBudget)));
Log::debug(sprintf('Content of currency format is: %s', json_encode($rawBudget['currency_format'] ?? [])));
Log::debug(sprintf('ISO code is: %s', $rawBudget['currency_format']['iso_code'] ?? '(none)'));
$freshBudgets[] = [
'id' => $rawBudget['id'],
'name' => $rawBudget['name'],
'currency_code' => $rawBudget['currency_format']['iso_code'],
'currency_code' => $rawBudget['currency_format']['iso_code'] ?? null,
];
}
$this->budgets = $freshBudgets;

View File

@@ -74,6 +74,7 @@ abstract class YnabRequest
}
try {
$content = trim($res->getBody()->getContents());
Log::debug(sprintf('Raw body is: %s', $content));
} catch (RuntimeException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());

Some files were not shown because too many files have changed in this diff Show More