Code cleanup

This commit is contained in:
James Cole
2024-12-22 08:43:12 +01:00
parent 5751f7e5a3
commit 565bd87959
574 changed files with 4600 additions and 4604 deletions

View File

@@ -29,7 +29,6 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;

View File

@@ -59,6 +59,38 @@ class ListController extends Controller
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
*
* List single resource.
*
* @throws FireflyException
*/
public function accounts(PiggyBank $piggyBank): JsonResponse
{
// types to get, page size:
$pageSize = $this->parameters->get('limit');
$manager = $this->getManager();
$collection = $piggyBank->accounts;
$count = $collection->count();
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($events, $transformer, 'accounts');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAttachmentByPiggyBank
@@ -119,36 +151,4 @@ class ListController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
*
* List single resource.
*
* @throws FireflyException
*/
public function accounts(PiggyBank $piggyBank): JsonResponse
{
// types to get, page size:
$pageSize = $this->parameters->get('limit');
$manager = $this->getManager();
$collection = $piggyBank->accounts;
$count = $collection->count();
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($events, $transformer, 'accounts');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -65,6 +65,25 @@ class StoreRequest extends FormRequest
return $data;
}
private function parseAccounts(mixed $array): array
{
if (!is_array($array)) {
return [];
}
$return = [];
foreach ($array as $entry) {
if (!is_array($entry)) {
continue;
}
$return[] = [
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
];
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
@@ -130,25 +149,6 @@ class StoreRequest extends FormRequest
}
}
private function parseAccounts(mixed $array): array
{
if (!is_array($array)) {
return [];
}
$return = [];
foreach ($array as $entry) {
if (!is_array($entry)) {
continue;
}
$return[] = [
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
];
}
return $return;
}
private function getCurrencyFromData(array $data): TransactionCurrency
{
if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {

View File

@@ -40,9 +40,9 @@ use Illuminate\Support\Facades\Log;
*/
class AccountController extends Controller
{
private AccountRepositoryInterface $repository;
private TransactionCurrency $default;
private ExchangeRateConverter $converter;
private TransactionCurrency $default;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@@ -45,9 +45,9 @@ class AccountController extends Controller
use CollectsAccountsFromFilter;
use ValidatesUserGroupTrait;
private AccountRepositoryInterface $repository;
private ChartData $chartData;
private TransactionCurrency $default;
private AccountRepositoryInterface $repository;
public function __construct()
{

View File

@@ -45,9 +45,10 @@ class BalanceController extends Controller
use CleansChartData;
use CollectsAccountsFromFilter;
private AccountRepositoryInterface $repository;
private GroupCollectorInterface $collector;
private ChartData $chartData;
private GroupCollectorInterface $collector;
private AccountRepositoryInterface $repository;
// private TransactionCurrency $default;
public function __construct()

View File

@@ -55,8 +55,8 @@ class Controller extends BaseController
use ValidatesUserGroupTrait;
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected ParameterBag $parameters;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
protected ParameterBag $parameters;
public function __construct()
{
@@ -92,8 +92,8 @@ class Controller extends BaseController
if ($page < 1) {
$page = 1;
}
if ($page > pow(2,16)) {
$page = pow(2,16);
if ($page > 2 ** 16) {
$page = 2 ** 16;
}
$bag->set('page', $page);

View File

@@ -48,6 +48,7 @@ class AccountController extends Controller
use Actions\DetachRelationship;
use Actions\FetchMany;
// use Actions\FetchOne;
use Actions\FetchRelated;
use Actions\FetchRelationship;

View File

@@ -36,9 +36,8 @@ use Illuminate\Support\Facades\Log;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@@ -39,9 +39,8 @@ use Illuminate\Http\JsonResponse;
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@@ -36,6 +36,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;

View File

@@ -38,6 +38,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
class ShowController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;

View File

@@ -35,9 +35,8 @@ use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'transaction-currencies';
private CurrencyRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
private CurrencyRepositoryInterface $repository;
public function __construct()
{

View File

@@ -73,6 +73,16 @@ class AutocompleteRequest extends FormRequest
return $array;
}
private function getAccountTypeParameter(array $types): array
{
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
public function rules(): array
{
$valid = array_keys($this->types);
@@ -86,14 +96,4 @@ class AutocompleteRequest extends FormRequest
'transaction_types' => 'nullable|in:todo',
];
}
private function getAccountTypeParameter(array $types): array
{
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
}

View File

@@ -40,6 +40,7 @@ class BalanceChartRequest extends FormRequest
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**

View File

@@ -62,6 +62,113 @@ class FixUnevenAmount extends Command
return 0;
}
private function convertOldStyleTransfers(): void
{
Log::debug('convertOldStyleTransfers()');
// select transactions with a foreign amount and a foreign currency. and it's a transfer. and they are different.
$transactions = Transaction::distinct()
->leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionTypeEnum::TRANSFER->value)
->whereNotNull('foreign_currency_id')
->whereNotNull('foreign_amount')->get(['transactions.transaction_journal_id'])
;
$count = 0;
Log::debug(sprintf('Found %d potential journal(s)', $transactions->count()));
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($transaction->transaction_journal_id);
if (null === $journal) {
Log::debug('Found no journal, continue.');
continue;
}
// needs to be a transfer.
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
Log::debug('Must be a transfer, continue.');
continue;
}
/** @var null|Transaction $destination */
$destination = $journal->transactions()->where('amount', '>', 0)->first();
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
if (null === $destination || null === $source) {
Log::debug('Source or destination transaction is NULL, continue.');
// will be picked up later.
continue;
}
if ($source->transaction_currency_id === $destination->transaction_currency_id) {
Log::debug('Ready to swap data between transactions.');
$destination->foreign_currency_id = $source->transaction_currency_id;
$destination->foreign_amount = app('steam')->positive($source->amount);
$destination->transaction_currency_id = $source->foreign_currency_id;
$destination->amount = app('steam')->positive($source->foreign_amount);
$destination->balance_dirty = true;
$source->balance_dirty = true;
$destination->save();
$source->save();
$this->friendlyWarning(sprintf('Corrected foreign amounts of transfer #%d.', $journal->id));
++$count;
}
}
if (0 === $count) {
$this->friendlyPositive('No "old style" foreign currency transfers.');
return;
}
}
private function fixUnevenAmounts(): void
{
$journals = \DB::table('transactions')
->groupBy('transaction_journal_id')
->whereNull('deleted_at')
->get(['transaction_journal_id', \DB::raw('SUM(amount) AS the_sum')])
;
/** @var \stdClass $entry */
foreach ($journals as $entry) {
$sum = (string) $entry->the_sum;
if (!is_numeric($sum)
|| '' === $sum // @phpstan-ignore-line
|| str_contains($sum, 'e')
|| str_contains($sum, ',')) {
$message = sprintf(
'Journal #%d has an invalid sum ("%s"). No sure what to do.',
$entry->transaction_journal_id,
$entry->the_sum
);
$this->friendlyWarning($message);
app('log')->warning($message);
++$this->count;
continue;
}
$res = -1;
try {
$res = bccomp($sum, '0');
} catch (\ValueError $e) {
$this->friendlyError(sprintf('Could not bccomp("%s", "0").', $sum));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
if (0 !== $res) {
$this->fixJournal($entry->transaction_journal_id);
}
}
if (0 === $this->count) {
$this->friendlyPositive('Database amount integrity is OK');
}
}
private function fixJournal(int $param): void
{
// one of the transactions is bad.
@@ -130,78 +237,6 @@ class FixUnevenAmount extends Command
++$this->count;
}
private function fixUnevenAmounts(): void
{
$journals = \DB::table('transactions')
->groupBy('transaction_journal_id')
->whereNull('deleted_at')
->get(['transaction_journal_id', \DB::raw('SUM(amount) AS the_sum')])
;
/** @var \stdClass $entry */
foreach ($journals as $entry) {
$sum = (string) $entry->the_sum;
if (!is_numeric($sum)
|| '' === $sum // @phpstan-ignore-line
|| str_contains($sum, 'e')
|| str_contains($sum, ',')) {
$message = sprintf(
'Journal #%d has an invalid sum ("%s"). No sure what to do.',
$entry->transaction_journal_id,
$entry->the_sum
);
$this->friendlyWarning($message);
app('log')->warning($message);
++$this->count;
continue;
}
$res = -1;
try {
$res = bccomp($sum, '0');
} catch (\ValueError $e) {
$this->friendlyError(sprintf('Could not bccomp("%s", "0").', $sum));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
if (0 !== $res) {
$this->fixJournal($entry->transaction_journal_id);
}
}
if (0 === $this->count) {
$this->friendlyPositive('Database amount integrity is OK');
}
}
private function matchCurrencies(): void
{
$journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id')
->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id'))
->get(['transaction_journals.*'])
;
$count = 0;
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
if (!$this->isForeignCurrencyTransfer($journal)) {
Transaction::where('transaction_journal_id', $journal->id)->update(['transaction_currency_id' => $journal->transaction_currency_id]);
++$count;
continue;
}
Log::debug(sprintf('Can skip foreign currency transfer #%d.', $journal->id));
}
if (0 === $count) {
$this->friendlyPositive('Journal currency integrity is OK');
return;
}
$this->friendlyPositive(sprintf('Fixed %d journal(s) with mismatched currencies.', $journals->count()));
}
private function isForeignCurrencyTransfer(TransactionJournal $journal): bool
{
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
@@ -236,66 +271,31 @@ class FixUnevenAmount extends Command
return false;
}
private function convertOldStyleTransfers(): void
private function matchCurrencies(): void
{
Log::debug('convertOldStyleTransfers()');
// select transactions with a foreign amount and a foreign currency. and it's a transfer. and they are different.
$transactions = Transaction::distinct()
->leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionTypeEnum::TRANSFER->value)
->whereNotNull('foreign_currency_id')
->whereNotNull('foreign_amount')->get(['transactions.transaction_journal_id'])
$journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id')
->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id'))
->get(['transaction_journals.*'])
;
$count = 0;
Log::debug(sprintf('Found %d potential journal(s)', $transactions->count()));
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($transaction->transaction_journal_id);
if (null === $journal) {
Log::debug('Found no journal, continue.');
continue;
}
// needs to be a transfer.
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
Log::debug('Must be a transfer, continue.');
continue;
}
/** @var null|Transaction $destination */
$destination = $journal->transactions()->where('amount', '>', 0)->first();
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
if (null === $destination || null === $source) {
Log::debug('Source or destination transaction is NULL, continue.');
// will be picked up later.
continue;
}
if ($source->transaction_currency_id === $destination->transaction_currency_id) {
Log::debug('Ready to swap data between transactions.');
$destination->foreign_currency_id = $source->transaction_currency_id;
$destination->foreign_amount = app('steam')->positive($source->amount);
$destination->transaction_currency_id = $source->foreign_currency_id;
$destination->amount = app('steam')->positive($source->foreign_amount);
$destination->balance_dirty = true;
$source->balance_dirty = true;
$destination->save();
$source->save();
$this->friendlyWarning(sprintf('Corrected foreign amounts of transfer #%d.', $journal->id));
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
if (!$this->isForeignCurrencyTransfer($journal)) {
Transaction::where('transaction_journal_id', $journal->id)->update(['transaction_currency_id' => $journal->transaction_currency_id]);
++$count;
continue;
}
Log::debug(sprintf('Can skip foreign currency transfer #%d.', $journal->id));
}
if (0 === $count) {
$this->friendlyPositive('No "old style" foreign currency transfers.');
$this->friendlyPositive('Journal currency integrity is OK');
return;
}
$this->friendlyPositive(sprintf('Fixed %d journal(s) with mismatched currencies.', $journals->count()));
}
}

View File

@@ -181,17 +181,6 @@ class RecalculateNativeAmounts extends Command
Log::debug(sprintf('Recalculated %d auto budgets.', $set->count()));
}
private function recalculateBills(UserGroup $userGroup, TransactionCurrency $currency): void
{
$set = $userGroup->bills()->where('transaction_currency_id', '!=', $currency->id)->get();
/** @var Bill $bill */
foreach ($set as $bill) {
$bill->touch();
}
Log::debug(sprintf('Recalculated %d bills.', $set->count()));
}
private function recalculateAvailableBudgets(UserGroup $userGroup, TransactionCurrency $currency): void
{
Log::debug('Start with available budgets.');
@@ -204,6 +193,17 @@ class RecalculateNativeAmounts extends Command
Log::debug(sprintf('Recalculated %d available budgets.', $set->count()));
}
private function recalculateBills(UserGroup $userGroup, TransactionCurrency $currency): void
{
$set = $userGroup->bills()->where('transaction_currency_id', '!=', $currency->id)->get();
/** @var Bill $bill */
foreach ($set as $bill) {
$bill->touch();
}
Log::debug(sprintf('Recalculated %d bills.', $set->count()));
}
private function calculateTransactions(UserGroup $userGroup, TransactionCurrency $currency): void
{
// custom query because of the potential size of this update.

View File

@@ -45,21 +45,8 @@ class AddTimezonesToDates extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:add-timezones-to-dates';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Make sure all dates have a timezone.';
public static array $models = [
public static array $models
= [
AccountBalance::class => ['date'], // done
AvailableBudget::class => ['start_date', 'end_date'], // done
Bill::class => ['date', 'end_date', 'extension_date'], // done
@@ -74,6 +61,20 @@ class AddTimezonesToDates extends Command
TransactionJournal::class => ['date'],
];
/**
* The console command description.
*
* @var string
*/
protected $description = 'Make sure all dates have a timezone.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:add-timezones-to-dates';
/**
* Execute the console command.
*/

View File

@@ -35,13 +35,6 @@ class ConvertDatesToUTC extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:migrate-to-utc';
/**
* The console command description.
*
@@ -49,6 +42,13 @@ class ConvertDatesToUTC extends Command
*/
protected $description = 'Convert stored dates to UTC.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:migrate-to-utc';
/**
* Execute the console command.
*/

View File

@@ -59,12 +59,6 @@ class CorrectAccountBalance extends Command
return 0;
}
private function correctBalanceAmounts(): void
{
return;
AccountBalanceCalculator::recalculateAll(true);
}
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
@@ -76,4 +70,10 @@ class CorrectAccountBalance extends Command
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
private function correctBalanceAmounts(): void
{
return;
AccountBalanceCalculator::recalculateAll(true);
}
}

View File

@@ -239,11 +239,6 @@ class OtherCurrenciesCorrections extends Command
return $currency;
}
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
private function isMultiCurrency(Account $account): bool
{
$value = $this->accountRepos->getMetaValue($account, 'is_multi_currency', false);
@@ -253,4 +248,9 @@ class OtherCurrenciesCorrections extends Command
return '1' === $value;
}
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
}

View File

@@ -39,9 +39,8 @@ class UpgradeMultiPiggyBanks extends Command
protected $description = 'Upgrade piggybanks so they can use multiple accounts.';
protected $signature = 'firefly-iii:upgrade-multi-piggies {--F|force : Force the execution of this command.}';
private PiggyBankRepositoryInterface $repository;
private AccountRepositoryInterface $accountRepository;
private PiggyBankRepositoryInterface $repository;
/**
* Execute the console command.
@@ -71,11 +70,6 @@ class UpgradeMultiPiggyBanks extends Command
return false;
}
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
private function upgradePiggyBanks(): void
{
$this->repository = app(PiggyBankRepositoryInterface::class);
@@ -109,4 +103,9 @@ class UpgradeMultiPiggyBanks extends Command
$piggyBank->piggyBankRepetitions()->delete();
}
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
}

View File

@@ -28,9 +28,9 @@ use FireflyIII\Models\Account;
class AccountBalance
{
public string $id;
public string $amount;
public string $currencyId;
public string $id;
public static function fromArray(): self
{

View File

@@ -35,8 +35,8 @@ class RegisteredUser extends Event
{
use SerializesModels;
public User $user;
public OwnerNotifiable $owner;
public User $user;
/**
* Create a new event instance. This event is triggered when a new user registers.

View File

@@ -33,8 +33,8 @@ class MFABackupFewLeft extends Event
{
use SerializesModels;
public User $user;
public int $count;
public User $user;
public function __construct(null|Authenticatable|User $user, int $count)
{

View File

@@ -33,8 +33,8 @@ class MFAManyFailedAttempts extends Event
{
use SerializesModels;
public User $user;
public int $count;
public User $user;
public function __construct(null|Authenticatable|User $user, int $count)
{

View File

@@ -31,8 +31,8 @@ class OwnerTestNotificationChannel
{
use SerializesModels;
public OwnerNotifiable $owner;
public string $channel;
public OwnerNotifiable $owner;
/**
* Create a new event instance.

View File

@@ -31,8 +31,8 @@ class UserTestNotificationChannel
{
use SerializesModels;
public User $user;
public string $channel;
public User $user;
/**
* Create a new event instance.

View File

@@ -49,8 +49,8 @@ class PiggyBankFactory
$this->piggyBankRepository->setUser($value);
}
}
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $accountRepository;
private CurrencyRepositoryInterface $currencyRepository;
private PiggyBankRepositoryInterface $piggyBankRepository;
public function __construct()
@@ -120,6 +120,21 @@ class PiggyBankFactory
return $piggyBank;
}
private function getCurrency(array $data): TransactionCurrency
{
// currency:
$defaultCurrency = app('amount')->getDefaultCurrency();
$currency = null;
if (array_key_exists('transaction_currency_code', $data)) {
$currency = $this->currencyRepository->findByCode((string) ($data['transaction_currency_code'] ?? ''));
}
if (array_key_exists('transaction_currency_id', $data)) {
$currency = $this->currencyRepository->find((int) ($data['transaction_currency_id'] ?? 0));
}
$currency ??= $defaultCurrency;
return $currency;
}
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
{
$piggyBankId = (int) $piggyBankId;
@@ -162,21 +177,6 @@ class PiggyBankFactory
->first(['piggy_banks.*']);
}
private function getCurrency(array $data): TransactionCurrency
{
// currency:
$defaultCurrency = app('amount')->getDefaultCurrency();
$currency = null;
if (array_key_exists('transaction_currency_code', $data)) {
$currency = $this->currencyRepository->findByCode((string) ($data['transaction_currency_code'] ?? ''));
}
if (array_key_exists('transaction_currency_id', $data)) {
$currency = $this->currencyRepository->find((int) ($data['transaction_currency_id'] ?? 0));
}
$currency ??= $defaultCurrency;
return $currency;
}
private function setOrder(PiggyBank $piggyBank, array $data): PiggyBank
{
$this->resetOrder();

View File

@@ -43,11 +43,16 @@ use Illuminate\Support\Facades\Notification;
*/
class AdminEventHandler
{
public function sendLoginAttemptNotification(UnknownUserAttemptedLogin $event): void
public function sendInvitationNotification(InvitationCreated $event): void
{
$sendMail = app('fireflyconfig')->get('notification_invite_created', true)->data;
if (false === $sendMail) {
return;
}
try {
$owner = new OwnerNotifiable();
Notification::send($owner, new UnknownUserLoginAttempt($event->address));
Notification::send($owner, new UserInvitation($owner, $event->invitee));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
@@ -65,16 +70,11 @@ class AdminEventHandler
}
}
public function sendInvitationNotification(InvitationCreated $event): void
public function sendLoginAttemptNotification(UnknownUserAttemptedLogin $event): void
{
$sendMail = app('fireflyconfig')->get('notification_invite_created', true)->data;
if (false === $sendMail) {
return;
}
try {
$owner = new OwnerNotifiable();
Notification::send($owner, new UserInvitation($owner, $event->invitee));
Notification::send($owner, new UnknownUserLoginAttempt($event->address));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {

View File

@@ -42,56 +42,6 @@ use Illuminate\Support\Facades\Notification;
class MFAHandler
{
public function sendMFAEnabledMail(EnabledMFA $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new EnabledMFANotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
public function sendNewMFABackupCodesMail(MFANewBackupCodes $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new NewBackupCodesNotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
public function sendBackupFewLeftMail(MFABackupFewLeft $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
@@ -118,6 +68,81 @@ class MFAHandler
}
}
public function sendBackupNoLeftMail(MFABackupNoLeft $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new MFABackupNoLeftNotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
public function sendMFADisabledMail(DisabledMFA $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new DisabledMFANotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
public function sendMFAEnabledMail(EnabledMFA $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new EnabledMFANotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
public function sendMFAFailedAttemptsMail(MFAManyFailedAttempts $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
@@ -144,14 +169,14 @@ class MFAHandler
}
}
public function sendBackupNoLeftMail(MFABackupNoLeft $event): void
public function sendNewMFABackupCodesMail(MFANewBackupCodes $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new MFABackupNoLeftNotification($user));
Notification::send($user, new NewBackupCodesNotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
@@ -193,29 +218,4 @@ class MFAHandler
app('log')->error($e->getTraceAsString());
}
}
public function sendMFADisabledMail(DisabledMFA $event): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$user = $event->user;
try {
Notification::send($user, new DisabledMFANotification($user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
}

View File

@@ -300,6 +300,27 @@ class UserEventHandler
}
}
public function sendLoginAttemptNotification(UserAttemptedLogin $event): void
{
try {
Notification::send($event->user, new UserFailedLoginAttempt($event->user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
/**
* Send a new password to the user.
*/
@@ -371,6 +392,61 @@ class UserEventHandler
}
}
/**
* Sends a test message to an administrator.
*/
public function sendTestNotification(UserTestNotificationChannel $event): void
{
Log::debug(sprintf('Now in (user) sendTestNotification("%s")', $event->channel));
switch ($event->channel) {
case 'email':
$class = UserTestNotificationEmail::class;
break;
case 'slack':
$class = UserTestNotificationSlack::class;
break;
case 'ntfy':
$class = UserTestNotificationNtfy::class;
break;
case 'pushover':
$class = UserTestNotificationPushover::class;
break;
default:
app('log')->error(sprintf('Unknown channel "%s" in (user) sendTestNotification method.', $event->channel));
return;
}
Log::debug(sprintf('Will send %s as a notification.', $class));
try {
Notification::send($event->user, new $class($event->user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
Log::debug(sprintf('If you see no errors above this line, test notification was sent over channel "%s"', $event->channel));
}
/**
* @throws FireflyException
*/
@@ -430,80 +506,4 @@ class UserEventHandler
event(new DetectedNewIPAddress($user));
}
}
public function sendLoginAttemptNotification(UserAttemptedLogin $event): void
{
try {
Notification::send($event->user, new UserFailedLoginAttempt($event->user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
}
/**
* Sends a test message to an administrator.
*/
public function sendTestNotification(UserTestNotificationChannel $event): void
{
Log::debug(sprintf('Now in (user) sendTestNotification("%s")', $event->channel));
switch ($event->channel) {
case 'email':
$class = UserTestNotificationEmail::class;
break;
case 'slack':
$class = UserTestNotificationSlack::class;
break;
case 'ntfy':
$class = UserTestNotificationNtfy::class;
break;
case 'pushover':
$class = UserTestNotificationPushover::class;
break;
default:
app('log')->error(sprintf('Unknown channel "%s" in (user) sendTestNotification method.', $event->channel));
return;
}
Log::debug(sprintf('Will send %s as a notification.', $class));
try {
Notification::send($event->user, new $class($event->user));
} catch (\Exception $e) { // @phpstan-ignore-line
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
Log::debug(sprintf('If you see no errors above this line, test notification was sent over channel "%s"', $event->channel));
}
}

View File

@@ -35,6 +35,31 @@ use Illuminate\Support\Facades\Log;
*/
class AccountObserver
{
public function created(Account $account): void
{
Log::debug('Observe "created" of an account.');
$this->updateNativeAmount($account);
}
private function updateNativeAmount(Account $account): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
$repository = app(AccountRepositoryInterface::class);
$currency = $repository->getAccountCurrency($account);
if (null !== $currency && $currency->id !== $userCurrency->id && '' !== (string) $account->virtual_balance && 0 !== bccomp($account->virtual_balance, '0')) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$account->native_virtual_balance = $converter->convert($currency, $userCurrency, today(), $account->virtual_balance);
}
if ('' === (string) $account->virtual_balance || ('' !== (string) $account->virtual_balance && 0 === bccomp($account->virtual_balance, '0'))) {
$account->virtual_balance = null;
$account->native_virtual_balance = null;
}
$account->saveQuietly();
Log::debug('Account native virtual balance is updated.');
}
/**
* Also delete related objects.
*/
@@ -57,34 +82,9 @@ class AccountObserver
$account->locations()->delete();
}
public function created(Account $account): void
{
Log::debug('Observe "created" of an account.');
$this->updateNativeAmount($account);
}
public function updated(Account $account): void
{
Log::debug('Observe "updated" of an account.');
$this->updateNativeAmount($account);
}
private function updateNativeAmount(Account $account): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
$repository = app(AccountRepositoryInterface::class);
$currency = $repository->getAccountCurrency($account);
if (null !== $currency && $currency->id !== $userCurrency->id && '' !== (string) $account->virtual_balance && 0 !== bccomp($account->virtual_balance, '0')) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$account->native_virtual_balance = $converter->convert($currency, $userCurrency, today(), $account->virtual_balance);
}
if ('' === (string) $account->virtual_balance || ('' !== (string) $account->virtual_balance && 0 === bccomp($account->virtual_balance, '0'))) {
$account->virtual_balance = null;
$account->native_virtual_balance = null;
}
$account->saveQuietly();
Log::debug('Account native virtual balance is updated.');
}
}

View File

@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
class AutoBudgetObserver
{
public function updated(AutoBudget $autoBudget): void
{
Log::debug('Observe "updated" of an auto budget.');
$this->updateNativeAmount($autoBudget);
}
public function created(AutoBudget $autoBudget): void
{
Log::debug('Observe "created" of an auto budget.');
$this->updateNativeAmount($autoBudget);
}
public function updated(AutoBudget $autoBudget): void
{
Log::debug('Observe "updated" of an auto budget.');
$this->updateNativeAmount($autoBudget);
}
private function updateNativeAmount(AutoBudget $autoBudget): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($autoBudget->budget->user->userGroup);

View File

@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
class AvailableBudgetObserver
{
public function updated(AvailableBudget $availableBudget): void
{
Log::debug('Observe "updated" of an available budget.');
$this->updateNativeAmount($availableBudget);
}
public function created(AvailableBudget $availableBudget): void
{
Log::debug('Observe "created" of an available budget.');
$this->updateNativeAmount($availableBudget);
}
public function updated(AvailableBudget $availableBudget): void
{
Log::debug('Observe "updated" of an available budget.');
$this->updateNativeAmount($availableBudget);
}
private function updateNativeAmount(AvailableBudget $availableBudget): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($availableBudget->user->userGroup);

View File

@@ -32,6 +32,12 @@ use Illuminate\Support\Facades\Log;
*/
class BillObserver
{
public function created(Bill $bill): void
{
Log::debug('Observe "created" of a bill.');
$this->updateNativeAmount($bill);
}
public function deleting(Bill $bill): void
{
app('log')->debug('Observe "deleting" of a bill.');
@@ -47,12 +53,6 @@ class BillObserver
$this->updateNativeAmount($bill);
}
public function created(Bill $bill): void
{
Log::debug('Observe "created" of a bill.');
$this->updateNativeAmount($bill);
}
private function updateNativeAmount(Bill $bill): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($bill->user->userGroup);

View File

@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
class BudgetLimitObserver
{
public function updated(BudgetLimit $budgetLimit): void
{
Log::debug('Observe "updated" of a budget limit.');
$this->updateNativeAmount($budgetLimit);
}
public function created(BudgetLimit $budgetLimit): void
{
Log::debug('Observe "created" of a budget limit.');
$this->updateNativeAmount($budgetLimit);
}
public function updated(BudgetLimit $budgetLimit): void
{
Log::debug('Observe "updated" of a budget limit.');
$this->updateNativeAmount($budgetLimit);
}
private function updateNativeAmount(BudgetLimit $budgetLimit): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($budgetLimit->budget->user->userGroup);

View File

@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
class PiggyBankEventObserver
{
public function updated(PiggyBankEvent $event): void
{
Log::debug('Observe "updated" of a piggy bank event.');
$this->updateNativeAmount($event);
}
public function created(PiggyBankEvent $event): void
{
Log::debug('Observe "created" of a piggy bank event.');
$this->updateNativeAmount($event);
}
public function updated(PiggyBankEvent $event): void
{
Log::debug('Observe "updated" of a piggy bank event.');
$this->updateNativeAmount($event);
}
private function updateNativeAmount(PiggyBankEvent $event): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($event->piggyBank->accounts()->first()->user->userGroup);

View File

@@ -33,18 +33,35 @@ use Illuminate\Support\Facades\Log;
*/
class PiggyBankObserver
{
public function updated(PiggyBank $piggyBank): void
{
Log::debug('Observe "updated" of a piggy bank.');
$this->updateNativeAmount($piggyBank);
}
public function created(PiggyBank $piggyBank): void
{
Log::debug('Observe "created" of a piggy bank.');
$this->updateNativeAmount($piggyBank);
}
/**
* Also delete related objects.
*/
public function deleting(PiggyBank $piggyBank): void
{
app('log')->debug('Observe "deleting" of a piggy bank.');
foreach ($piggyBank->attachments()->get() as $attachment) {
$attachment->delete();
}
$piggyBank->piggyBankEvents()->delete();
$piggyBank->piggyBankRepetitions()->delete();
$piggyBank->notes()->delete();
}
public function updated(PiggyBank $piggyBank): void
{
Log::debug('Observe "updated" of a piggy bank.');
$this->updateNativeAmount($piggyBank);
}
private function updateNativeAmount(PiggyBank $piggyBank): void
{
$group = $piggyBank->accounts()->first()?->user->userGroup;
@@ -66,21 +83,4 @@ class PiggyBankObserver
$piggyBank->saveQuietly();
Log::debug('Piggy bank native target amount is updated.');
}
/**
* Also delete related objects.
*/
public function deleting(PiggyBank $piggyBank): void
{
app('log')->debug('Observe "deleting" of a piggy bank.');
foreach ($piggyBank->attachments()->get() as $attachment) {
$attachment->delete();
}
$piggyBank->piggyBankEvents()->delete();
$piggyBank->piggyBankRepetitions()->delete();
$piggyBank->notes()->delete();
}
}

View File

@@ -35,6 +35,18 @@ class TransactionObserver
{
public static bool $recalculate = true;
public function created(Transaction $transaction): void
{
Log::debug('Observe "created" of a transaction.');
if (config('firefly.feature_flags.running_balance_column')) {
if (1 === bccomp($transaction->amount, '0') && self::$recalculate) {
Log::debug('Trigger recalculateForJournal');
AccountBalanceCalculator::recalculateForJournal($transaction->transactionJournal);
}
}
$this->updateNativeAmount($transaction);
}
public function deleting(?Transaction $transaction): void
{
app('log')->debug('Observe "deleting" of a transaction.');
@@ -53,18 +65,6 @@ class TransactionObserver
$this->updateNativeAmount($transaction);
}
public function created(Transaction $transaction): void
{
Log::debug('Observe "created" of a transaction.');
if (config('firefly.feature_flags.running_balance_column')) {
if (1 === bccomp($transaction->amount, '0') && self::$recalculate) {
Log::debug('Trigger recalculateForJournal');
AccountBalanceCalculator::recalculateForJournal($transaction->transactionJournal);
}
}
$this->updateNativeAmount($transaction);
}
private function updateNativeAmount(Transaction $transaction): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($transaction->transactionJournal->user->userGroup);

View File

@@ -163,6 +163,22 @@ class TwoFactorController extends Controller
app('preferences')->set('mfa_history', $newHistory);
}
private function addToMFAFailureCounter(): void
{
$preference = (int) app('preferences')->get('mfa_failure_count', 0)->data;
++$preference;
Log::channel('audit')->info(sprintf('MFA failure count is set to %d.', $preference));
app('preferences')->set('mfa_failure_count', $preference);
}
private function getMFAFailureCounter(): int
{
$value = (int) app('preferences')->get('mfa_failure_count', 0)->data;
Log::channel('audit')->info(sprintf('MFA failure count is %d.', $value));
return $value;
}
private function addToMFAHistory(string $mfaCode): void
{
/** @var array $mfaHistory */
@@ -177,6 +193,12 @@ class TwoFactorController extends Controller
$this->filterMFAHistory();
}
private function resetMFAFailureCounter(): void
{
app('preferences')->set('mfa_failure_count', 0);
Log::channel('audit')->info('MFA failure count is set to zero.');
}
/**
* Checks if code is in users backup codes.
*/
@@ -219,26 +241,4 @@ class TwoFactorController extends Controller
app('preferences')->set('mfa_recovery', $newList);
}
private function addToMFAFailureCounter(): void
{
$preference = (int) app('preferences')->get('mfa_failure_count', 0)->data;
++$preference;
Log::channel('audit')->info(sprintf('MFA failure count is set to %d.', $preference));
app('preferences')->set('mfa_failure_count', $preference);
}
private function getMFAFailureCounter(): int
{
$value = (int) app('preferences')->get('mfa_failure_count', 0)->data;
Log::channel('audit')->info(sprintf('MFA failure count is %d.', $value));
return $value;
}
private function resetMFAFailureCounter(): void
{
app('preferences')->set('mfa_failure_count', 0);
Log::channel('audit')->info('MFA failure count is set to zero.');
}
}

View File

@@ -102,13 +102,14 @@ class BudgetLimitController extends Controller
}
/**
* @return Factory|View
* @return Redirector|RedirectResponse
*/
public function show(BudgetLimit $budgetLimit)
public function delete(BudgetLimit $budgetLimit)
{
$notes = $this->blRepository->getNoteText($budgetLimit);
$this->blRepository->destroyBudgetLimit($budgetLimit);
session()->flash('success', trans('firefly.deleted_bl'));
return view('budgets.budget-limits.show', compact('budgetLimit', 'notes'));
return redirect(route('budgets.index'));
}
/**
@@ -122,14 +123,13 @@ class BudgetLimitController extends Controller
}
/**
* @return Redirector|RedirectResponse
* @return Factory|View
*/
public function delete(BudgetLimit $budgetLimit)
public function show(BudgetLimit $budgetLimit)
{
$this->blRepository->destroyBudgetLimit($budgetLimit);
session()->flash('success', trans('firefly.deleted_bl'));
$notes = $this->blRepository->getNoteText($budgetLimit);
return redirect(route('budgets.index'));
return view('budgets.budget-limits.show', compact('budgetLimit', 'notes'));
}
/**

View File

@@ -29,6 +29,7 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Route;
/**
* Class Controller.
@@ -119,7 +120,7 @@ abstract class Controller extends BaseController
app('view')->share('locale', $locale);
app('view')->share('shownDemo', $shownDemo);
app('view')->share('current_route_name', $page);
app('view')->share('original_route_name', \Route::currentRouteName());
app('view')->share('original_route_name', Route::currentRouteName());
}
app('view')->share('darkMode', $darkMode);

View File

@@ -106,59 +106,6 @@ class IndexController extends Controller
return view('piggy-banks.index', compact('piggyBanks', 'accounts'));
}
private function makeSums(array $piggyBanks): array
{
$sums = [];
foreach ($piggyBanks as $groupOrder => $group) {
$groupId = $group['object_group_id'];
foreach ($group['piggy_banks'] as $piggy) {
$currencyId = $piggy['currency_id'];
$sums[$groupId][$currencyId] ??= [
'target' => '0',
'saved' => '0',
'left_to_save' => '0',
'save_per_month' => '0',
'currency_id' => $currencyId,
'currency_code' => $piggy['currency_code'],
'currency_symbol' => $piggy['currency_symbol'],
'currency_decimal_places' => $piggy['currency_decimal_places'],
];
// target_amount
// current_amount
// left_to_save
// save_per_month
$sums[$groupId][$currencyId]['target'] = bcadd($sums[$groupId][$currencyId]['target'], (string) $piggy['target_amount']);
$sums[$groupId][$currencyId]['saved'] = bcadd($sums[$groupId][$currencyId]['saved'], (string) $piggy['current_amount']);
$sums[$groupId][$currencyId]['left_to_save'] = bcadd($sums[$groupId][$currencyId]['left_to_save'], (string) $piggy['left_to_save']);
$sums[$groupId][$currencyId]['save_per_month'] = bcadd($sums[$groupId][$currencyId]['save_per_month'], (string) $piggy['save_per_month']);
}
}
foreach ($piggyBanks as $groupOrder => $group) {
$groupId = $group['object_group_id'];
$piggyBanks[$groupOrder]['sums'] = $sums[$groupId] ?? [];
}
return $piggyBanks;
}
/**
* Set the order of a piggy bank.
*/
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
{
$objectGroupTitle = (string) $request->get('objectGroupTitle');
$newOrder = (int) $request->get('order');
$this->piggyRepos->setOrder($piggyBank, $newOrder);
if ('' !== $objectGroupTitle) {
$this->piggyRepos->setObjectGroup($piggyBank, $objectGroupTitle);
}
if ('' === $objectGroupTitle) {
$this->piggyRepos->removeObjectGroup($piggyBank);
}
return response()->json(['data' => 'OK']);
}
private function groupPiggyBanks(Collection $collection): array
{
/** @var PiggyBankTransformer $transformer */
@@ -251,4 +198,57 @@ class IndexController extends Controller
return $accounts;
}
private function makeSums(array $piggyBanks): array
{
$sums = [];
foreach ($piggyBanks as $groupOrder => $group) {
$groupId = $group['object_group_id'];
foreach ($group['piggy_banks'] as $piggy) {
$currencyId = $piggy['currency_id'];
$sums[$groupId][$currencyId] ??= [
'target' => '0',
'saved' => '0',
'left_to_save' => '0',
'save_per_month' => '0',
'currency_id' => $currencyId,
'currency_code' => $piggy['currency_code'],
'currency_symbol' => $piggy['currency_symbol'],
'currency_decimal_places' => $piggy['currency_decimal_places'],
];
// target_amount
// current_amount
// left_to_save
// save_per_month
$sums[$groupId][$currencyId]['target'] = bcadd($sums[$groupId][$currencyId]['target'], (string) $piggy['target_amount']);
$sums[$groupId][$currencyId]['saved'] = bcadd($sums[$groupId][$currencyId]['saved'], (string) $piggy['current_amount']);
$sums[$groupId][$currencyId]['left_to_save'] = bcadd($sums[$groupId][$currencyId]['left_to_save'], (string) $piggy['left_to_save']);
$sums[$groupId][$currencyId]['save_per_month'] = bcadd($sums[$groupId][$currencyId]['save_per_month'], (string) $piggy['save_per_month']);
}
}
foreach ($piggyBanks as $groupOrder => $group) {
$groupId = $group['object_group_id'];
$piggyBanks[$groupOrder]['sums'] = $sums[$groupId] ?? [];
}
return $piggyBanks;
}
/**
* Set the order of a piggy bank.
*/
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
{
$objectGroupTitle = (string) $request->get('objectGroupTitle');
$newOrder = (int) $request->get('order');
$this->piggyRepos->setOrder($piggyBank, $newOrder);
if ('' !== $objectGroupTitle) {
$this->piggyRepos->setObjectGroup($piggyBank, $objectGroupTitle);
}
if ('' === $objectGroupTitle) {
$this->piggyRepos->removeObjectGroup($piggyBank);
}
return response()->json(['data' => 'OK']);
}
}

View File

@@ -80,19 +80,59 @@ class MfaController extends Controller
}
public function index(): Factory|RedirectResponse|View
/**
* @throws FireflyException
*/
public function backupCodes(Request $request): Factory|RedirectResponse|View
{
if (!$this->internalAuth) {
request()->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
$request->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
return redirect(route('profile.index'));
}
$enabledMFA = null !== auth()->user()->mfa_secret;
if (false === $enabledMFA) {
request()->session()->flash('info', trans('firefly.mfa_not_enabled'));
return redirect(route('profile.index'));
}
$subTitle = (string)trans('firefly.mfa_index_title');
$subTitleIcon = 'fa-calculator';
$enabledMFA = null !== auth()->user()->mfa_secret;
return view('profile.mfa.backup-codes-intro');
}
public function backupCodesPost(ExistingTokenFormRequest $request): Redirector|RedirectResponse|View
{
if (!$this->internalAuth) {
$request->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
return redirect(route('profile.index'));
}
$enabledMFA = null !== auth()->user()->mfa_secret;
if (false === $enabledMFA) {
request()->session()->flash('info', trans('firefly.mfa_not_enabled'));
return redirect(route('profile.index'));
}
// generate recovery codes:
$recovery = app(Recovery::class);
$recoveryCodes = $recovery->lowercase()
->setCount(8) // Generate 8 codes
->setBlocks(2) // Every code must have 2 blocks
->setChars(6) // Each block must have 6 chars
->toArray()
;
$codes = implode("\r\n", $recoveryCodes);
app('preferences')->set('mfa_recovery', $recoveryCodes);
app('preferences')->mark();
// send user notification.
$user = auth()->user();
Log::channel('audit')->info(sprintf('User "%s" has generated new backup codes.', $user->email));
event(new MFANewBackupCodes($user));
return view('profile.mfa.backup-codes-post')->with(compact('codes'));
return view('profile.mfa.index')->with(compact('subTitle', 'subTitleIcon', 'enabledMFA'));
}
public function disableMFA(Request $request): Factory|RedirectResponse|View
@@ -180,66 +220,10 @@ class MfaController extends Controller
app('preferences')->set('temp-mfa-secret', $secret);
return view('profile.mfa.enable-mfa', compact('image', 'secret'));
}
public function backupCodesPost(ExistingTokenFormRequest $request): Redirector|RedirectResponse|View
{
if (!$this->internalAuth) {
$request->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
return redirect(route('profile.index'));
}
$enabledMFA = null !== auth()->user()->mfa_secret;
if (false === $enabledMFA) {
request()->session()->flash('info', trans('firefly.mfa_not_enabled'));
return redirect(route('profile.index'));
}
// generate recovery codes:
$recovery = app(Recovery::class);
$recoveryCodes = $recovery->lowercase()
->setCount(8) // Generate 8 codes
->setBlocks(2) // Every code must have 2 blocks
->setChars(6) // Each block must have 6 chars
->toArray()
;
$codes = implode("\r\n", $recoveryCodes);
app('preferences')->set('mfa_recovery', $recoveryCodes);
app('preferences')->mark();
// send user notification.
$user = auth()->user();
Log::channel('audit')->info(sprintf('User "%s" has generated new backup codes.', $user->email));
event(new MFANewBackupCodes($user));
return view('profile.mfa.backup-codes-post')->with(compact('codes'));
}
/**
* @throws FireflyException
*/
public function backupCodes(Request $request): Factory|RedirectResponse|View
{
if (!$this->internalAuth) {
$request->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
return redirect(route('profile.index'));
}
$enabledMFA = null !== auth()->user()->mfa_secret;
if (false === $enabledMFA) {
request()->session()->flash('info', trans('firefly.mfa_not_enabled'));
return redirect(route('profile.index'));
}
return view('profile.mfa.backup-codes-intro');
}
/**
* Submit 2FA for the first time.
*
@@ -340,4 +324,19 @@ class MfaController extends Controller
}
app('preferences')->set('mfa_history', $newHistory);
}
public function index(): Factory|RedirectResponse|View
{
if (!$this->internalAuth) {
request()->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
return redirect(route('profile.index'));
}
$subTitle = (string) trans('firefly.mfa_index_title');
$subTitleIcon = 'fa-calculator';
$enabledMFA = null !== auth()->user()->mfa_secret;
return view('profile.mfa.index')->with(compact('subTitle', 'subTitleIcon', 'enabledMFA'));
}
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Transaction;
use Exception;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;

View File

@@ -24,9 +24,9 @@ declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
use Barryvdh\Debugbar\Facades\Debugbar;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Vite;
use Barryvdh\Debugbar\Facades\Debugbar;
/**
* Class SecureHeaders

View File

@@ -30,7 +30,8 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
*/
class VerifyCsrfToken extends Middleware
{
protected $except = [
protected $except
= [
'oauth/token',
];
}

View File

@@ -9,14 +9,6 @@ use LaravelJsonApi\Core\Resources\JsonApiResource;
class AccountBalanceResource extends JsonApiResource
{
/**
* Get the resource id.
*/
public function id(): string
{
return $this->resource->id;
}
/**
* Get the resource's attributes.
*
@@ -30,6 +22,14 @@ class AccountBalanceResource extends JsonApiResource
];
}
/**
* Get the resource id.
*/
public function id(): string
{
return $this->resource->id;
}
/**
* Get the resource's relationships.
*

View File

@@ -4,11 +4,6 @@ declare(strict_types=1);
namespace FireflyIII\JsonApi\V2\Accounts;
use FireflyIII\Rules\Account\IsUniqueAccount;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Rules\UniqueAccountNumber;
use FireflyIII\Rules\UniqueIban;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Support\Facades\Log;
use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest;

View File

@@ -13,14 +13,6 @@ use LaravelJsonApi\Core\Resources\JsonApiResource;
*/
class AccountResource extends JsonApiResource
{
/**
* Get the resource id.
*/
public function id(): string
{
return (string) $this->resource->id;
}
/**
* Get the resource's attributes.
*
@@ -69,6 +61,14 @@ class AccountResource extends JsonApiResource
];
}
/**
* Get the resource id.
*/
public function id(): string
{
return (string) $this->resource->id;
}
/**
* Get the resource's relationships.
*

View File

@@ -91,6 +91,13 @@ class AccountSchema extends Schema
return $array;
}
public function pagination(): EnumerablePagination
{
Log::debug(__METHOD__);
return EnumerablePagination::make();
}
public function repository(): AccountRepository
{
Log::debug(__METHOD__);
@@ -102,11 +109,4 @@ class AccountSchema extends Schema
->withUserGroup($this->userGroup)
;
}
public function pagination(): EnumerablePagination
{
Log::debug(__METHOD__);
return EnumerablePagination::make();
}
}

View File

@@ -6,11 +6,8 @@ namespace FireflyIII\JsonApi\V2\Accounts;
use FireflyIII\Models\Account;
use LaravelJsonApi\Eloquent\Contracts\Paginator;
use LaravelJsonApi\Eloquent\Fields\Boolean;
use LaravelJsonApi\Eloquent\Fields\DateTime;
use LaravelJsonApi\Eloquent\Fields\ID;
use LaravelJsonApi\Eloquent\Fields\Number;
use LaravelJsonApi\Eloquent\Fields\Relations\HasMany;
use LaravelJsonApi\Eloquent\Fields\Relations\HasOne;
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;

View File

@@ -126,17 +126,17 @@ class AccountQuery extends QueryAll implements HasPagination
return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']);
}
#[\Override]
public function paginate(array $page): Page
{
exit('here weare');
// TODO: Implement paginate() method.
}
#[\Override]
public function getOrPaginate(?array $page): iterable
{
exit('here weare');
// TODO: Implement getOrPaginate() method.
}
#[\Override]
public function paginate(array $page): Page
{
exit('here weare');
// TODO: Implement paginate() method.
}
}

View File

@@ -34,6 +34,13 @@ class CrudAccount extends CrudResource
{
use CollectsCustomParameters;
public function create(array $validatedData): Account
{
var_dump($validatedData);
exit;
}
/**
* Read the supplied site.
*/
@@ -51,11 +58,4 @@ class CrudAccount extends CrudResource
return $enrichment->enrichSingle($account);
}
public function create(array $validatedData): Account
{
var_dump($validatedData);
exit;
}
}

View File

@@ -94,6 +94,11 @@ class Account extends Model
return $this->belongsTo(User::class);
}
public function accountBalances(): HasMany
{
return $this->hasMany(AccountBalance::class);
}
public function accountType(): BelongsTo
{
return $this->belongsTo(AccountType::class);
@@ -123,11 +128,6 @@ class Account extends Model
return $this->hasMany(AccountMeta::class);
}
public function accountBalances(): HasMany
{
return $this->hasMany(AccountBalance::class);
}
public function getEditNameAttribute(): string
{
$name = $this->name;

View File

@@ -15,15 +15,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AccountBalance extends Model
{
use HasFactory;
protected $fillable = ['account_id', 'title', 'transaction_currency_id', 'balance', 'date', 'date_tz'];
protected function casts(): array
{
return [
'date' => SeparateTimezoneCaster::class,
'balance' => 'string',
];
}
protected $fillable = ['account_id', 'title', 'transaction_currency_id', 'balance', 'date', 'date_tz'];
public function account(): BelongsTo
{
@@ -34,4 +27,12 @@ class AccountBalance extends Model
{
return $this->belongsTo(TransactionCurrency::class);
}
protected function casts(): array
{
return [
'date' => SeparateTimezoneCaster::class,
'balance' => 'string',
];
}
}

View File

@@ -23,7 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use FireflyIII\Enums\AccountTypeEnum;
use Deprecated;
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use FireflyIII\Enums\AutoBudgetType;
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
@@ -47,11 +46,11 @@ class AutoBudget extends Model
#[\Deprecated]
public const int AUTO_BUDGET_ROLLOVER = 2;
protected $fillable = ['budget_id', 'amount', 'period'];
protected $casts = [
protected $casts
= [
'amount' => 'string',
];
protected $fillable = ['budget_id', 'amount', 'period'];
public function budget(): BelongsTo
{
@@ -63,13 +62,6 @@ class AutoBudget extends Model
return $this->belongsTo(TransactionCurrency::class);
}
protected function casts(): array
{
return [
// 'auto_budget_type' => AutoBudgetType::class,
];
}
protected function amount(): Attribute
{
return Attribute::make(
@@ -84,6 +76,13 @@ class AutoBudget extends Model
);
}
protected function casts(): array
{
return [
// 'auto_budget_type' => AutoBudgetType::class,
];
}
protected function transactionCurrencyId(): Attribute
{
return Attribute::make(

View File

@@ -86,11 +86,6 @@ class BudgetLimit extends Model
return $this->belongsTo(Budget::class);
}
public function transactionCurrency(): BelongsTo
{
return $this->belongsTo(TransactionCurrency::class);
}
/**
* Get all the notes.
*/
@@ -99,6 +94,11 @@ class BudgetLimit extends Model
return $this->morphMany(Note::class, 'noteable');
}
public function transactionCurrency(): BelongsTo
{
return $this->belongsTo(TransactionCurrency::class);
}
/**
* Get the amount
*/

View File

@@ -79,16 +79,16 @@ class PiggyBank extends Model
throw new NotFoundHttpException();
}
public function transactionCurrency(): BelongsTo
{
return $this->belongsTo(TransactionCurrency::class);
}
public function account(): BelongsTo
{
return $this->belongsTo(Account::class);
}
public function accounts(): BelongsToMany
{
return $this->belongsToMany(Account::class)->withPivot(['current_amount', 'native_current_amount']);
}
public function attachments(): MorphMany
{
return $this->morphMany(Attachment::class, 'attachable');
@@ -115,11 +115,6 @@ class PiggyBank extends Model
return $this->hasMany(PiggyBankEvent::class);
}
public function accounts(): BelongsToMany
{
return $this->belongsToMany(Account::class)->withPivot(['current_amount', 'native_current_amount']);
}
public function piggyBankRepetitions(): HasMany
{
return $this->hasMany(PiggyBankRepetition::class);
@@ -133,6 +128,11 @@ class PiggyBank extends Model
$this->attributes['target_amount'] = (string) $value;
}
public function transactionCurrency(): BelongsTo
{
return $this->belongsTo(TransactionCurrency::class);
}
protected function accountId(): Attribute
{
return Attribute::make(

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use FireflyIII\Enums\RecurrenceRepetitionWeekend;
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
@@ -67,6 +66,11 @@ class RecurrenceRepetition extends Model
/** @var string The table to store the data in */
protected $table = 'recurrences_repetitions';
public function recurrence(): BelongsTo
{
return $this->belongsTo(Recurrence::class);
}
protected function casts(): array
{
return [
@@ -74,11 +78,6 @@ class RecurrenceRepetition extends Model
];
}
public function recurrence(): BelongsTo
{
return $this->belongsTo(Recurrence::class);
}
protected function recurrenceId(): Attribute
{
return Attribute::make(

View File

@@ -183,13 +183,6 @@ class Transaction extends Model
);
}
protected function balanceDirty(): Attribute
{
return Attribute::make(
get: static fn ($value) => 1 === (int)$value,
);
}
/**
* Get the amount
*/
@@ -200,6 +193,13 @@ class Transaction extends Model
);
}
protected function balanceDirty(): Attribute
{
return Attribute::make(
get: static fn ($value) => 1 === (int) $value,
);
}
/**
* Get the foreign amount
*/

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -67,13 +66,6 @@ class TransactionType extends Model
];
protected $fillable = ['type'];
protected function casts(): array
{
return [
// 'type' => TransactionTypeEnum::class,
];
}
/**
* Route binder. Converts the key in the URL to the specified object (or throw 404).
*
@@ -116,4 +108,11 @@ class TransactionType extends Model
{
return $this->hasMany(TransactionJournal::class);
}
protected function casts(): array
{
return [
// 'type' => TransactionTypeEnum::class,
];
}
}

View File

@@ -54,15 +54,6 @@ class Webhook extends Model
];
protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'user_group_id', 'url', 'title', 'secret'];
protected function casts(): array
{
return [
// 'delivery' => WebhookDelivery::class,
// 'response' => WebhookResponse::class,
// 'trigger' => WebhookTrigger::class,
];
}
public static function getDeliveries(): array
{
$array = [];
@@ -164,4 +155,13 @@ class Webhook extends Model
{
return $this->hasMany(WebhookMessage::class);
}
protected function casts(): array
{
return [
// 'delivery' => WebhookDelivery::class,
// 'response' => WebhookResponse::class,
// 'trigger' => WebhookTrigger::class,
];
}
}

View File

@@ -72,16 +72,6 @@ class MFABackupFewLeftNotification extends Notification
return (new MailMessage())->markdown('emails.security.few-backup-codes', ['user' => $this->user, 'count' => $this->count, 'ip' => $ip, 'host' => $host, 'userAgent' => $userAgent, 'time' => $time])->subject($subject);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.mfa_few_backups_left_slack', ['email' => $this->user->email, 'count' => $this->count]);
return new SlackMessage()->content($message);
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -103,6 +93,16 @@ class MFABackupFewLeftNotification extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.mfa_few_backups_left_slack', ['email' => $this->user->email, 'count' => $this->count]);
return new SlackMessage()->content($message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -70,16 +70,6 @@ class MFABackupNoLeftNotification extends Notification
return (new MailMessage())->markdown('emails.security.no-backup-codes', ['user' => $this->user, 'ip' => $ip, 'host' => $host, 'userAgent' => $userAgent, 'time' => $time])->subject($subject);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.mfa_no_backups_left_slack', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -101,6 +91,16 @@ class MFABackupNoLeftNotification extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.mfa_no_backups_left_slack', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -69,16 +69,6 @@ class MFAManyFailedAttemptsNotification extends Notification
return (new MailMessage())->markdown('emails.security.many-failed-attempts', ['user' => $this->user, 'count' => $this->count, 'ip' => $ip, 'host' => $host, 'userAgent' => $userAgent, 'time' => $time])->subject($subject);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.mfa_many_failed_slack', ['email' => $this->user->email, 'count' => $this->count]);
return new SlackMessage()->content($message);
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -100,6 +90,16 @@ class MFAManyFailedAttemptsNotification extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.mfa_many_failed_slack', ['email' => $this->user->email, 'count' => $this->count]);
return new SlackMessage()->content($message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -70,16 +70,6 @@ class MFAUsedBackupCodeNotification extends Notification
return (new MailMessage())->markdown('emails.security.used-backup-code', ['user' => $this->user, 'ip' => $ip, 'host' => $host, 'userAgent' => $userAgent, 'time' => $time])->subject($subject);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.used_backup_code_slack', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -101,6 +91,16 @@ class MFAUsedBackupCodeNotification extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.used_backup_code_slack', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -70,16 +70,6 @@ class NewBackupCodesNotification extends Notification
return (new MailMessage())->markdown('emails.security.new-backup-codes', ['user' => $this->user, 'ip' => $ip, 'host' => $host, 'userAgent' => $userAgent, 'time' => $time])->subject($subject);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.new_backup_codes_slack', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -101,6 +91,16 @@ class NewBackupCodesNotification extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.new_backup_codes_slack', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -67,16 +67,6 @@ class UserFailedLoginAttempt extends Notification
return (new MailMessage())->markdown('emails.security.failed-login', ['user' => $this->user, 'ip' => $ip, 'host' => $host, 'userAgent' => $userAgent, 'time' => $time])->subject($subject);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.failed_login_message', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -98,6 +88,16 @@ class UserFailedLoginAttempt extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans('email.failed_login_message', ['email' => $this->user->email]);
return new SlackMessage()->content($message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -73,21 +73,14 @@ class BillReminder extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
private function getSubject(): string
{
$bill = $this->bill;
$url = route('bills.show', [$bill->id]);
$message = (string) trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
if (0 === $this->diff) {
$message = (string) trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
}
return new SlackMessage()
->warning()
->attachment(static function ($attachment) use ($bill, $url): void {
$attachment->title((string) trans('firefly.visit_bill', ['name' => $bill->name]), $url);
})
->content($this->getSubject())
;
return $message;
}
public function toNtfy(User $notifiable): Message
@@ -111,14 +104,21 @@ class BillReminder extends Notification
;
}
private function getSubject(): string
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$message = (string) trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
if (0 === $this->diff) {
$message = (string) trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
}
$bill = $this->bill;
$url = route('bills.show', [$bill->id]);
return $message;
return new SlackMessage()
->warning()
->attachment(static function ($attachment) use ($bill, $url): void {
$attachment->title((string) trans('firefly.visit_bill', ['name' => $bill->name]), $url);
})
->content($this->getSubject())
;
}
/**

View File

@@ -67,14 +67,6 @@ class NewAccessToken extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
return new SlackMessage()->content((string) trans('email.access_token_created_body'));
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -96,6 +88,14 @@ class NewAccessToken extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
return new SlackMessage()->content((string) trans('email.access_token_created_body'));
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -65,23 +65,6 @@ class RuleActionFailed extends Notification
];
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$groupTitle = $this->groupTitle;
$groupLink = $this->groupLink;
$ruleTitle = $this->ruleTitle;
$ruleLink = $this->ruleLink;
return new SlackMessage()->content($this->message)->attachment(static function ($attachment) use ($groupTitle, $groupLink): void {
$attachment->title((string) trans('rules.inspect_transaction', ['title' => $groupTitle]), $groupLink);
})->attachment(static function ($attachment) use ($ruleTitle, $ruleLink): void {
$attachment->title((string) trans('rules.inspect_rule', ['title' => $ruleTitle]), $ruleLink);
});
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -100,6 +83,23 @@ class RuleActionFailed extends Notification
return PushoverMessage::create($this->message);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
$groupTitle = $this->groupTitle;
$groupLink = $this->groupLink;
$ruleTitle = $this->ruleTitle;
$ruleLink = $this->ruleLink;
return new SlackMessage()->content($this->message)->attachment(static function ($attachment) use ($groupTitle, $groupLink): void {
$attachment->title((string) trans('rules.inspect_transaction', ['title' => $groupTitle]), $groupLink);
})->attachment(static function ($attachment) use ($ruleTitle, $ruleLink): void {
$attachment->title((string) trans('rules.inspect_rule', ['title' => $ruleTitle]), $ruleLink);
});
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/

View File

@@ -75,14 +75,6 @@ class UserNewPassword extends Notification
;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
return new SlackMessage()->content((string) trans('email.reset_pw_message'));
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
@@ -101,6 +93,14 @@ class UserNewPassword extends Notification
return PushoverMessage::create((string) trans('email.reset_pw_message'));
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function toSlack(User $notifiable)
{
return new SlackMessage()->content((string) trans('email.reset_pw_message'));
}
public function via(User $notifiable)
{
return ReturnsAvailableChannels::returnChannels('user', $notifiable);

View File

@@ -30,19 +30,16 @@ use Illuminate\Support\Facades\Log;
class AccountPolicy
{
/**
* TODO needs better authentication, also for group.
*/
public function view(User $user, Account $account): bool
{
return auth()->check() && $user->id === $account->user_id;
}
public function create(): bool
{
return auth()->check();
}
public function viewAccountBalances(User $user, Account $account): bool
{
return $this->view($user, $account);
}
/**
* Everybody can do this, but selection should limit to user.
*
@@ -65,8 +62,11 @@ class AccountPolicy
return $this->view($user, $account);
}
public function viewAccountBalances(User $user, Account $account): bool
/**
* TODO needs better authentication, also for group.
*/
public function view(User $user, Account $account): bool
{
return $this->view($user, $account);
return auth()->check() && $user->id === $account->user_id;
}
}

View File

@@ -38,6 +38,13 @@ class UserPolicy
return auth()->check() && $user->id === $account->user_id;
}
public function viewAccounts(User $user): bool
{
return true;
return auth()->check();
}
/**
* Everybody can do this, but selection should limit to user.
*
@@ -49,11 +56,4 @@ class UserPolicy
return auth()->check();
}
public function viewAccounts(User $user): bool
{
return true;
return auth()->check();
}
}

View File

@@ -562,6 +562,17 @@ class AccountRepository implements AccountRepositoryInterface
;
}
/**
* @throws FireflyException
*/
public function update(Account $account, array $data): Account
{
/** @var AccountUpdateService $service */
$service = app(AccountUpdateService::class);
return $service->update($account, $data);
}
public function searchAccount(string $query, array $types, int $limit): Collection
{
$dbQuery = $this->user->accounts()
@@ -634,15 +645,4 @@ class AccountRepository implements AccountRepositoryInterface
return $factory->create($data);
}
/**
* @throws FireflyException
*/
public function update(Account $account, array $data): Account
{
/** @var AccountUpdateService $service */
$service = app(AccountUpdateService::class);
return $service->update($account, $data);
}
}

View File

@@ -256,6 +256,12 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
;
}
#[\Override]
public function getNoteText(BudgetLimit $budgetLimit): string
{
return (string) $budgetLimit->notes()->first()?->text;
}
public function setUser(null|Authenticatable|User $user): void
{
if ($user instanceof User) {
@@ -324,6 +330,23 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
;
}
#[\Override]
public function setNoteText(BudgetLimit $budgetLimit, string $text): void
{
$dbNote = $budgetLimit->notes()->first();
if ('' !== $text) {
if (null === $dbNote) {
$dbNote = new Note();
$dbNote->noteable()->associate($budgetLimit);
}
$dbNote->text = trim($text);
$dbNote->save();
return;
}
$dbNote?->delete();
}
/**
* @throws FireflyException
*/
@@ -427,27 +450,4 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
return $limit;
}
#[\Override]
public function getNoteText(BudgetLimit $budgetLimit): string
{
return (string) $budgetLimit->notes()->first()?->text;
}
#[\Override]
public function setNoteText(BudgetLimit $budgetLimit, string $text): void
{
$dbNote = $budgetLimit->notes()->first();
if ('' !== $text) {
if (null === $dbNote) {
$dbNote = new Note();
$dbNote->noteable()->associate($budgetLimit);
}
$dbNote->text = trim($text);
$dbNote->save();
return;
}
$dbNote?->delete();
}
}

View File

@@ -48,10 +48,6 @@ interface BudgetLimitRepositoryInterface
*/
public function destroyAll(): void;
public function getNoteText(BudgetLimit $budgetLimit): string;
public function setNoteText(BudgetLimit $budgetLimit, string $text): void;
/**
* Destroy a budget limit.
*/
@@ -68,6 +64,10 @@ interface BudgetLimitRepositoryInterface
public function getBudgetLimits(Budget $budget, ?Carbon $start = null, ?Carbon $end = null): Collection;
public function getNoteText(BudgetLimit $budgetLimit): string;
public function setNoteText(BudgetLimit $budgetLimit, string $text): void;
public function setUser(null|Authenticatable|User $user): void;
public function store(array $data): BudgetLimit;

View File

@@ -37,6 +37,12 @@ class CurrencyRepository implements CurrencyRepositoryInterface
{
private User $user;
#[\Override]
public function find(int $currencyId): ?TransactionCurrency
{
return TransactionCurrency::find($currencyId);
}
/**
* Find by currency code, return NULL if unfound.
*/
@@ -106,10 +112,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface
$this->user = $user;
}
}
#[\Override]
public function find(int $currencyId): ?TransactionCurrency
{
return TransactionCurrency::find($currencyId);
}
}

View File

@@ -35,6 +35,8 @@ use Illuminate\Support\Collection;
*/
interface CurrencyRepositoryInterface
{
public function find(int $currencyId): ?TransactionCurrency;
/**
* Find by currency code, return NULL if unfound.
*
@@ -42,8 +44,6 @@ interface CurrencyRepositoryInterface
*/
public function findByCode(string $currencyCode): ?TransactionCurrency;
public function find(int $currencyId): ?TransactionCurrency;
/**
* Returns the complete set of transactions but needs
* no user object.

View File

@@ -80,24 +80,6 @@ trait ModifiesPiggyBanks
return true;
}
public function removeAmountFromAll(PiggyBank $piggyBank, string $amount): void
{
foreach ($piggyBank->accounts as $account) {
$current = $account->pivot->current_amount;
// if this account contains more than the amount, remove the amount and return.
if (1 === bccomp($current, $amount)) {
$this->removeAmount($piggyBank, $account, $amount);
return;
}
// 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);
$amount = bcsub($amount, $current);
}
}
}
public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool
{
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
@@ -220,57 +202,6 @@ trait ModifiesPiggyBanks
return $factory->store($data);
}
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
{
$oldOrder = $piggyBank->order;
// Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
if ($newOrder > $oldOrder) {
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->decrement('piggy_banks.order')
;
$piggyBank->order = $newOrder;
Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
$piggyBank->save();
return true;
}
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->increment('piggy_banks.order')
;
$piggyBank->order = $newOrder;
Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
$piggyBank->save();
return true;
}
public function updateNote(PiggyBank $piggyBank, string $note): void
{
if ('' === $note) {
$dbNote = $piggyBank->notes()->first();
$dbNote?->delete();
return;
}
$dbNote = $piggyBank->notes()->first();
if (null === $dbNote) {
$dbNote = new Note();
$dbNote->noteable()->associate($piggyBank);
}
$dbNote->text = trim($note);
$dbNote->save();
}
public function update(PiggyBank $piggyBank, array $data): PiggyBank
{
$piggyBank = $this->updateProperties($piggyBank, $data);
@@ -363,4 +294,73 @@ trait ModifiesPiggyBanks
return $piggyBank;
}
public function updateNote(PiggyBank $piggyBank, string $note): void
{
if ('' === $note) {
$dbNote = $piggyBank->notes()->first();
$dbNote?->delete();
return;
}
$dbNote = $piggyBank->notes()->first();
if (null === $dbNote) {
$dbNote = new Note();
$dbNote->noteable()->associate($piggyBank);
}
$dbNote->text = trim($note);
$dbNote->save();
}
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
{
$oldOrder = $piggyBank->order;
// Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
if ($newOrder > $oldOrder) {
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->decrement('piggy_banks.order')
;
$piggyBank->order = $newOrder;
Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
$piggyBank->save();
return true;
}
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->increment('piggy_banks.order')
;
$piggyBank->order = $newOrder;
Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
$piggyBank->save();
return true;
}
public function removeAmountFromAll(PiggyBank $piggyBank, string $amount): void
{
foreach ($piggyBank->accounts as $account) {
$current = $account->pivot->current_amount;
// if this account contains more than the amount, remove the amount and return.
if (1 === bccomp($current, $amount)) {
$this->removeAmount($piggyBank, $account, $amount);
return;
}
// 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);
$amount = bcsub($amount, $current);
}
}
}
}

View File

@@ -119,35 +119,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
);
}
/**
* Get current amount saved in piggy bank.
*/
public function getCurrentAmount(PiggyBank $piggyBank, ?Account $account = null): string
{
$sum = '0';
foreach ($piggyBank->accounts as $current) {
if (null !== $account && $account->id !== $current->id) {
continue;
}
$amount = (string) $current->pivot->current_amount;
$amount = '' === $amount ? '0' : $amount;
$sum = bcadd($sum, $amount);
}
Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
return $sum;
}
public function getRepetition(PiggyBank $piggyBank, bool $overrule = false): ?PiggyBankRepetition
{
if (false === $overrule) {
throw new FireflyException('[b] Piggy bank repetitions are EOL.');
}
Log::warning('Piggy bank repetitions are EOL.');
return $piggyBank->piggyBankRepetitions()->first();
}
public function getEvents(PiggyBank $piggyBank): Collection
{
return $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
@@ -302,6 +273,35 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
;
}
/**
* Get current amount saved in piggy bank.
*/
public function getCurrentAmount(PiggyBank $piggyBank, ?Account $account = null): string
{
$sum = '0';
foreach ($piggyBank->accounts as $current) {
if (null !== $account && $account->id !== $current->id) {
continue;
}
$amount = (string) $current->pivot->current_amount;
$amount = '' === $amount ? '0' : $amount;
$sum = bcadd($sum, $amount);
}
Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
return $sum;
}
public function getRepetition(PiggyBank $piggyBank, bool $overrule = false): ?PiggyBankRepetition
{
if (false === $overrule) {
throw new FireflyException('[b] Piggy bank repetitions are EOL.');
}
Log::warning('Piggy bank repetitions are EOL.');
return $piggyBank->piggyBankRepetitions()->first();
}
/**
* Returns the suggested amount the user should save per month, or "".
*/
@@ -352,28 +352,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
return $balance;
}
public function searchPiggyBank(string $query, int $limit): Collection
{
$search = PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id)
->with(
[
'objectGroups',
]
)
->orderBy('piggy_banks.order', 'ASC')->distinct()
;
if ('' !== $query) {
$search->whereLike('piggy_banks.name', sprintf('%%%s%%', $query));
}
$search->orderBy('piggy_banks.order', 'ASC')
->orderBy('piggy_banks.name', 'ASC')
;
return $search->take($limit)->get(['piggy_banks.*']);
}
#[\Override]
public function purgeAll(): void
{
@@ -398,4 +376,26 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
$factory->user = $this->user;
$factory->resetOrder();
}
public function searchPiggyBank(string $query, int $limit): Collection
{
$search = PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id)
->with(
[
'objectGroups',
]
)
->orderBy('piggy_banks.order', 'ASC')->distinct()
;
if ('' !== $query) {
$search->whereLike('piggy_banks.name', sprintf('%%%s%%', $query));
}
$search->orderBy('piggy_banks.order', 'ASC')
->orderBy('piggy_banks.name', 'ASC')
;
return $search->take($limit)->get(['piggy_banks.*']);
}
}

View File

@@ -53,8 +53,6 @@ interface PiggyBankRepositoryInterface
public function destroyAll(): void;
public function purgeAll(): void;
public function find(int $piggyBankId): ?PiggyBank;
/**
@@ -70,22 +68,20 @@ interface PiggyBankRepositoryInterface
* Get current amount saved in piggy bank.
*/
public function getCurrentAmount(PiggyBank $piggyBank, ?Account $account = null): string;
/**
* Get current amount saved in piggy bank.
*/
/**
* Get all events.
*/
public function getEvents(PiggyBank $piggyBank): Collection;
/**
* Get current amount saved in piggy bank.
*/
/**
* Used for connecting to a piggy bank.
*/
public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string;
public function updateNote(PiggyBank $piggyBank, string $note): void;
/**
* Return note for piggy bank.
*/
@@ -113,6 +109,8 @@ interface PiggyBankRepositoryInterface
*/
public function leftOnAccount(PiggyBank $piggyBank, Account $account, Carbon $date): string;
public function purgeAll(): void;
public function removeAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool;
public function removeAmountFromAll(PiggyBank $piggyBank, string $amount): void;
@@ -148,4 +146,6 @@ interface PiggyBankRepositoryInterface
* Update existing piggy bank.
*/
public function update(PiggyBank $piggyBank, array $data): PiggyBank;
public function updateNote(PiggyBank $piggyBank, string $note): void;
}

View File

@@ -174,6 +174,18 @@ class UserGroupRepository implements UserGroupRepositoryInterface
return UserGroup::all();
}
#[\Override]
public function getById(int $id): ?UserGroup
{
return UserGroup::find($id);
}
#[\Override]
public function getMembershipsFromGroupId(int $groupId): Collection
{
return $this->user->groupMemberships()->where('user_group_id', $groupId)->get();
}
public function setUser(null|Authenticatable|User $user): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
@@ -295,16 +307,4 @@ class UserGroupRepository implements UserGroupRepositoryInterface
$this->user->user_group_id = $userGroup->id;
$this->user->save();
}
#[\Override]
public function getMembershipsFromGroupId(int $groupId): Collection
{
return $this->user->groupMemberships()->where('user_group_id', $groupId)->get();
}
#[\Override]
public function getById(int $id): ?UserGroup
{
return UserGroup::find($id);
}
}

View File

@@ -36,13 +36,13 @@ interface UserGroupRepositoryInterface
{
public function destroy(UserGroup $userGroup): void;
public function getMembershipsFromGroupId(int $groupId): Collection;
public function get(): Collection;
public function getAll(): Collection;
public function getById(int $id): ?UserGroup;
public function getAll(): Collection;
public function getMembershipsFromGroupId(int $groupId): Collection;
public function setUser(null|Authenticatable|User $user): void;

View File

@@ -117,6 +117,12 @@ class AccountRepository implements AccountRepositoryInterface
return $account;
}
#[\Override]
public function getAccountBalances(Account $account): Collection
{
return $account->accountBalances;
}
public function getAccountCurrency(Account $account): ?TransactionCurrency
{
$type = $account->accountType->type;
@@ -164,6 +170,15 @@ class AccountRepository implements AccountRepositoryInterface
return $account;
}
#[\Override]
public function getAccountTypes(Collection $accounts): Collection
{
return AccountType::leftJoin('accounts', 'accounts.account_type_id', '=', 'account_types.id')
->whereIn('accounts.id', $accounts->pluck('id')->toArray())
->get(['accounts.id', 'account_types.type'])
;
}
public function getAccountsById(array $accountIds): Collection
{
$query = $this->userGroup->accounts();
@@ -218,6 +233,57 @@ class AccountRepository implements AccountRepositoryInterface
return $query->get(['accounts.*']);
}
#[\Override]
public function getLastActivity(Collection $accounts): array
{
return Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
->leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id')
->groupBy('transactions.account_id')
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) as date_max')])->toArray() // @phpstan-ignore-line
;
}
#[\Override]
public function getMetaValues(Collection $accounts, array $fields): Collection
{
$query = AccountMeta::whereIn('account_id', $accounts->pluck('id')->toArray());
if (count($fields) > 0) {
$query->whereIn('name', $fields);
}
return $query->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']);
}
#[\Override]
public function getObjectGroups(Collection $accounts): array
{
$groupIds = [];
$return = [];
$set = DB::table('object_groupables')->where('object_groupable_type', Account::class)
->whereIn('object_groupable_id', $accounts->pluck('id')->toArray())->get()
;
/** @var \stdClass $row */
foreach ($set as $row) {
$groupIds[] = $row->object_group_id;
}
$groupIds = array_unique($groupIds);
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
/** @var \stdClass $row */
foreach ($set as $row) {
if (!array_key_exists($row->object_groupable_id, $return)) {
/** @var null|ObjectGroup $group */
$group = $groups->firstWhere('id', '=', $row->object_group_id);
if (null !== $group) {
$return[$row->object_groupable_id] = ['title' => $group->title, 'order' => $group->order, 'id' => $group->id];
}
}
}
return $return;
}
public function resetAccountOrder(): void
{
$sets = [
@@ -298,6 +364,15 @@ class AccountRepository implements AccountRepositoryInterface
return $query->get(['accounts.*']);
}
#[\Override]
public function update(Account $account, array $data): Account
{
/** @var AccountUpdateService $service */
$service = app(AccountUpdateService::class);
return $service->update($account, $data);
}
public function searchAccount(string $query, array $types, int $page, int $limit): Collection
{
// search by group, not by user
@@ -331,79 +406,4 @@ class AccountRepository implements AccountRepositoryInterface
return $dbQuery->get(['accounts.*']);
}
#[\Override]
public function update(Account $account, array $data): Account
{
/** @var AccountUpdateService $service */
$service = app(AccountUpdateService::class);
return $service->update($account, $data);
}
#[\Override]
public function getMetaValues(Collection $accounts, array $fields): Collection
{
$query = AccountMeta::whereIn('account_id', $accounts->pluck('id')->toArray());
if (count($fields) > 0) {
$query->whereIn('name', $fields);
}
return $query->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']);
}
#[\Override]
public function getAccountTypes(Collection $accounts): Collection
{
return AccountType::leftJoin('accounts', 'accounts.account_type_id', '=', 'account_types.id')
->whereIn('accounts.id', $accounts->pluck('id')->toArray())
->get(['accounts.id', 'account_types.type'])
;
}
#[\Override]
public function getLastActivity(Collection $accounts): array
{
return Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
->leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id')
->groupBy('transactions.account_id')
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) as date_max')])->toArray() // @phpstan-ignore-line
;
}
#[\Override]
public function getObjectGroups(Collection $accounts): array
{
$groupIds = [];
$return = [];
$set = DB::table('object_groupables')->where('object_groupable_type', Account::class)
->whereIn('object_groupable_id', $accounts->pluck('id')->toArray())->get()
;
/** @var \stdClass $row */
foreach ($set as $row) {
$groupIds[] = $row->object_group_id;
}
$groupIds = array_unique($groupIds);
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
/** @var \stdClass $row */
foreach ($set as $row) {
if (!array_key_exists($row->object_groupable_id, $return)) {
/** @var null|ObjectGroup $group */
$group = $groups->firstWhere('id', '=', $row->object_group_id);
if (null !== $group) {
$return[$row->object_groupable_id] = ['title' => $group->title, 'order' => $group->order, 'id' => $group->id];
}
}
}
return $return;
}
#[\Override]
public function getAccountBalances(Account $account): Collection
{
return $account->accountBalances;
}
}

View File

@@ -37,12 +37,6 @@ interface AccountRepositoryInterface
{
public function countAccounts(array $types): int;
public function getAccountTypes(Collection $accounts): Collection;
public function getLastActivity(Collection $accounts): array;
public function getMetaValues(Collection $accounts, array $fields): Collection;
public function find(int $accountId): ?Account;
public function findByAccountNumber(string $number, array $types): ?Account;
@@ -51,9 +45,11 @@ interface AccountRepositoryInterface
public function findByName(string $name, array $types): ?Account;
public function getAccountBalances(Account $account): Collection;
public function getAccountCurrency(Account $account): ?TransactionCurrency;
public function getAccountBalances(Account $account): Collection;
public function getAccountTypes(Collection $accounts): Collection;
public function getAccountsById(array $accountIds): Collection;
@@ -66,11 +62,15 @@ interface AccountRepositoryInterface
public function getActiveAccountsByType(array $types): Collection;
public function getLastActivity(Collection $accounts): array;
/**
* Return meta value for account. Null if not found.
*/
public function getMetaValue(Account $account, string $field): ?string;
public function getMetaValues(Collection $accounts, array $fields): Collection;
public function getObjectGroups(Collection $accounts): array;
public function getUserGroup(): UserGroup;

View File

@@ -308,22 +308,6 @@ class CurrencyRepository implements CurrencyRepositoryInterface
return $currency->code === config('firefly.default_currency', 'EUR');
}
public function makeDefault(TransactionCurrency $currency): void
{
$current = app('amount')->getDefaultCurrencyByUserGroup($this->userGroup);
app('log')->debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->userGroup->id));
$this->userGroup->currencies()->detach($currency->id);
foreach ($this->userGroup->currencies()->get() as $item) {
$this->userGroup->currencies()->updateExistingPivot($item->id, ['group_default' => false]);
}
$this->userGroup->currencies()->syncWithoutDetaching([$currency->id => ['group_default' => true]]);
if ($current->id !== $currency->id) {
Log::debug('Trigger on a different default currency.');
// clear all native amounts through an event.
event(new UserGroupChangedDefaultCurrency($this->userGroup));
}
}
public function searchCurrency(string $search, int $limit): Collection
{
$query = TransactionCurrency::where('enabled', true);
@@ -388,4 +372,20 @@ class CurrencyRepository implements CurrencyRepositoryInterface
return $service->update($currency, $data);
}
public function makeDefault(TransactionCurrency $currency): void
{
$current = app('amount')->getDefaultCurrencyByUserGroup($this->userGroup);
app('log')->debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->userGroup->id));
$this->userGroup->currencies()->detach($currency->id);
foreach ($this->userGroup->currencies()->get() as $item) {
$this->userGroup->currencies()->updateExistingPivot($item->id, ['group_default' => false]);
}
$this->userGroup->currencies()->syncWithoutDetaching([$currency->id => ['group_default' => true]]);
if ($current->id !== $currency->id) {
Log::debug('Trigger on a different default currency.');
// clear all native amounts through an event.
event(new UserGroupChangedDefaultCurrency($this->userGroup));
}
}
}

View File

@@ -39,16 +39,19 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface
// orderBy('date', 'DESC')->toRawSql();
return
$this->userGroup->currencyExchangeRates()
->where(function (Builder $q1) use ($from, $to) {
$q1->where(function (Builder $q) use ($from, $to) {
->where(function (Builder $q1) use ($from, $to): void {
$q1->where(function (Builder $q) use ($from, $to): void {
$q->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id);
})->orWhere(function (Builder $q) use ($from, $to) {
->where('to_currency_id', $to->id)
;
})->orWhere(function (Builder $q) use ($from, $to): void {
$q->where('from_currency_id', $to->id)
->where('to_currency_id', $from->id);
->where('to_currency_id', $from->id)
;
});
})
->orderBy('date', 'DESC')->get(['currency_exchange_rates.*']);
->orderBy('date', 'DESC')->get(['currency_exchange_rates.*'])
;
}
}

View File

@@ -35,8 +35,14 @@ use Illuminate\Contracts\Validation\ValidationRule;
*/
class IsUniqueAccount implements ValidationRule, DataAwareRule
{
protected \Closure $fail;
protected array $data = [];
protected \Closure $fail;
#[\Override]
public function setData(array $data): void
{
$this->data = $data;
}
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
@@ -103,28 +109,6 @@ class IsUniqueAccount implements ValidationRule, DataAwareRule
return null === $result;
}
/**
* 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;
}
/**
* TODO Duplicate from old validation class.
*
@@ -196,9 +180,25 @@ class IsUniqueAccount implements ValidationRule, DataAwareRule
return 0 === auth()->user()->accounts()->where('name', $value)->count();
}
#[\Override]
public function setData(array $data): void
/**
* TODO duplicate from old validation class.
*/
private function validateAccountAnonymously(): bool
{
$this->data = $data;
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

@@ -28,16 +28,15 @@ use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Log;
class IsAllowedGroupAction implements ValidationRule
{
private array $acceptedRoles;
private string $className;
private string $methodName;
private array $acceptedRoles;
private UserGroupRepositoryInterface $repository;
public function __construct(string $className, string $methodName)

View File

@@ -45,13 +45,6 @@ class Amount
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
}
public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string
{
$format = TransactionCurrency::find($currencyId);
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
}
/**
* This method will properly format the given number, in color or "black and white",
* as a currency, given two things: the currency required and the current locale.
@@ -86,6 +79,13 @@ class Amount
return $result;
}
public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string
{
$format = TransactionCurrency::find($currencyId);
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
}
public function getAllCurrencies(): Collection
{
return TransactionCurrency::orderBy('code', 'ASC')->get();

View File

@@ -35,15 +35,6 @@ class ChartData
$this->series = [];
}
public function render(): array
{
if (0 === count($this->series)) {
throw new FireflyException('No series added to chart');
}
return $this->series;
}
/**
* @throws FireflyException
*/
@@ -64,4 +55,13 @@ class ChartData
$this->series[] = $data;
}
public function render(): array
{
if (0 === count($this->series)) {
throw new FireflyException('No series added to chart');
}
return $this->series;
}
}

View File

@@ -104,19 +104,6 @@ class FireflyConfig
return $this->set($name, $default);
}
public function setEncrypted(string $name, mixed $value): Configuration
{
try {
$encrypted = encrypt($value);
} catch (EncryptException $e) {
Log::error(sprintf('Could not encrypt configuration value "%s": %s', $name, $e->getMessage()));
throw new FireflyException(sprintf('Could not encrypt configuration value "%s". Cowardly refuse to continue.', $name));
}
return $this->set($name, $encrypted);
}
public function set(string $name, mixed $value): Configuration
{
try {
@@ -170,4 +157,17 @@ class FireflyConfig
{
return $this->set($name, $value);
}
public function setEncrypted(string $name, mixed $value): Configuration
{
try {
$encrypted = encrypt($value);
} catch (EncryptException $e) {
Log::error(sprintf('Could not encrypt configuration value "%s": %s', $name, $e->getMessage()));
throw new FireflyException(sprintf('Could not encrypt configuration value "%s". Cowardly refuse to continue.', $name));
}
return $this->set($name, $encrypted);
}
}

View File

@@ -34,6 +34,26 @@ use Illuminate\Support\MessageBag;
*/
trait FormSupport
{
public function multiSelect(string $name, ?array $list = null, $selected = null, ?array $options = null): string
{
$list ??= [];
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = $this->fillFieldValue($name, $selected);
unset($options['autocomplete'], $options['placeholder']);
try {
$html = view('form.multi-select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
} catch (\Throwable $e) {
app('log')->debug(sprintf('Could not render multi-select(): %s', $e->getMessage()));
$html = 'Could not render multi-select.';
}
return $html;
}
/**
* @param mixed $selected
*/
@@ -56,26 +76,6 @@ trait FormSupport
return $html;
}
public function multiSelect(string $name, ?array $list = null, $selected = null, ?array $options = null): string
{
$list ??= [];
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = $this->fillFieldValue($name, $selected);
unset($options['autocomplete'], $options['placeholder']);
try {
$html = view('form.multi-select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
} catch (\Throwable $e) {
app('log')->debug(sprintf('Could not render multi-select(): %s', $e->getMessage()));
$html = 'Could not render multi-select.';
}
return $html;
}
protected function label(string $name, ?array $options = null): string
{
$options ??= [];

View File

@@ -38,6 +38,7 @@ class AccountBalanceGrouped
{
private array $accountIds;
private string $carbonFormat;
private ExchangeRateConverter $converter;
private array $currencies = [];
private array $data = [];
private TransactionCurrency $default;
@@ -45,7 +46,6 @@ class AccountBalanceGrouped
private array $journals = [];
private string $preferredRange;
private Carbon $start;
private ExchangeRateConverter $converter;
public function __construct()
{
@@ -139,51 +139,6 @@ class AccountBalanceGrouped
$converter->summarize();
}
public function setAccounts(Collection $accounts): void
{
$this->accountIds = $accounts->pluck('id')->toArray();
}
public function setDefault(TransactionCurrency $default): void
{
$this->default = $default;
$defaultCurrencyId = $default->id;
$this->currencies = [$default->id => $default]; // currency cache
$this->data[$defaultCurrencyId] = [
'currency_id' => (string) $defaultCurrencyId,
'currency_symbol' => $default->symbol,
'currency_code' => $default->code,
'currency_name' => $default->name,
'currency_decimal_places' => $default->decimal_places,
'native_currency_id' => (string) $defaultCurrencyId,
'native_currency_symbol' => $default->symbol,
'native_currency_code' => $default->code,
'native_currency_name' => $default->name,
'native_currency_decimal_places' => $default->decimal_places,
];
}
public function setEnd(Carbon $end): void
{
$this->end = $end;
}
public function setJournals(array $journals): void
{
$this->journals = $journals;
}
public function setPreferredRange(string $preferredRange): void
{
$this->preferredRange = $preferredRange;
$this->carbonFormat = app('navigation')->preferredCarbonFormatByPeriod($preferredRange);
}
public function setStart(Carbon $start): void
{
$this->start = $start;
}
private function processJournal(array $journal): void
{
// format the date according to the period
@@ -292,4 +247,49 @@ class AccountBalanceGrouped
return $rate;
}
public function setAccounts(Collection $accounts): void
{
$this->accountIds = $accounts->pluck('id')->toArray();
}
public function setDefault(TransactionCurrency $default): void
{
$this->default = $default;
$defaultCurrencyId = $default->id;
$this->currencies = [$default->id => $default]; // currency cache
$this->data[$defaultCurrencyId] = [
'currency_id' => (string) $defaultCurrencyId,
'currency_symbol' => $default->symbol,
'currency_code' => $default->code,
'currency_name' => $default->name,
'currency_decimal_places' => $default->decimal_places,
'native_currency_id' => (string) $defaultCurrencyId,
'native_currency_symbol' => $default->symbol,
'native_currency_code' => $default->code,
'native_currency_name' => $default->name,
'native_currency_decimal_places' => $default->decimal_places,
];
}
public function setEnd(Carbon $end): void
{
$this->end = $end;
}
public function setJournals(array $journals): void
{
$this->journals = $journals;
}
public function setPreferredRange(string $preferredRange): void
{
$this->preferredRange = $preferredRange;
$this->carbonFormat = app('navigation')->preferredCarbonFormatByPeriod($preferredRange);
}
public function setStart(Carbon $start): void
{
$this->start = $start;
}
}

View File

@@ -32,7 +32,8 @@ use FireflyIII\Models\AccountType;
*/
trait AccountFilter
{
protected array $types = [
protected array $types
= [
'all' => [
AccountTypeEnum::DEFAULT->value,
AccountType::CASH,

View File

@@ -39,21 +39,11 @@ class ExchangeRateConverter
{
// use ConvertsExchangeRates;
private array $fallback = [];
private bool $ignoreSettings = false;
private bool $isPrepared = false;
private bool $noPreparedRates = false;
private array $prepared = [];
private int $queryCount = 0;
private bool $ignoreSettings = false;
public function setIgnoreSettings(bool $ignoreSettings): void
{
$this->ignoreSettings = $ignoreSettings;
}
public function enabled(): bool
{
return false !== config('cer.enabled') || true === $this->ignoreSettings;
}
/**
* @throws FireflyException
@@ -70,6 +60,11 @@ class ExchangeRateConverter
return bcmul($amount, $rate);
}
public function enabled(): bool
{
return false !== config('cer.enabled') || true === $this->ignoreSettings;
}
/**
* @throws FireflyException
*/
@@ -138,6 +133,11 @@ class ExchangeRateConverter
return $rate;
}
private function getCacheKey(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
{
return sprintf('cer-%d-%d-%s', $from->id, $to->id, $date->format('Y-m-d'));
}
private function getFromDB(int $from, int $to, string $date): ?string
{
if ($from === $to) {
@@ -338,6 +338,11 @@ class ExchangeRateConverter
Log::debug(sprintf('Fallback rate %s > %s = %s', $to->code, $from->code, bcdiv('1', $fallback)));
}
public function setIgnoreSettings(bool $ignoreSettings): void
{
$this->ignoreSettings = $ignoreSettings;
}
public function summarize(): void
{
if (false === $this->enabled()) {
@@ -345,9 +350,4 @@ class ExchangeRateConverter
}
Log::debug(sprintf('ExchangeRateConverter ran %d queries.', $this->queryCount));
}
private function getCacheKey(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
{
return sprintf('cer-%d-%d-%s', $from->id, $to->id, $date->format('Y-m-d'));
}
}

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