Various phpstan fixes [skip ci]

This commit is contained in:
James Cole 2025-01-04 08:42:06 +01:00
parent d4942efd8e
commit c43b37baef
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
34 changed files with 43 additions and 1229 deletions

View File

@ -51,8 +51,7 @@ class AdminEventHandler
} }
try { try {
$owner = new OwnerNotifiable(); Notification::send(new OwnerNotifiable(), new UserInvitation($event->invitee));
Notification::send($owner, new UserInvitation($owner, $event->invitee));
} catch (\Exception $e) { // @phpstan-ignore-line } catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage(); $message = $e->getMessage();
if (str_contains($message, 'Bcc')) { if (str_contains($message, 'Bcc')) {
@ -158,7 +157,7 @@ class AdminEventHandler
Log::debug(sprintf('Will send %s as a notification.', $class)); Log::debug(sprintf('Will send %s as a notification.', $class));
try { try {
Notification::send($event->owner, new $class($event->owner)); Notification::send($event->owner, new $class());
} catch (\Exception $e) { // @phpstan-ignore-line } catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage(); $message = $e->getMessage();
if (str_contains($message, 'Bcc')) { if (str_contains($message, 'Bcc')) {

View File

@ -232,7 +232,7 @@ class UserEventHandler
$owner = $event->owner; $owner = $event->owner;
try { try {
Notification::send($owner, new AdminRegistrationNotification($event->owner, $event->user)); Notification::send($owner, new AdminRegistrationNotification($event->user));
} catch (\Exception $e) { // @phpstan-ignore-line } catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage(); $message = $e->getMessage();
if (str_contains($message, 'Bcc')) { if (str_contains($message, 'Bcc')) {
@ -428,7 +428,7 @@ class UserEventHandler
Log::debug(sprintf('Will send %s as a notification.', $class)); Log::debug(sprintf('Will send %s as a notification.', $class));
try { try {
Notification::send($event->user, new $class($event->user)); Notification::send($event->user, new $class());
} catch (\Exception $e) { // @phpstan-ignore-line } catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage(); $message = $e->getMessage();
if (str_contains($message, 'Bcc')) { if (str_contains($message, 'Bcc')) {

View File

@ -46,12 +46,10 @@ class UserInvitation extends Notification
use Queueable; use Queueable;
private InvitedUser $invitee; private InvitedUser $invitee;
private OwnerNotifiable $owner;
public function __construct(OwnerNotifiable $owner, InvitedUser $invitee) public function __construct(InvitedUser $invitee)
{ {
$this->invitee = $invitee; $this->invitee = $invitee;
$this->owner = $owner;
} }
/** /**

View File

@ -45,13 +45,11 @@ class UserRegistration extends Notification
{ {
use Queueable; use Queueable;
private OwnerNotifiable $owner;
private User $user; private User $user;
public function __construct(OwnerNotifiable $owner, User $user) public function __construct( User $user)
{ {
$this->user = $user; $this->user = $user;
$this->owner = $owner;
} }
/** /**

View File

@ -36,13 +36,6 @@ class OwnerTestNotificationEmail extends Notification
{ {
use Queueable; use Queueable;
private OwnerNotifiable $owner;
public function __construct(OwnerNotifiable $owner)
{
$this->owner = $owner;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -40,13 +40,6 @@ class OwnerTestNotificationNtfy extends Notification
{ {
use Queueable; use Queueable;
public OwnerNotifiable $owner;
public function __construct(OwnerNotifiable $owner)
{
$this->owner = $owner;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
* *

View File

@ -40,13 +40,6 @@ class OwnerTestNotificationPushover extends Notification
{ {
use Queueable; use Queueable;
private OwnerNotifiable $owner;
public function __construct(OwnerNotifiable $owner)
{
$this->owner = $owner;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -38,13 +38,6 @@ class OwnerTestNotificationSlack extends Notification
{ {
use Queueable; use Queueable;
private OwnerNotifiable $owner;
public function __construct(OwnerNotifiable $owner)
{
$this->owner = $owner;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -36,13 +36,6 @@ class UserTestNotificationEmail extends Notification
{ {
use Queueable; use Queueable;
private User $user;
public function __construct(User $user)
{
$this->user = $user;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -40,13 +40,6 @@ class UserTestNotificationNtfy extends Notification
{ {
use Queueable; use Queueable;
public User $user;
public function __construct(User $user)
{
$this->user = $user;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -40,13 +40,6 @@ class UserTestNotificationPushover extends Notification
{ {
use Queueable; use Queueable;
private User $user;
public function __construct(User $user)
{
$this->user = $user;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -38,13 +38,6 @@ class UserTestNotificationSlack extends Notification
{ {
use Queueable; use Queueable;
private User $user;
public function __construct(User $user)
{
$this->user = $user;
}
/** /**
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */

View File

@ -34,15 +34,13 @@ class UserPolicy
public function view(User $user, User $user1): bool public function view(User $user, User $user1): bool
{ {
return true; return true;
// return auth()->check() && $user->id === $account->user_id;
return auth()->check() && $user->id === $account->user_id;
} }
public function viewAccounts(User $user): bool public function viewAccounts(User $user): bool
{ {
return true; return true;
// return auth()->check();
return auth()->check();
} }
/** /**
@ -53,7 +51,6 @@ class UserPolicy
public function viewAny(): bool public function viewAny(): bool
{ {
return true; return true;
// return auth()->check();
return auth()->check();
} }
} }

View File

@ -209,7 +209,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
*/ */
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget
{ {
/** @var AvailableBudget */ /** @var null|AvailableBudget */
$availableBudget = $this->user->availableBudgets() $availableBudget = $this->user->availableBudgets()
->where('transaction_currency_id', $currency->id) ->where('transaction_currency_id', $currency->id)
->where('start_date', $start->format('Y-m-d')) ->where('start_date', $start->format('Y-m-d'))

View File

@ -68,9 +68,9 @@ trait ModifiesPiggyBanks
$pivot->native_current_amount = null; $pivot->native_current_amount = null;
// also update native_current_amount. // also update native_current_amount.
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup); $userCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
if ($userCurrency->id !== $piggyBank->transaction_currency_id) { if ($userCurrency->id !== $piggyBank->transaction_currency_id) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount); $pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount);
} }
@ -91,9 +91,9 @@ trait ModifiesPiggyBanks
$pivot->native_current_amount = null; $pivot->native_current_amount = null;
// also update native_current_amount. // also update native_current_amount.
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup); $userCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
if ($userCurrency->id !== $piggyBank->transaction_currency_id) { if ($userCurrency->id !== $piggyBank->transaction_currency_id) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount); $pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount);
} }
@ -125,8 +125,8 @@ trait ModifiesPiggyBanks
Log::debug(sprintf('Maximum amount: %s', $maxAmount)); Log::debug(sprintf('Maximum amount: %s', $maxAmount));
} }
$compare = bccomp($amount, $maxAmount); $compare = bccomp($amount, $maxAmount);
$result = $compare <= 0; $result = $compare <= 0;
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true))); Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
@ -160,11 +160,11 @@ trait ModifiesPiggyBanks
public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank
{ {
$repetition = $this->getRepetition($piggyBank); $repetition = $this->getRepetition($piggyBank);
if (null === $repetition) { if (null === $repetition) {
return $piggyBank; return $piggyBank;
} }
$max = $piggyBank->target_amount; $max = $piggyBank->target_amount;
if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) { if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) {
$amount = $max; $amount = $max;
} }
@ -207,14 +207,14 @@ trait ModifiesPiggyBanks
public function update(PiggyBank $piggyBank, array $data): PiggyBank public function update(PiggyBank $piggyBank, array $data): PiggyBank
{ {
$piggyBank = $this->updateProperties($piggyBank, $data); $piggyBank = $this->updateProperties($piggyBank, $data);
if (array_key_exists('notes', $data)) { if (array_key_exists('notes', $data)) {
$this->updateNote($piggyBank, (string) $data['notes']); $this->updateNote($piggyBank, (string) $data['notes']);
} }
// update the order of the piggy bank: // update the order of the piggy bank:
$oldOrder = $piggyBank->order; $oldOrder = $piggyBank->order;
$newOrder = (int) ($data['order'] ?? $oldOrder); $newOrder = (int) ($data['order'] ?? $oldOrder);
if ($oldOrder !== $newOrder) { if ($oldOrder !== $newOrder) {
$this->setOrder($piggyBank, $newOrder); $this->setOrder($piggyBank, $newOrder);
} }
@ -306,7 +306,7 @@ trait ModifiesPiggyBanks
return; return;
} }
$dbNote = $piggyBank->notes()->first(); $dbNote = $piggyBank->notes()->first();
if (null === $dbNote) { if (null === $dbNote) {
$dbNote = new Note(); $dbNote = new Note();
$dbNote->noteable()->associate($piggyBank); $dbNote->noteable()->associate($piggyBank);
@ -317,16 +317,15 @@ trait ModifiesPiggyBanks
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
{ {
$oldOrder = $piggyBank->order; $oldOrder = $piggyBank->order;
// Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); // Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
if ($newOrder > $oldOrder) { if ($newOrder > $oldOrder) {
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id) ->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder) ->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id) ->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->decrement('piggy_banks.order') ->distinct()->decrement('piggy_banks.order');
;
$piggyBank->order = $newOrder; $piggyBank->order = $newOrder;
Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
@ -335,12 +334,11 @@ trait ModifiesPiggyBanks
return true; return true;
} }
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id) ->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder) ->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id) ->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->increment('piggy_banks.order') ->distinct()->increment('piggy_banks.order');
;
$piggyBank->order = $newOrder; $piggyBank->order = $newOrder;
Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
@ -360,10 +358,8 @@ trait ModifiesPiggyBanks
return; return;
} }
// if this account contains less than the amount, remove the current amount, update the amount and continue. // if this account contains less than the amount, remove the current amount, update the amount and continue.
if (bccomp($current, $amount) < 1) { $this->removeAmount($piggyBank, $account, $current);
$this->removeAmount($piggyBank, $account, $current); $amount = bcsub($amount, $current);
$amount = bcsub($amount, $current);
}
} }
} }
} }

View File

@ -1,206 +0,0 @@
<?php
/*
* IsUniqueAccount.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Rules\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\User;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* @method fail(string $string)
*/
class IsUniqueAccount implements ValidationRule, DataAwareRule
{
protected array $data = [];
protected \Closure $fail;
#[\Override]
public function setData(array $data): self // @phpstan-ignore-line
{
$this->data = $data;
return $this;
}
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
return;
$this->fail = $fail;
// because a user does not have to be logged in (tests and what-not).
if (!auth()->check()) {
app('log')->debug('validateUniqueAccountForUser::anon');
$fail('validation.nog_logged_in')->translate();
return;
}
if (array_key_exists('type', $this->data)) {
app('log')->debug('validateUniqueAccountForUser::typeString');
$this->validateByAccountTypeString($value, $parameters, (string) $this->data['type']);
}
if (array_key_exists('account_type_id', $this->data)) {
app('log')->debug('validateUniqueAccountForUser::typeId');
$this->validateByAccountTypeId($value, $parameters);
}
$parameterId = $parameters[0] ?? null;
if (null !== $parameterId) {
app('log')->debug('validateUniqueAccountForUser::paramId');
$this->validateByParameterId((int) $parameterId, $value);
}
if (array_key_exists('id', $this->data)) {
app('log')->debug('validateUniqueAccountForUser::accountId');
$this->validateByAccountId($value);
}
// without type, just try to validate the name.
app('log')->debug('validateUniqueAccountForUser::accountName');
$this->validateByAccountName($value);
}
/**
* TODO duplicate from old validation class.
*/
private function validateByAccountTypeString(string $value, array $parameters, string $type): bool
{
/** @var null|array $search */
$search = config('firefly.accountTypeByIdentifier.%s', $type);
if (null === $search) {
return false;
}
$accountTypes = AccountType::whereIn('type', $search)->get();
$ignore = (int) ($parameters[0] ?? 0.0);
$accountTypeIds = $accountTypes->pluck('id')->toArray();
/** @var null|Account $result */
$result = auth()->user()->accounts()->whereIn('account_type_id', $accountTypeIds)->where('id', '!=', $ignore)
->where('name', $value)
->first()
;
return null === $result;
}
/**
* TODO Duplicate from old validation class.
*
* @param mixed $value
* @param mixed $parameters
*/
private function validateByAccountTypeId($value, $parameters): bool
{
$type = AccountType::find($this->data['account_type_id'])->first();
$ignore = (int) ($parameters[0] ?? 0.0);
/** @var null|Account $result */
$result = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)
->where('name', $value)
->first()
;
return null === $result;
}
/**
* TODO Duplicate from old validation class.
*
* @param mixed $value
*/
private function validateByParameterId(int $accountId, $value): bool
{
/** @var Account $existingAccount */
$existingAccount = Account::find($accountId);
$type = $existingAccount->accountType;
$ignore = $existingAccount->id;
$entry = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)
->where('name', $value)
->first()
;
return null === $entry;
}
/**
* TODO Duplicate from old validation class.
*
* @param mixed $value
*/
private function validateByAccountId($value): bool
{
/** @var Account $existingAccount */
$existingAccount = Account::find($this->data['id']);
$type = $existingAccount->accountType;
$ignore = $existingAccount->id;
$entry = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)
->where('name', $value)
->first()
;
return null === $entry;
}
/**
* TODO is duplicate
* TODO does not take group into account. Must be made group aware.
*/
private function validateByAccountName(string $value): bool
{
return 0 === auth()->user()->accounts()->where('name', $value)->count();
}
/**
* TODO duplicate from old validation class.
*/
private function validateAccountAnonymously(): bool
{
if (!array_key_exists('user_id', $this->data)) {
$this->fail('No user ID provided.');
return false;
}
/** @var User $user */
$user = User::find($this->data['user_id']);
$type = AccountType::find($this->data['account_type_id'])->first();
$value = $this->data['name'];
/** @var null|Account $result */
$result = $user->accounts()->where('account_type_id', $type->id)->where('name', $value)->first();
return null === $result;
}
}

View File

@ -79,8 +79,8 @@ class ValidRecurrenceRepetitionValue implements ValidationRule
if (2 !== count($parameters)) { if (2 !== count($parameters)) {
return false; return false;
} }
$nthDay = (int) ($parameters[0] ?? 0.0); $nthDay = (int) $parameters[0];
$dayOfWeek = (int) ($parameters[1] ?? 0.0); $dayOfWeek = (int) $parameters[1];
if ($nthDay < 1 || $nthDay > 5) { if ($nthDay < 1 || $nthDay > 5) {
return false; return false;
} }

View File

@ -177,7 +177,7 @@ class Amount
return $cache->get(); return $cache->get();
} }
/** @var TransactionCurrency $default */ /** @var TransactionCurrency|null $default */
$default = $userGroup->currencies()->where('group_default', true)->first(); $default = $userGroup->currencies()->where('group_default', true)->first();
if (null === $default) { if (null === $default) {
$default = $this->getSystemCurrency(); $default = $this->getSystemCurrency();

View File

@ -33,7 +33,7 @@ use FireflyIII\Exceptions\IntervalException;
class Calculator class Calculator
{ {
public const int DEFAULT_INTERVAL = 1; public const int DEFAULT_INTERVAL = 1;
private static ?\SplObjectStorage $intervalMap = null; private static ?\SplObjectStorage $intervalMap = null; // @phpstan-ignore-line
private static array $intervals = []; private static array $intervals = [];
/** /**

View File

@ -1,168 +0,0 @@
<?php
/*
* ConvertsExchangeRates.php
* Copyright (c) 2022 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Http\Api;
use Carbon\Carbon;
use FireflyIII\Models\TransactionCurrency;
/**
* Trait ConvertsExchangeRates
*/
trait ConvertsExchangeRates
{
private ?bool $enabled = null;
/**
* @deprecated
*/
public function cerChartSet(array $set): array
{
if (null === $this->enabled) {
$this->getPreference();
}
// if not enabled, return the same array but without conversion:
return $set;
$this->enabled = false;
if (false === $this->enabled) {
$set['converted'] = false;
return $set;
}
$set['converted'] = true;
/** @var TransactionCurrency $native */
$native = app('amount')->getDefaultCurrency();
$currency = $this->getCurrency((int) $set['currency_id']);
if ($native->id === $currency->id) {
$set['native_currency_id'] = (string) $currency->id;
$set['native_currency_code'] = $currency->code;
$set['native_currency_symbol'] = $currency->symbol;
$set['native_currency_decimal_places'] = $currency->decimal_places;
return $set;
}
foreach ($set['entries'] as $date => $entry) {
$carbon = Carbon::createFromFormat(\DateTimeInterface::ATOM, $date);
$rate = $this->getRate($currency, $native, $carbon);
$rate = '0' === $rate ? '1' : $rate;
app('log')->debug(sprintf('bcmul("%s", "%s")', (string) $entry, $rate));
$set['entries'][$date] = (float) bcmul((string) $entry, $rate);
}
return $set;
}
/**
* @deprecated
*/
private function getPreference(): void
{
$this->enabled = config('cer.currency_conversion');
}
/**
* @deprecated
*/
private function getCurrency(int $currencyId): TransactionCurrency
{
$result = TransactionCurrency::find($currencyId);
if (null === $result) {
return app('amount')->getDefaultCurrency();
}
return $result;
}
/**
* For a sum of entries, get the exchange rate to the native currency of
* the user.
*
* @deprecated
*/
public function cerSum(array $entries): array
{
if (null === $this->enabled) {
$this->getPreference();
}
// if false, return the same array without conversion info
if (false === $this->enabled) {
$return = [];
/** @var array $entry */
foreach ($entries as $entry) {
$entry['converted'] = false;
$return[] = $entry;
}
return $return;
}
/** @var TransactionCurrency $native */
$native = app('amount')->getDefaultCurrency();
$return = [];
/** @var array $entry */
foreach ($entries as $entry) {
$currency = $this->getCurrency((int) $entry['id']);
if ($currency->id !== $native->id) {
$amount = $this->convertAmount($entry['sum'], $currency, $native);
$entry['converted'] = true;
$entry['native_sum'] = $amount;
$entry['native_currency_id'] = (string) $native->id;
$entry['native_currency_name'] = $native->name;
$entry['native_currency_symbol'] = $native->symbol;
$entry['native_currency_code'] = $native->code;
$entry['native_currency_decimal_places'] = $native->decimal_places;
}
if ($currency->id === $native->id) {
$entry['converted'] = false;
$entry['native_sum'] = $entry['sum'];
$entry['native_currency_id'] = (string) $native->id;
$entry['native_currency_name'] = $native->name;
$entry['native_currency_symbol'] = $native->symbol;
$entry['native_currency_code'] = $native->code;
$entry['native_currency_decimal_places'] = $native->decimal_places;
}
$return[] = $entry;
}
return $return;
}
/**
* @deprecated
*/
private function convertAmount(string $amount, TransactionCurrency $from, TransactionCurrency $to, ?Carbon $date = null): string
{
app('log')->debug(sprintf('Converting %s from %s to %s', $amount, $from->code, $to->code));
$date ??= today(config('app.timezone'));
$rate = $this->getRate($from, $to, $date);
return bcmul($amount, $rate);
}
}

View File

@ -40,10 +40,7 @@ use Illuminate\Support\Facades\Log;
class ExchangeRateConverter class ExchangeRateConverter
{ {
// use ConvertsExchangeRates; // use ConvertsExchangeRates;
private array $fallback = [];
private bool $ignoreSettings = false; private bool $ignoreSettings = false;
private bool $isPrepared = false;
private bool $noPreparedRates = false;
private array $prepared = []; private array $prepared = [];
private int $queryCount = 0; private int $queryCount = 0;
@ -275,84 +272,6 @@ class ExchangeRateConverter
return $euro->id; return $euro->id;
} }
/**
* @throws FireflyException
*/
public function prepare(TransactionCurrency $from, TransactionCurrency $to, Carbon $start, Carbon $end): void
{
if (false === $this->enabled()) {
return;
}
Log::debug('prepare()');
$start->startOfDay();
$end->endOfDay();
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
$set = $this->userGroup
->currencyExchangeRates()
->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id)
->where('date', '<=', $end->format('Y-m-d'))
->where('date', '>=', $start->format('Y-m-d'))
->orderBy('date', 'DESC')->get()
;
++$this->queryCount;
if (0 === $set->count()) {
Log::debug('No prepared rates found in this period, use the fallback');
$this->fallback($from, $to, $start);
$this->noPreparedRates = true;
$this->isPrepared = true;
Log::debug('prepare DONE()');
return;
}
$this->isPrepared = true;
// so there is a fallback just in case. Now loop the set of rates we DO have.
$temp = [];
$count = 0;
foreach ($set as $rate) {
$date = $rate->date->format('Y-m-d');
$temp[$date] ??= [
$from->id => [
$to->id => $rate->rate,
],
];
++$count;
}
Log::debug(sprintf('Found %d rates in this period.', $count));
$currentStart = clone $start;
while ($currentStart->lte($end)) {
$currentDate = $currentStart->format('Y-m-d');
$this->prepared[$currentDate] ??= [];
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
// fill from temp or fallback or from temp (see before)
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
}
$currentStart->addDay();
}
}
/**
* If there are no exchange rate in the "prepare" array, future searches for any exchange rate
* will result in nothing: otherwise the preparation had been unnecessary. So, to fix this Firefly III
* will set two fallback currency exchange rates, A > B and B > A using the regular getCurrencyRate method.
*
* This method in turn will fall back on the default exchange rate (if present) or on "1" if necessary.
*
* @throws FireflyException
*/
private function fallback(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): void
{
Log::debug('fallback()');
$fallback = $this->getRate($from, $to, $date);
$fallback = 0 === bccomp('0', $fallback) ? '1' : $fallback;
$this->fallback[$from->id][$to->id] = $fallback;
$this->fallback[$to->id][$from->id] = bcdiv('1', $fallback);
Log::debug(sprintf('Fallback rate %s > %s = %s', $from->code, $to->code, $fallback));
Log::debug(sprintf('Fallback rate %s > %s = %s', $to->code, $from->code, bcdiv('1', $fallback)));
}
public function setIgnoreSettings(bool $ignoreSettings): void public function setIgnoreSettings(bool $ignoreSettings): void
{ {
$this->ignoreSettings = $ignoreSettings; $this->ignoreSettings = $ignoreSettings;

View File

@ -1,46 +0,0 @@
<?php
/*
* CollectsCustomParameters.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
use Carbon\Carbon;
trait CollectsCustomParameters
{
protected function getOtherParams(array $params): array
{
$return = [];
if (array_key_exists('startPeriod', $params)) {
$return['start'] = Carbon::parse($params['startPeriod']);
}
if (array_key_exists('endPeriod', $params)) {
$return['end'] = Carbon::parse($params['endPeriod']);
}
if (array_key_exists('currentMoment', $params)) {
$return['today'] = Carbon::parse($params['currentMoment']);
}
return $return;
}
}

View File

@ -1,63 +0,0 @@
<?php
/*
* UserGroupDetectable.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi\Concerns;
use FireflyIII\Models\UserGroup;
use FireflyIII\User;
trait UserGroupDetectable
{
/**
* Return the user group or NULL if none is set.
* Will throw exception if invalid.
* TODO Duplicate from API v2 code.
*/
public function detectUserGroup(): ?UserGroup
{
/** @var User $user */
$user = auth()->user();
app('log')->debug('Now in detectUserGroup()');
/** @var null|UserGroup $userGroup */
$userGroup = request()->route()?->parameter('userGroup');
if (null === $userGroup) {
app('log')->debug('Request class has no userGroup parameter, but perhaps there is a parameter.');
$userGroupId = (int) request()->get('user_group_id');
if (0 === $userGroupId) {
app('log')->debug(sprintf('Request class has no user_group_id parameter, grab default from user (group #%d).', $user->user_group_id));
$userGroupId = (int) $user->user_group_id;
}
$userGroup = UserGroup::find($userGroupId);
if (null === $userGroup) {
app('log')->error(sprintf('Request class has user_group_id (#%d), but group does not exist.', $userGroupId));
return null;
}
app('log')->debug('Request class has valid user_group_id.');
}
return $userGroup;
}
}

View File

@ -1,49 +0,0 @@
<?php
/*
* UsergroupAware.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi\Concerns;
use FireflyIII\Models\UserGroup;
trait UsergroupAware
{
protected UserGroup $userGroup;
public function getUserGroup(): UserGroup
{
return $this->userGroup;
}
public function setUserGroup(UserGroup $userGroup): void
{
$this->userGroup = $userGroup;
}
public function withUserGroup(UserGroup $userGroup): self
{
$this->userGroup = $userGroup;
return $this;
}
}

View File

@ -1,138 +0,0 @@
<?php
/*
* ExpandsQuery.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
use FireflyIII\Models\Account;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Log;
trait ExpandsQuery
{
use AccountFilter;
final protected function addFilterParams(string $class, Builder $query, ?FilterParameters $filters): Builder
{
Log::debug(__METHOD__);
if (null === $filters) {
return $query;
}
if (0 === count($filters->all())) {
return $query;
}
// parse filters valid for this class.
$parsed = $this->parseAllFilters($class, $filters);
// expand query for each query filter
$config = config('api.valid_query_filters')[$class];
$query->where(function (Builder $q) use ($config, $parsed): void {
foreach ($parsed as $key => $filter) {
if (in_array($key, $config, true)) {
Log::debug(sprintf('Add query filter "%s"', $key));
// add type to query:
foreach ($filter as $value) {
$q->whereLike($key, sprintf('%%%s%%', $value));
}
}
}
});
// TODO this is special treatment, but alas, unavoidable right now.
if (Account::class === $class && array_key_exists('type', $parsed)) {
if (count($parsed['type']) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $parsed['type']);
}
}
return $query;
}
private function parseAllFilters(string $class, FilterParameters $filters): array
{
$config = config('api.valid_api_filters')[$class];
$parsed = [];
foreach ($filters->all() as $filter) {
$key = $filter->key();
if (!in_array($key, $config, true)) {
continue;
}
// make array if not array:
$value = $filter->value();
if (null === $value) {
continue;
}
if (!is_array($value)) {
$value = [$value];
}
switch ($filter->key()) {
case 'name':
$parsed['name'] = $value;
break;
case 'type':
$parsed['type'] = $this->parseAccountTypeFilter($value);
break;
}
}
return $parsed;
}
private function parseAccountTypeFilter(array $value): array
{
$return = [];
foreach ($value as $entry) {
$return = array_merge($return, $this->mapAccountTypes($entry));
}
return array_unique($return);
}
final protected function addPagination(Builder $query, array $pagination): Builder
{
$skip = ($pagination['number'] - 1) * $pagination['size'];
return $query->skip($skip)->take($pagination['size']);
}
final protected function addSortParams(string $class, Builder $query, ?SortFields $sort): Builder
{
$config = config('api.valid_query_sort')[$class] ?? [];
if (null === $sort) {
return $query;
}
foreach ($sort->all() as $sortField) {
if (in_array($sortField->name(), $config, true)) {
$query->orderBy($sortField->name(), $sortField->isAscending() ? 'ASC' : 'DESC');
}
}
return $query;
}
}

View File

@ -1,56 +0,0 @@
<?php
/*
* FiltersPagination.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
trait FiltersPagination
{
protected function filtersPagination(?array $pagination): array
{
if (null === $pagination) {
return [
'number' => 1,
'size' => $this->getPageSize(),
];
}
// cleanup page number
$pagination['number'] = (int) ($pagination['number'] ?? 1);
$pagination['number'] = min(65536, max($pagination['number'], 1));
// clean up page size
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
$pagination['size'] = min(1337, max($pagination['size'], 1));
return $pagination;
}
private function getPageSize(): int
{
if (auth()->check()) {
return (int) app('preferences')->get('listPageSize', 50)->data;
}
return 50;
}
}

View File

@ -1,48 +0,0 @@
<?php
/*
* SortsCollection.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
trait SortsCollection
{
protected function sortCollection(string $class, Collection $collection, ?SortFields $sortFields): Collection
{
Log::debug(__METHOD__);
$config = config('api.valid_api_sort')[$class] ?? [];
if (null === $sortFields) {
return $collection;
}
foreach ($sortFields->all() as $sortField) {
if (in_array($sortField->name(), $config, true)) {
Log::debug(sprintf('Sort collection by "%s"', $sortField->name()));
$collection = $sortField->isAscending() ? $collection->sortBy($sortField->name()) : $collection->sortByDesc($sortField->name());
}
}
return $collection;
}
}

View File

@ -1,130 +0,0 @@
<?php
/*
* SortsQueryResults.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
trait SortsQueryResults
{
final protected function postQuerySort(string $class, Collection $collection, SortFields $parameters): Collection
{
Log::debug(__METHOD__);
foreach ($parameters->all() as $field) {
$collection = $this->sortQueryCollection($class, $collection, $field);
}
return $collection;
}
/**
* TODO improve this.
*/
private function sortQueryCollection(string $class, Collection $collection, SortField $field): Collection
{
// here be custom sort things.
// sort by balance
if (Account::class === $class && 'balance' === $field->name()) {
$ascending = $field->isAscending();
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftSum = $this->sumBalance($left->balance);
$rightSum = $this->sumBalance($right->balance);
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
});
}
if (Account::class === $class && 'balance_difference' === $field->name()) {
$ascending = $field->isAscending();
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftSum = $this->sumBalanceDifference($left->balance);
$rightSum = $this->sumBalanceDifference($right->balance);
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
});
}
// sort by account number
if (Account::class === $class && 'account_number' === $field->name()) {
$ascending = $field->isAscending();
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftNr = sprintf('%s%s', $left->iban, $left->account_number);
$rightNr = sprintf('%s%s', $right->iban, $right->account_number);
return $ascending ? strcmp($leftNr, $rightNr) : strcmp($rightNr, $leftNr);
});
}
// sort by last activity
if (Account::class === $class && 'last_activity' === $field->name()) {
$ascending = $field->isAscending();
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftNr = (int) $left->last_activity?->format('U');
$rightNr = (int) $right->last_activity?->format('U');
if ($ascending) {
return $leftNr <=> $rightNr;
}
return $rightNr <=> $leftNr;
// return (int) ($ascending ? $rightNr < $leftNr : $leftNr < $rightNr );
});
}
// sort by balance difference.
return $collection;
}
private function sumBalance(?array $balance): string
{
if (null === $balance) {
return '-10000000000'; // minus one billion
}
if (0 === count($balance)) {
return '-10000000000'; // minus one billion
}
$sum = '0';
foreach ($balance as $entry) {
$sum = bcadd($sum, $entry['balance']);
}
return $sum;
}
private function sumBalanceDifference(?array $balance): string
{
if (null === $balance) {
return '-10000000000'; // minus one billion
}
if (0 === count($balance)) {
return '-10000000000'; // minus one billion
}
$sum = '0';
foreach ($balance as $entry) {
$sum = bcadd($sum, $entry['balance_difference']);
}
return $sum;
}
}

View File

@ -1,48 +0,0 @@
<?php
/*
* ValidateSortParameters.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
use Illuminate\Support\Facades\Log;
trait ValidateSortParameters
{
public function needsFullDataset(string $class, ?SortFields $params): bool
{
Log::debug(__METHOD__);
if (null === $params) {
return false;
}
$config = config('api.full_data_set')[$class] ?? [];
foreach ($params->all() as $field) {
if (in_array($field->name(), $config, true)) {
Log::debug('TRUE');
return true;
}
}
return false;
}
}

View File

@ -156,7 +156,7 @@ class AccountBalanceCalculator
* @var array $currencies * @var array $currencies
*/ */
foreach ($balances as $accountId => $currencies) { foreach ($balances as $accountId => $currencies) {
/** @var Account $account */ /** @var Account|null $account */
$account = Account::find($accountId); $account = Account::find($accountId);
if (null === $account) { if (null === $account) {
Log::error(sprintf('Could not find account #%d, will not save account balance.', $accountId)); Log::error(sprintf('Could not find account #%d, will not save account balance.', $accountId));
@ -169,7 +169,7 @@ class AccountBalanceCalculator
* @var array $balance * @var array $balance
*/ */
foreach ($currencies as $currencyId => $balance) { foreach ($currencies as $currencyId => $balance) {
/** @var TransactionCurrency $currency */ /** @var TransactionCurrency|null $currency */
$currency = TransactionCurrency::find($currencyId); $currency = TransactionCurrency::find($currencyId);
if (null === $currency) { if (null === $currency) {
Log::error(sprintf('Could not find currency #%d, will not save account balance.', $currencyId)); Log::error(sprintf('Could not find currency #%d, will not save account balance.', $currencyId));
@ -208,43 +208,4 @@ class AccountBalanceCalculator
$object->optimizedCalculation($accounts, $transactionJournal->date); $object->optimizedCalculation($accounts, $transactionJournal->date);
} }
private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance
{
$query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency);
$entry = $query->first();
if (null !== $entry) {
// Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
return $entry;
}
$entry = new AccountBalance();
$entry->title = 'balance';
$entry->account_id = $account;
$entry->transaction_currency_id = $currency;
$entry->balance = '0';
$entry->save();
// Log::debug(sprintf('Created new account balance for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
return $entry;
}
private function getAccountBalanceByJournal(string $title, int $account, int $journal, int $currency): AccountBalance
{
$query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency);
$entry = $query->first();
if (null !== $entry) {
return $entry;
}
$entry = new AccountBalance();
$entry->title = $title;
$entry->account_id = $account;
$entry->transaction_journal_id = $journal;
$entry->transaction_currency_id = $currency;
$entry->balance = '0';
$entry->save();
return $entry;
}
} }

View File

@ -433,7 +433,7 @@ class Navigation
*/ */
public function getViewRange(bool $correct): string public function getViewRange(bool $correct): string
{ {
$range = app('preferences')->get('viewRange', '1M')?->data ?? '1M'; $range = app('preferences')->get('viewRange', '1M')->data ?? '1M';
if (is_array($range)) { if (is_array($range)) {
$range = '1M'; $range = '1M';
} }

View File

@ -1,30 +0,0 @@
<?php
/**
* ConvertAPIDataTypes.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Request;
/**
* Trait ConvertAPIDataTypes
*/
trait ConvertAPIDataTypes {}

View File

@ -55,22 +55,6 @@ class Steam
return TransactionCurrency::find((int) $result->data); return TransactionCurrency::find((int) $result->data);
} }
private function sumTransactions(array $transactions, string $key): string
{
$sum = '0';
/** @var array $transaction */
foreach ($transactions as $transaction) {
$value = (string) ($transaction[$key] ?? '0');
$value = '' === $value ? '0' : $value;
$sum = bcadd($sum, $value);
// Log::debug(sprintf('Add value from "%s": %s', $key, $value));
}
Log::debug(sprintf('Sum of "%s"-fields is %s', $key, $sum));
return $sum;
}
public function finalAccountBalanceInRange(Account $account, Carbon $start, Carbon $end, bool $convertToNative): array public function finalAccountBalanceInRange(Account $account, Carbon $start, Carbon $end, bool $convertToNative): array
{ {
// expand period. // expand period.

View File

@ -38,7 +38,7 @@ use Illuminate\Support\Facades\Log;
/** /**
* Class UpdatePiggybank * Class UpdatePiggybank
*/ */
class UpdatePiggybank implements ActionInterface class UpdatePiggyBank implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;