mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-22 20:36:43 +00:00
Code cleanup
This commit is contained in:
@@ -29,7 +29,6 @@ use FireflyIII\Models\Account;
|
|||||||
use FireflyIII\Models\Bill;
|
use FireflyIII\Models\Bill;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\PiggyBank;
|
|
||||||
use FireflyIII\Models\Recurrence;
|
use FireflyIII\Models\Recurrence;
|
||||||
use FireflyIII\Models\Rule;
|
use FireflyIII\Models\Rule;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
|
@@ -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:
|
* This endpoint is documented at:
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAttachmentByPiggyBank
|
* 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);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -65,6 +65,25 @@ class StoreRequest extends FormRequest
|
|||||||
return $data;
|
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.
|
* 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
|
private function getCurrencyFromData(array $data): TransactionCurrency
|
||||||
{
|
{
|
||||||
if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {
|
if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {
|
||||||
|
@@ -40,9 +40,9 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class AccountController extends Controller
|
class AccountController extends Controller
|
||||||
{
|
{
|
||||||
private AccountRepositoryInterface $repository;
|
|
||||||
private TransactionCurrency $default;
|
|
||||||
private ExchangeRateConverter $converter;
|
private ExchangeRateConverter $converter;
|
||||||
|
private TransactionCurrency $default;
|
||||||
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* AccountController constructor.
|
||||||
|
@@ -45,9 +45,9 @@ class AccountController extends Controller
|
|||||||
use CollectsAccountsFromFilter;
|
use CollectsAccountsFromFilter;
|
||||||
use ValidatesUserGroupTrait;
|
use ValidatesUserGroupTrait;
|
||||||
|
|
||||||
private AccountRepositoryInterface $repository;
|
|
||||||
private ChartData $chartData;
|
private ChartData $chartData;
|
||||||
private TransactionCurrency $default;
|
private TransactionCurrency $default;
|
||||||
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@@ -45,9 +45,10 @@ class BalanceController extends Controller
|
|||||||
use CleansChartData;
|
use CleansChartData;
|
||||||
use CollectsAccountsFromFilter;
|
use CollectsAccountsFromFilter;
|
||||||
|
|
||||||
private AccountRepositoryInterface $repository;
|
|
||||||
private GroupCollectorInterface $collector;
|
|
||||||
private ChartData $chartData;
|
private ChartData $chartData;
|
||||||
|
private GroupCollectorInterface $collector;
|
||||||
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
// private TransactionCurrency $default;
|
// private TransactionCurrency $default;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
@@ -55,8 +55,8 @@ class Controller extends BaseController
|
|||||||
use ValidatesUserGroupTrait;
|
use ValidatesUserGroupTrait;
|
||||||
|
|
||||||
protected const string CONTENT_TYPE = 'application/vnd.api+json';
|
protected const string CONTENT_TYPE = 'application/vnd.api+json';
|
||||||
protected ParameterBag $parameters;
|
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
protected ParameterBag $parameters;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -92,8 +92,8 @@ class Controller extends BaseController
|
|||||||
if ($page < 1) {
|
if ($page < 1) {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
}
|
}
|
||||||
if ($page > pow(2,16)) {
|
if ($page > 2 ** 16) {
|
||||||
$page = pow(2,16);
|
$page = 2 ** 16;
|
||||||
}
|
}
|
||||||
$bag->set('page', $page);
|
$bag->set('page', $page);
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ class AccountController extends Controller
|
|||||||
use Actions\DetachRelationship;
|
use Actions\DetachRelationship;
|
||||||
|
|
||||||
use Actions\FetchMany;
|
use Actions\FetchMany;
|
||||||
|
|
||||||
// use Actions\FetchOne;
|
// use Actions\FetchOne;
|
||||||
use Actions\FetchRelated;
|
use Actions\FetchRelated;
|
||||||
use Actions\FetchRelationship;
|
use Actions\FetchRelationship;
|
||||||
|
@@ -36,9 +36,8 @@ use Illuminate\Support\Facades\Log;
|
|||||||
class IndexController extends Controller
|
class IndexController extends Controller
|
||||||
{
|
{
|
||||||
public const string RESOURCE_KEY = 'accounts';
|
public const string RESOURCE_KEY = 'accounts';
|
||||||
|
|
||||||
private AccountRepositoryInterface $repository;
|
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
|
||||||
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* AccountController constructor.
|
||||||
|
@@ -39,9 +39,8 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class ShowController extends Controller
|
class ShowController extends Controller
|
||||||
{
|
{
|
||||||
public const string RESOURCE_KEY = 'accounts';
|
public const string RESOURCE_KEY = 'accounts';
|
||||||
|
|
||||||
private AccountRepositoryInterface $repository;
|
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
|
||||||
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* AccountController constructor.
|
||||||
|
@@ -36,6 +36,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
|
|||||||
class IndexController extends Controller
|
class IndexController extends Controller
|
||||||
{
|
{
|
||||||
use ValidatesUserGroupTrait;
|
use ValidatesUserGroupTrait;
|
||||||
|
|
||||||
public const string RESOURCE_KEY = 'exchange-rates';
|
public const string RESOURCE_KEY = 'exchange-rates';
|
||||||
|
|
||||||
private ExchangeRateRepositoryInterface $repository;
|
private ExchangeRateRepositoryInterface $repository;
|
||||||
|
@@ -38,6 +38,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
|
|||||||
class ShowController extends Controller
|
class ShowController extends Controller
|
||||||
{
|
{
|
||||||
use ValidatesUserGroupTrait;
|
use ValidatesUserGroupTrait;
|
||||||
|
|
||||||
public const string RESOURCE_KEY = 'exchange-rates';
|
public const string RESOURCE_KEY = 'exchange-rates';
|
||||||
|
|
||||||
private ExchangeRateRepositoryInterface $repository;
|
private ExchangeRateRepositoryInterface $repository;
|
||||||
|
@@ -35,9 +35,8 @@ use Illuminate\Pagination\LengthAwarePaginator;
|
|||||||
class IndexController extends Controller
|
class IndexController extends Controller
|
||||||
{
|
{
|
||||||
public const string RESOURCE_KEY = 'transaction-currencies';
|
public const string RESOURCE_KEY = 'transaction-currencies';
|
||||||
|
|
||||||
private CurrencyRepositoryInterface $repository;
|
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
private CurrencyRepositoryInterface $repository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@@ -73,6 +73,16 @@ class AutocompleteRequest extends FormRequest
|
|||||||
return $array;
|
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
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$valid = array_keys($this->types);
|
$valid = array_keys($this->types);
|
||||||
@@ -86,14 +96,4 @@ class AutocompleteRequest extends FormRequest
|
|||||||
'transaction_types' => 'nullable|in:todo',
|
'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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -40,6 +40,7 @@ class BalanceChartRequest extends FormRequest
|
|||||||
use ChecksLogin;
|
use ChecksLogin;
|
||||||
use ConvertsDataTypes;
|
use ConvertsDataTypes;
|
||||||
use ValidatesUserGroupTrait;
|
use ValidatesUserGroupTrait;
|
||||||
|
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -62,6 +62,113 @@ class FixUnevenAmount extends Command
|
|||||||
return 0;
|
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
|
private function fixJournal(int $param): void
|
||||||
{
|
{
|
||||||
// one of the transactions is bad.
|
// one of the transactions is bad.
|
||||||
@@ -130,78 +237,6 @@ class FixUnevenAmount extends Command
|
|||||||
++$this->count;
|
++$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
|
private function isForeignCurrencyTransfer(TransactionJournal $journal): bool
|
||||||
{
|
{
|
||||||
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
|
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
|
||||||
@@ -236,66 +271,31 @@ class FixUnevenAmount extends Command
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function convertOldStyleTransfers(): void
|
private function matchCurrencies(): void
|
||||||
{
|
{
|
||||||
Log::debug('convertOldStyleTransfers()');
|
$journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id')
|
||||||
// select transactions with a foreign amount and a foreign currency. and it's a transfer. and they are different.
|
->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id'))
|
||||||
$transactions = Transaction::distinct()
|
->get(['transaction_journals.*'])
|
||||||
->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;
|
$count = 0;
|
||||||
|
|
||||||
Log::debug(sprintf('Found %d potential journal(s)', $transactions->count()));
|
/** @var TransactionJournal $journal */
|
||||||
|
foreach ($journals as $journal) {
|
||||||
/** @var Transaction $transaction */
|
if (!$this->isForeignCurrencyTransfer($journal)) {
|
||||||
foreach ($transactions as $transaction) {
|
Transaction::where('transaction_journal_id', $journal->id)->update(['transaction_currency_id' => $journal->transaction_currency_id]);
|
||||||
/** @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;
|
++$count;
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('Can skip foreign currency transfer #%d.', $journal->id));
|
||||||
}
|
}
|
||||||
if (0 === $count) {
|
if (0 === $count) {
|
||||||
$this->friendlyPositive('No "old style" foreign currency transfers.');
|
$this->friendlyPositive('Journal currency integrity is OK');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->friendlyPositive(sprintf('Fixed %d journal(s) with mismatched currencies.', $journals->count()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -181,17 +181,6 @@ class RecalculateNativeAmounts extends Command
|
|||||||
Log::debug(sprintf('Recalculated %d auto budgets.', $set->count()));
|
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
|
private function recalculateAvailableBudgets(UserGroup $userGroup, TransactionCurrency $currency): void
|
||||||
{
|
{
|
||||||
Log::debug('Start with available budgets.');
|
Log::debug('Start with available budgets.');
|
||||||
@@ -204,6 +193,17 @@ class RecalculateNativeAmounts extends Command
|
|||||||
Log::debug(sprintf('Recalculated %d available budgets.', $set->count()));
|
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
|
private function calculateTransactions(UserGroup $userGroup, TransactionCurrency $currency): void
|
||||||
{
|
{
|
||||||
// custom query because of the potential size of this update.
|
// custom query because of the potential size of this update.
|
||||||
|
@@ -45,21 +45,8 @@ class AddTimezonesToDates extends Command
|
|||||||
{
|
{
|
||||||
use ShowsFriendlyMessages;
|
use ShowsFriendlyMessages;
|
||||||
|
|
||||||
/**
|
public static array $models
|
||||||
* 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 = [
|
|
||||||
AccountBalance::class => ['date'], // done
|
AccountBalance::class => ['date'], // done
|
||||||
AvailableBudget::class => ['start_date', 'end_date'], // done
|
AvailableBudget::class => ['start_date', 'end_date'], // done
|
||||||
Bill::class => ['date', 'end_date', 'extension_date'], // done
|
Bill::class => ['date', 'end_date', 'extension_date'], // done
|
||||||
@@ -74,6 +61,20 @@ class AddTimezonesToDates extends Command
|
|||||||
TransactionJournal::class => ['date'],
|
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.
|
* Execute the console command.
|
||||||
*/
|
*/
|
||||||
|
@@ -35,13 +35,6 @@ class ConvertDatesToUTC extends Command
|
|||||||
{
|
{
|
||||||
use ShowsFriendlyMessages;
|
use ShowsFriendlyMessages;
|
||||||
|
|
||||||
/**
|
|
||||||
* The name and signature of the console command.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $signature = 'firefly-iii:migrate-to-utc';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
*
|
*
|
||||||
@@ -49,6 +42,13 @@ class ConvertDatesToUTC extends Command
|
|||||||
*/
|
*/
|
||||||
protected $description = 'Convert stored dates to UTC.';
|
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.
|
* Execute the console command.
|
||||||
*/
|
*/
|
||||||
|
@@ -59,12 +59,6 @@ class CorrectAccountBalance extends Command
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function correctBalanceAmounts(): void
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
AccountBalanceCalculator::recalculateAll(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function isExecuted(): bool
|
private function isExecuted(): bool
|
||||||
{
|
{
|
||||||
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
|
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
|
||||||
@@ -76,4 +70,10 @@ class CorrectAccountBalance extends Command
|
|||||||
{
|
{
|
||||||
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function correctBalanceAmounts(): void
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
AccountBalanceCalculator::recalculateAll(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -239,11 +239,6 @@ class OtherCurrenciesCorrections extends Command
|
|||||||
return $currency;
|
return $currency;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function markAsExecuted(): void
|
|
||||||
{
|
|
||||||
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function isMultiCurrency(Account $account): bool
|
private function isMultiCurrency(Account $account): bool
|
||||||
{
|
{
|
||||||
$value = $this->accountRepos->getMetaValue($account, 'is_multi_currency', false);
|
$value = $this->accountRepos->getMetaValue($account, 'is_multi_currency', false);
|
||||||
@@ -253,4 +248,9 @@ class OtherCurrenciesCorrections extends Command
|
|||||||
|
|
||||||
return '1' === $value;
|
return '1' === $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function markAsExecuted(): void
|
||||||
|
{
|
||||||
|
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -39,9 +39,8 @@ class UpgradeMultiPiggyBanks extends Command
|
|||||||
protected $description = 'Upgrade piggybanks so they can use multiple accounts.';
|
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.}';
|
protected $signature = 'firefly-iii:upgrade-multi-piggies {--F|force : Force the execution of this command.}';
|
||||||
|
|
||||||
private PiggyBankRepositoryInterface $repository;
|
|
||||||
private AccountRepositoryInterface $accountRepository;
|
private AccountRepositoryInterface $accountRepository;
|
||||||
|
private PiggyBankRepositoryInterface $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
@@ -71,11 +70,6 @@ class UpgradeMultiPiggyBanks extends Command
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function markAsExecuted(): void
|
|
||||||
{
|
|
||||||
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function upgradePiggyBanks(): void
|
private function upgradePiggyBanks(): void
|
||||||
{
|
{
|
||||||
$this->repository = app(PiggyBankRepositoryInterface::class);
|
$this->repository = app(PiggyBankRepositoryInterface::class);
|
||||||
@@ -109,4 +103,9 @@ class UpgradeMultiPiggyBanks extends Command
|
|||||||
$piggyBank->piggyBankRepetitions()->delete();
|
$piggyBank->piggyBankRepetitions()->delete();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function markAsExecuted(): void
|
||||||
|
{
|
||||||
|
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,9 +28,9 @@ use FireflyIII\Models\Account;
|
|||||||
|
|
||||||
class AccountBalance
|
class AccountBalance
|
||||||
{
|
{
|
||||||
public string $id;
|
|
||||||
public string $amount;
|
public string $amount;
|
||||||
public string $currencyId;
|
public string $currencyId;
|
||||||
|
public string $id;
|
||||||
|
|
||||||
public static function fromArray(): self
|
public static function fromArray(): self
|
||||||
{
|
{
|
||||||
|
@@ -35,8 +35,8 @@ class RegisteredUser extends Event
|
|||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
public User $user;
|
|
||||||
public OwnerNotifiable $owner;
|
public OwnerNotifiable $owner;
|
||||||
|
public User $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance. This event is triggered when a new user registers.
|
* Create a new event instance. This event is triggered when a new user registers.
|
||||||
|
@@ -33,8 +33,8 @@ class MFABackupFewLeft extends Event
|
|||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
public User $user;
|
|
||||||
public int $count;
|
public int $count;
|
||||||
|
public User $user;
|
||||||
|
|
||||||
public function __construct(null|Authenticatable|User $user, int $count)
|
public function __construct(null|Authenticatable|User $user, int $count)
|
||||||
{
|
{
|
||||||
|
@@ -33,8 +33,8 @@ class MFAManyFailedAttempts extends Event
|
|||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
public User $user;
|
|
||||||
public int $count;
|
public int $count;
|
||||||
|
public User $user;
|
||||||
|
|
||||||
public function __construct(null|Authenticatable|User $user, int $count)
|
public function __construct(null|Authenticatable|User $user, int $count)
|
||||||
{
|
{
|
||||||
|
@@ -31,8 +31,8 @@ class OwnerTestNotificationChannel
|
|||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
public OwnerNotifiable $owner;
|
|
||||||
public string $channel;
|
public string $channel;
|
||||||
|
public OwnerNotifiable $owner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance.
|
||||||
|
@@ -31,8 +31,8 @@ class UserTestNotificationChannel
|
|||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
public User $user;
|
|
||||||
public string $channel;
|
public string $channel;
|
||||||
|
public User $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance.
|
||||||
|
@@ -49,8 +49,8 @@ class PiggyBankFactory
|
|||||||
$this->piggyBankRepository->setUser($value);
|
$this->piggyBankRepository->setUser($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private CurrencyRepositoryInterface $currencyRepository;
|
|
||||||
private AccountRepositoryInterface $accountRepository;
|
private AccountRepositoryInterface $accountRepository;
|
||||||
|
private CurrencyRepositoryInterface $currencyRepository;
|
||||||
private PiggyBankRepositoryInterface $piggyBankRepository;
|
private PiggyBankRepositoryInterface $piggyBankRepository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -120,6 +120,21 @@ class PiggyBankFactory
|
|||||||
return $piggyBank;
|
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
|
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
||||||
{
|
{
|
||||||
$piggyBankId = (int) $piggyBankId;
|
$piggyBankId = (int) $piggyBankId;
|
||||||
@@ -162,21 +177,6 @@ class PiggyBankFactory
|
|||||||
->first(['piggy_banks.*']);
|
->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
|
private function setOrder(PiggyBank $piggyBank, array $data): PiggyBank
|
||||||
{
|
{
|
||||||
$this->resetOrder();
|
$this->resetOrder();
|
||||||
|
@@ -43,11 +43,16 @@ use Illuminate\Support\Facades\Notification;
|
|||||||
*/
|
*/
|
||||||
class AdminEventHandler
|
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 {
|
try {
|
||||||
$owner = new OwnerNotifiable();
|
$owner = new OwnerNotifiable();
|
||||||
Notification::send($owner, new UnknownUserLoginAttempt($event->address));
|
Notification::send($owner, new UserInvitation($owner, $event->invitee));
|
||||||
} catch (\Exception $e) { // @phpstan-ignore-line
|
} catch (\Exception $e) { // @phpstan-ignore-line
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
if (str_contains($message, 'Bcc')) {
|
if (str_contains($message, 'Bcc')) {
|
||||||
@@ -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 {
|
try {
|
||||||
$owner = new OwnerNotifiable();
|
$owner = new OwnerNotifiable();
|
||||||
Notification::send($owner, new UserInvitation($owner, $event->invitee));
|
Notification::send($owner, new UnknownUserLoginAttempt($event->address));
|
||||||
} catch (\Exception $e) { // @phpstan-ignore-line
|
} catch (\Exception $e) { // @phpstan-ignore-line
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
if (str_contains($message, 'Bcc')) {
|
if (str_contains($message, 'Bcc')) {
|
||||||
|
@@ -42,56 +42,6 @@ use Illuminate\Support\Facades\Notification;
|
|||||||
|
|
||||||
class MFAHandler
|
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
|
public function sendBackupFewLeftMail(MFABackupFewLeft $event): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
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
|
public function sendMFAFailedAttemptsMail(MFAManyFailedAttempts $event): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
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__));
|
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||||
|
|
||||||
$user = $event->user;
|
$user = $event->user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Notification::send($user, new MFABackupNoLeftNotification($user));
|
Notification::send($user, new NewBackupCodesNotification($user));
|
||||||
} catch (\Exception $e) { // @phpstan-ignore-line
|
} catch (\Exception $e) { // @phpstan-ignore-line
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
if (str_contains($message, 'Bcc')) {
|
if (str_contains($message, 'Bcc')) {
|
||||||
@@ -193,29 +218,4 @@ class MFAHandler
|
|||||||
app('log')->error($e->getTraceAsString());
|
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
* 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
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
@@ -430,80 +506,4 @@ class UserEventHandler
|
|||||||
event(new DetectedNewIPAddress($user));
|
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,31 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class AccountObserver
|
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.
|
* Also delete related objects.
|
||||||
*/
|
*/
|
||||||
@@ -57,34 +82,9 @@ class AccountObserver
|
|||||||
$account->locations()->delete();
|
$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
|
public function updated(Account $account): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "updated" of an account.');
|
Log::debug('Observe "updated" of an account.');
|
||||||
$this->updateNativeAmount($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.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class AutoBudgetObserver
|
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
|
public function created(AutoBudget $autoBudget): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "created" of an auto budget.');
|
Log::debug('Observe "created" of an auto budget.');
|
||||||
$this->updateNativeAmount($autoBudget);
|
$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
|
private function updateNativeAmount(AutoBudget $autoBudget): void
|
||||||
{
|
{
|
||||||
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($autoBudget->budget->user->userGroup);
|
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($autoBudget->budget->user->userGroup);
|
||||||
|
@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class AvailableBudgetObserver
|
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
|
public function created(AvailableBudget $availableBudget): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "created" of an available budget.');
|
Log::debug('Observe "created" of an available budget.');
|
||||||
$this->updateNativeAmount($availableBudget);
|
$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
|
private function updateNativeAmount(AvailableBudget $availableBudget): void
|
||||||
{
|
{
|
||||||
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($availableBudget->user->userGroup);
|
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($availableBudget->user->userGroup);
|
||||||
|
@@ -32,6 +32,12 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class BillObserver
|
class BillObserver
|
||||||
{
|
{
|
||||||
|
public function created(Bill $bill): void
|
||||||
|
{
|
||||||
|
Log::debug('Observe "created" of a bill.');
|
||||||
|
$this->updateNativeAmount($bill);
|
||||||
|
}
|
||||||
|
|
||||||
public function deleting(Bill $bill): void
|
public function deleting(Bill $bill): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Observe "deleting" of a bill.');
|
app('log')->debug('Observe "deleting" of a bill.');
|
||||||
@@ -47,12 +53,6 @@ class BillObserver
|
|||||||
$this->updateNativeAmount($bill);
|
$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
|
private function updateNativeAmount(Bill $bill): void
|
||||||
{
|
{
|
||||||
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($bill->user->userGroup);
|
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($bill->user->userGroup);
|
||||||
|
@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class BudgetLimitObserver
|
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
|
public function created(BudgetLimit $budgetLimit): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "created" of a budget limit.');
|
Log::debug('Observe "created" of a budget limit.');
|
||||||
$this->updateNativeAmount($budgetLimit);
|
$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
|
private function updateNativeAmount(BudgetLimit $budgetLimit): void
|
||||||
{
|
{
|
||||||
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($budgetLimit->budget->user->userGroup);
|
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($budgetLimit->budget->user->userGroup);
|
||||||
|
@@ -30,18 +30,18 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class PiggyBankEventObserver
|
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
|
public function created(PiggyBankEvent $event): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "created" of a piggy bank event.');
|
Log::debug('Observe "created" of a piggy bank event.');
|
||||||
$this->updateNativeAmount($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
|
private function updateNativeAmount(PiggyBankEvent $event): void
|
||||||
{
|
{
|
||||||
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($event->piggyBank->accounts()->first()->user->userGroup);
|
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($event->piggyBank->accounts()->first()->user->userGroup);
|
||||||
|
@@ -33,18 +33,35 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class PiggyBankObserver
|
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
|
public function created(PiggyBank $piggyBank): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "created" of a piggy bank.');
|
Log::debug('Observe "created" of a piggy bank.');
|
||||||
$this->updateNativeAmount($piggyBank);
|
$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
|
private function updateNativeAmount(PiggyBank $piggyBank): void
|
||||||
{
|
{
|
||||||
$group = $piggyBank->accounts()->first()?->user->userGroup;
|
$group = $piggyBank->accounts()->first()?->user->userGroup;
|
||||||
@@ -66,21 +83,4 @@ class PiggyBankObserver
|
|||||||
$piggyBank->saveQuietly();
|
$piggyBank->saveQuietly();
|
||||||
Log::debug('Piggy bank native target amount is updated.');
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,18 @@ class TransactionObserver
|
|||||||
{
|
{
|
||||||
public static bool $recalculate = true;
|
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
|
public function deleting(?Transaction $transaction): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Observe "deleting" of a transaction.');
|
app('log')->debug('Observe "deleting" of a transaction.');
|
||||||
@@ -53,18 +65,6 @@ class TransactionObserver
|
|||||||
$this->updateNativeAmount($transaction);
|
$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
|
private function updateNativeAmount(Transaction $transaction): void
|
||||||
{
|
{
|
||||||
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($transaction->transactionJournal->user->userGroup);
|
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($transaction->transactionJournal->user->userGroup);
|
||||||
|
@@ -163,6 +163,22 @@ class TwoFactorController extends Controller
|
|||||||
app('preferences')->set('mfa_history', $newHistory);
|
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
|
private function addToMFAHistory(string $mfaCode): void
|
||||||
{
|
{
|
||||||
/** @var array $mfaHistory */
|
/** @var array $mfaHistory */
|
||||||
@@ -177,6 +193,12 @@ class TwoFactorController extends Controller
|
|||||||
$this->filterMFAHistory();
|
$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.
|
* Checks if code is in users backup codes.
|
||||||
*/
|
*/
|
||||||
@@ -219,26 +241,4 @@ class TwoFactorController extends Controller
|
|||||||
|
|
||||||
app('preferences')->set('mfa_recovery', $newList);
|
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.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
$notes = $this->blRepository->getNoteText($budgetLimit);
|
||||||
session()->flash('success', trans('firefly.deleted_bl'));
|
|
||||||
|
|
||||||
return redirect(route('budgets.index'));
|
return view('budgets.budget-limits.show', compact('budgetLimit', 'notes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -29,6 +29,7 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
|||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
use Illuminate\Routing\Controller as BaseController;
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
use Route;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Controller.
|
* Class Controller.
|
||||||
@@ -119,7 +120,7 @@ abstract class Controller extends BaseController
|
|||||||
app('view')->share('locale', $locale);
|
app('view')->share('locale', $locale);
|
||||||
app('view')->share('shownDemo', $shownDemo);
|
app('view')->share('shownDemo', $shownDemo);
|
||||||
app('view')->share('current_route_name', $page);
|
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);
|
app('view')->share('darkMode', $darkMode);
|
||||||
|
|
||||||
|
@@ -106,59 +106,6 @@ class IndexController extends Controller
|
|||||||
return view('piggy-banks.index', compact('piggyBanks', 'accounts'));
|
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
|
private function groupPiggyBanks(Collection $collection): array
|
||||||
{
|
{
|
||||||
/** @var PiggyBankTransformer $transformer */
|
/** @var PiggyBankTransformer $transformer */
|
||||||
@@ -251,4 +198,57 @@ class IndexController extends Controller
|
|||||||
|
|
||||||
return $accounts;
|
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']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
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'));
|
return redirect(route('profile.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$subTitle = (string)trans('firefly.mfa_index_title');
|
return view('profile.mfa.backup-codes-intro');
|
||||||
$subTitleIcon = 'fa-calculator';
|
}
|
||||||
$enabledMFA = null !== auth()->user()->mfa_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'));
|
||||||
|
|
||||||
return view('profile.mfa.index')->with(compact('subTitle', 'subTitleIcon', 'enabledMFA'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function disableMFA(Request $request): Factory|RedirectResponse|View
|
public function disableMFA(Request $request): Factory|RedirectResponse|View
|
||||||
@@ -180,66 +220,10 @@ class MfaController extends Controller
|
|||||||
app('preferences')->set('temp-mfa-secret', $secret);
|
app('preferences')->set('temp-mfa-secret', $secret);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return view('profile.mfa.enable-mfa', compact('image', '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.
|
* Submit 2FA for the first time.
|
||||||
*
|
*
|
||||||
@@ -340,4 +324,19 @@ class MfaController extends Controller
|
|||||||
}
|
}
|
||||||
app('preferences')->set('mfa_history', $newHistory);
|
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'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers\Transaction;
|
namespace FireflyIII\Http\Controllers\Transaction;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
@@ -24,9 +24,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Middleware;
|
namespace FireflyIII\Http\Middleware;
|
||||||
|
|
||||||
|
use Barryvdh\Debugbar\Facades\Debugbar;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Vite;
|
use Illuminate\Support\Facades\Vite;
|
||||||
use Barryvdh\Debugbar\Facades\Debugbar;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SecureHeaders
|
* Class SecureHeaders
|
||||||
|
@@ -30,7 +30,8 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
|||||||
*/
|
*/
|
||||||
class VerifyCsrfToken extends Middleware
|
class VerifyCsrfToken extends Middleware
|
||||||
{
|
{
|
||||||
protected $except = [
|
protected $except
|
||||||
|
= [
|
||||||
'oauth/token',
|
'oauth/token',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -9,14 +9,6 @@ use LaravelJsonApi\Core\Resources\JsonApiResource;
|
|||||||
|
|
||||||
class AccountBalanceResource extends JsonApiResource
|
class AccountBalanceResource extends JsonApiResource
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Get the resource id.
|
|
||||||
*/
|
|
||||||
public function id(): string
|
|
||||||
{
|
|
||||||
return $this->resource->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the resource's attributes.
|
* 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.
|
* Get the resource's relationships.
|
||||||
*
|
*
|
||||||
|
@@ -4,11 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\JsonApi\V2\Accounts;
|
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 FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest;
|
use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest;
|
||||||
|
@@ -13,14 +13,6 @@ use LaravelJsonApi\Core\Resources\JsonApiResource;
|
|||||||
*/
|
*/
|
||||||
class AccountResource extends JsonApiResource
|
class AccountResource extends JsonApiResource
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Get the resource id.
|
|
||||||
*/
|
|
||||||
public function id(): string
|
|
||||||
{
|
|
||||||
return (string) $this->resource->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the resource's attributes.
|
* 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.
|
* Get the resource's relationships.
|
||||||
*
|
*
|
||||||
|
@@ -91,6 +91,13 @@ class AccountSchema extends Schema
|
|||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function pagination(): EnumerablePagination
|
||||||
|
{
|
||||||
|
Log::debug(__METHOD__);
|
||||||
|
|
||||||
|
return EnumerablePagination::make();
|
||||||
|
}
|
||||||
|
|
||||||
public function repository(): AccountRepository
|
public function repository(): AccountRepository
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
@@ -102,11 +109,4 @@ class AccountSchema extends Schema
|
|||||||
->withUserGroup($this->userGroup)
|
->withUserGroup($this->userGroup)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pagination(): EnumerablePagination
|
|
||||||
{
|
|
||||||
Log::debug(__METHOD__);
|
|
||||||
|
|
||||||
return EnumerablePagination::make();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -6,11 +6,8 @@ namespace FireflyIII\JsonApi\V2\Accounts;
|
|||||||
|
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use LaravelJsonApi\Eloquent\Contracts\Paginator;
|
use LaravelJsonApi\Eloquent\Contracts\Paginator;
|
||||||
use LaravelJsonApi\Eloquent\Fields\Boolean;
|
|
||||||
use LaravelJsonApi\Eloquent\Fields\DateTime;
|
use LaravelJsonApi\Eloquent\Fields\DateTime;
|
||||||
use LaravelJsonApi\Eloquent\Fields\ID;
|
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\Relations\HasOne;
|
||||||
use LaravelJsonApi\Eloquent\Fields\Str;
|
use LaravelJsonApi\Eloquent\Fields\Str;
|
||||||
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
|
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
|
||||||
|
@@ -126,17 +126,17 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']);
|
return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[\Override]
|
|
||||||
public function paginate(array $page): Page
|
|
||||||
{
|
|
||||||
exit('here weare');
|
|
||||||
// TODO: Implement paginate() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
#[\Override]
|
#[\Override]
|
||||||
public function getOrPaginate(?array $page): iterable
|
public function getOrPaginate(?array $page): iterable
|
||||||
{
|
{
|
||||||
exit('here weare');
|
exit('here weare');
|
||||||
// TODO: Implement getOrPaginate() method.
|
// TODO: Implement getOrPaginate() method.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\Override]
|
||||||
|
public function paginate(array $page): Page
|
||||||
|
{
|
||||||
|
exit('here weare');
|
||||||
|
// TODO: Implement paginate() method.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,13 @@ class CrudAccount extends CrudResource
|
|||||||
{
|
{
|
||||||
use CollectsCustomParameters;
|
use CollectsCustomParameters;
|
||||||
|
|
||||||
|
public function create(array $validatedData): Account
|
||||||
|
{
|
||||||
|
var_dump($validatedData);
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the supplied site.
|
* Read the supplied site.
|
||||||
*/
|
*/
|
||||||
@@ -51,11 +58,4 @@ class CrudAccount extends CrudResource
|
|||||||
|
|
||||||
return $enrichment->enrichSingle($account);
|
return $enrichment->enrichSingle($account);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(array $validatedData): Account
|
|
||||||
{
|
|
||||||
var_dump($validatedData);
|
|
||||||
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -94,6 +94,11 @@ class Account extends Model
|
|||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function accountBalances(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(AccountBalance::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function accountType(): BelongsTo
|
public function accountType(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(AccountType::class);
|
return $this->belongsTo(AccountType::class);
|
||||||
@@ -123,11 +128,6 @@ class Account extends Model
|
|||||||
return $this->hasMany(AccountMeta::class);
|
return $this->hasMany(AccountMeta::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function accountBalances(): HasMany
|
|
||||||
{
|
|
||||||
return $this->hasMany(AccountBalance::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEditNameAttribute(): string
|
public function getEditNameAttribute(): string
|
||||||
{
|
{
|
||||||
$name = $this->name;
|
$name = $this->name;
|
||||||
|
@@ -15,15 +15,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
class AccountBalance extends Model
|
class AccountBalance extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $fillable = ['account_id', 'title', 'transaction_currency_id', 'balance', 'date', 'date_tz'];
|
|
||||||
|
|
||||||
protected function casts(): array
|
protected $fillable = ['account_id', 'title', 'transaction_currency_id', 'balance', 'date', 'date_tz'];
|
||||||
{
|
|
||||||
return [
|
|
||||||
'date' => SeparateTimezoneCaster::class,
|
|
||||||
'balance' => 'string',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function account(): BelongsTo
|
public function account(): BelongsTo
|
||||||
{
|
{
|
||||||
@@ -34,4 +27,12 @@ class AccountBalance extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(TransactionCurrency::class);
|
return $this->belongsTo(TransactionCurrency::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'date' => SeparateTimezoneCaster::class,
|
||||||
|
'balance' => 'string',
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use Deprecated;
|
||||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use FireflyIII\Enums\AutoBudgetType;
|
|
||||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@@ -47,11 +46,11 @@ class AutoBudget extends Model
|
|||||||
|
|
||||||
#[\Deprecated]
|
#[\Deprecated]
|
||||||
public const int AUTO_BUDGET_ROLLOVER = 2;
|
public const int AUTO_BUDGET_ROLLOVER = 2;
|
||||||
protected $fillable = ['budget_id', 'amount', 'period'];
|
protected $casts
|
||||||
|
= [
|
||||||
protected $casts = [
|
|
||||||
'amount' => 'string',
|
'amount' => 'string',
|
||||||
];
|
];
|
||||||
|
protected $fillable = ['budget_id', 'amount', 'period'];
|
||||||
|
|
||||||
public function budget(): BelongsTo
|
public function budget(): BelongsTo
|
||||||
{
|
{
|
||||||
@@ -63,13 +62,6 @@ class AutoBudget extends Model
|
|||||||
return $this->belongsTo(TransactionCurrency::class);
|
return $this->belongsTo(TransactionCurrency::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function casts(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
// 'auto_budget_type' => AutoBudgetType::class,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function amount(): Attribute
|
protected function amount(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
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
|
protected function transactionCurrencyId(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
|
@@ -86,11 +86,6 @@ class BudgetLimit extends Model
|
|||||||
return $this->belongsTo(Budget::class);
|
return $this->belongsTo(Budget::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function transactionCurrency(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TransactionCurrency::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the notes.
|
* Get all the notes.
|
||||||
*/
|
*/
|
||||||
@@ -99,6 +94,11 @@ class BudgetLimit extends Model
|
|||||||
return $this->morphMany(Note::class, 'noteable');
|
return $this->morphMany(Note::class, 'noteable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function transactionCurrency(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(TransactionCurrency::class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the amount
|
* Get the amount
|
||||||
*/
|
*/
|
||||||
|
@@ -79,16 +79,16 @@ class PiggyBank extends Model
|
|||||||
throw new NotFoundHttpException();
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function transactionCurrency(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TransactionCurrency::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function account(): BelongsTo
|
public function account(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Account::class);
|
return $this->belongsTo(Account::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function accounts(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Account::class)->withPivot(['current_amount', 'native_current_amount']);
|
||||||
|
}
|
||||||
|
|
||||||
public function attachments(): MorphMany
|
public function attachments(): MorphMany
|
||||||
{
|
{
|
||||||
return $this->morphMany(Attachment::class, 'attachable');
|
return $this->morphMany(Attachment::class, 'attachable');
|
||||||
@@ -115,11 +115,6 @@ class PiggyBank extends Model
|
|||||||
return $this->hasMany(PiggyBankEvent::class);
|
return $this->hasMany(PiggyBankEvent::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function accounts(): BelongsToMany
|
|
||||||
{
|
|
||||||
return $this->belongsToMany(Account::class)->withPivot(['current_amount', 'native_current_amount']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function piggyBankRepetitions(): HasMany
|
public function piggyBankRepetitions(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(PiggyBankRepetition::class);
|
return $this->hasMany(PiggyBankRepetition::class);
|
||||||
@@ -133,6 +128,11 @@ class PiggyBank extends Model
|
|||||||
$this->attributes['target_amount'] = (string) $value;
|
$this->attributes['target_amount'] = (string) $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function transactionCurrency(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(TransactionCurrency::class);
|
||||||
|
}
|
||||||
|
|
||||||
protected function accountId(): Attribute
|
protected function accountId(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
|
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use FireflyIII\Enums\RecurrenceRepetitionWeekend;
|
|
||||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@@ -67,6 +66,11 @@ class RecurrenceRepetition extends Model
|
|||||||
/** @var string The table to store the data in */
|
/** @var string The table to store the data in */
|
||||||
protected $table = 'recurrences_repetitions';
|
protected $table = 'recurrences_repetitions';
|
||||||
|
|
||||||
|
public function recurrence(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Recurrence::class);
|
||||||
|
}
|
||||||
|
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@@ -74,11 +78,6 @@ class RecurrenceRepetition extends Model
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function recurrence(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Recurrence::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recurrenceId(): Attribute
|
protected function recurrenceId(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
|
@@ -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
|
* 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
|
* Get the foreign amount
|
||||||
*/
|
*/
|
||||||
|
@@ -23,7 +23,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use FireflyIII\Enums\TransactionTypeEnum;
|
|
||||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@@ -67,13 +66,6 @@ class TransactionType extends Model
|
|||||||
];
|
];
|
||||||
protected $fillable = ['type'];
|
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).
|
* 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);
|
return $this->hasMany(TransactionJournal::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// 'type' => TransactionTypeEnum::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -54,15 +54,6 @@ class Webhook extends Model
|
|||||||
];
|
];
|
||||||
protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'user_group_id', 'url', 'title', 'secret'];
|
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
|
public static function getDeliveries(): array
|
||||||
{
|
{
|
||||||
$array = [];
|
$array = [];
|
||||||
@@ -164,4 +155,13 @@ class Webhook extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(WebhookMessage::class);
|
return $this->hasMany(WebhookMessage::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// 'delivery' => WebhookDelivery::class,
|
||||||
|
// 'response' => WebhookResponse::class,
|
||||||
|
// 'trigger' => WebhookTrigger::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -73,21 +73,14 @@ class BillReminder extends Notification
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getSubject(): string
|
||||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
|
||||||
*/
|
|
||||||
public function toSlack(User $notifiable)
|
|
||||||
{
|
{
|
||||||
$bill = $this->bill;
|
$message = (string) trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
|
||||||
$url = route('bills.show', [$bill->id]);
|
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()
|
return $message;
|
||||||
->warning()
|
|
||||||
->attachment(static function ($attachment) use ($bill, $url): void {
|
|
||||||
$attachment->title((string) trans('firefly.visit_bill', ['name' => $bill->name]), $url);
|
|
||||||
})
|
|
||||||
->content($this->getSubject())
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toNtfy(User $notifiable): 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]);
|
$bill = $this->bill;
|
||||||
if (0 === $this->diff) {
|
$url = route('bills.show', [$bill->id]);
|
||||||
$message = (string) trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
||||||
@@ -100,6 +83,23 @@ class RuleActionFailed extends Notification
|
|||||||
return PushoverMessage::create($this->message);
|
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)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
|
@@ -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
|
public function toNtfy(User $notifiable): Message
|
||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
||||||
@@ -101,6 +93,14 @@ class UserNewPassword extends Notification
|
|||||||
return PushoverMessage::create((string) trans('email.reset_pw_message'));
|
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)
|
public function via(User $notifiable)
|
||||||
{
|
{
|
||||||
return ReturnsAvailableChannels::returnChannels('user', $notifiable);
|
return ReturnsAvailableChannels::returnChannels('user', $notifiable);
|
||||||
|
@@ -30,19 +30,16 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class AccountPolicy
|
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
|
public function create(): bool
|
||||||
{
|
{
|
||||||
return auth()->check();
|
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.
|
* Everybody can do this, but selection should limit to user.
|
||||||
*
|
*
|
||||||
@@ -65,8 +62,11 @@ class AccountPolicy
|
|||||||
return $this->view($user, $account);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,13 @@ class UserPolicy
|
|||||||
return auth()->check() && $user->id === $account->user_id;
|
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.
|
* Everybody can do this, but selection should limit to user.
|
||||||
*
|
*
|
||||||
@@ -49,11 +56,4 @@ class UserPolicy
|
|||||||
|
|
||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function viewAccounts(User $user): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return auth()->check();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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
|
public function searchAccount(string $query, array $types, int $limit): Collection
|
||||||
{
|
{
|
||||||
$dbQuery = $this->user->accounts()
|
$dbQuery = $this->user->accounts()
|
||||||
@@ -634,15 +645,4 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
|
|
||||||
return $factory->create($data);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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
|
public function setUser(null|Authenticatable|User $user): void
|
||||||
{
|
{
|
||||||
if ($user instanceof User) {
|
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
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
@@ -427,27 +450,4 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
|
|||||||
|
|
||||||
return $limit;
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -48,10 +48,6 @@ interface BudgetLimitRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function destroyAll(): void;
|
public function destroyAll(): void;
|
||||||
|
|
||||||
public function getNoteText(BudgetLimit $budgetLimit): string;
|
|
||||||
|
|
||||||
public function setNoteText(BudgetLimit $budgetLimit, string $text): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a budget limit.
|
* Destroy a budget limit.
|
||||||
*/
|
*/
|
||||||
@@ -68,6 +64,10 @@ interface BudgetLimitRepositoryInterface
|
|||||||
|
|
||||||
public function getBudgetLimits(Budget $budget, ?Carbon $start = null, ?Carbon $end = null): Collection;
|
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 setUser(null|Authenticatable|User $user): void;
|
||||||
|
|
||||||
public function store(array $data): BudgetLimit;
|
public function store(array $data): BudgetLimit;
|
||||||
|
@@ -37,6 +37,12 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
|||||||
{
|
{
|
||||||
private User $user;
|
private User $user;
|
||||||
|
|
||||||
|
#[\Override]
|
||||||
|
public function find(int $currencyId): ?TransactionCurrency
|
||||||
|
{
|
||||||
|
return TransactionCurrency::find($currencyId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find by currency code, return NULL if unfound.
|
* Find by currency code, return NULL if unfound.
|
||||||
*/
|
*/
|
||||||
@@ -106,10 +112,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
|||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[\Override]
|
|
||||||
public function find(int $currencyId): ?TransactionCurrency
|
|
||||||
{
|
|
||||||
return TransactionCurrency::find($currencyId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,8 @@ use Illuminate\Support\Collection;
|
|||||||
*/
|
*/
|
||||||
interface CurrencyRepositoryInterface
|
interface CurrencyRepositoryInterface
|
||||||
{
|
{
|
||||||
|
public function find(int $currencyId): ?TransactionCurrency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find by currency code, return NULL if unfound.
|
* Find by currency code, return NULL if unfound.
|
||||||
*
|
*
|
||||||
@@ -42,8 +44,6 @@ interface CurrencyRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function findByCode(string $currencyCode): ?TransactionCurrency;
|
public function findByCode(string $currencyCode): ?TransactionCurrency;
|
||||||
|
|
||||||
public function find(int $currencyId): ?TransactionCurrency;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the complete set of transactions but needs
|
* Returns the complete set of transactions but needs
|
||||||
* no user object.
|
* no user object.
|
||||||
|
@@ -80,24 +80,6 @@ trait ModifiesPiggyBanks
|
|||||||
return true;
|
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
|
public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool
|
||||||
{
|
{
|
||||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||||
@@ -220,57 +202,6 @@ trait ModifiesPiggyBanks
|
|||||||
return $factory->store($data);
|
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
|
public function update(PiggyBank $piggyBank, array $data): PiggyBank
|
||||||
{
|
{
|
||||||
$piggyBank = $this->updateProperties($piggyBank, $data);
|
$piggyBank = $this->updateProperties($piggyBank, $data);
|
||||||
@@ -363,4 +294,73 @@ trait ModifiesPiggyBanks
|
|||||||
|
|
||||||
return $piggyBank;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
public function getEvents(PiggyBank $piggyBank): Collection
|
||||||
{
|
{
|
||||||
return $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
|
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 "".
|
* Returns the suggested amount the user should save per month, or "".
|
||||||
*/
|
*/
|
||||||
@@ -352,28 +352,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
|||||||
return $balance;
|
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]
|
#[\Override]
|
||||||
public function purgeAll(): void
|
public function purgeAll(): void
|
||||||
{
|
{
|
||||||
@@ -398,4 +376,26 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
|||||||
$factory->user = $this->user;
|
$factory->user = $this->user;
|
||||||
$factory->resetOrder();
|
$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.*']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -53,8 +53,6 @@ interface PiggyBankRepositoryInterface
|
|||||||
|
|
||||||
public function destroyAll(): void;
|
public function destroyAll(): void;
|
||||||
|
|
||||||
public function purgeAll(): void;
|
|
||||||
|
|
||||||
public function find(int $piggyBankId): ?PiggyBank;
|
public function find(int $piggyBankId): ?PiggyBank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,22 +68,20 @@ interface PiggyBankRepositoryInterface
|
|||||||
* Get current amount saved in piggy bank.
|
* Get current amount saved in piggy bank.
|
||||||
*/
|
*/
|
||||||
public function getCurrentAmount(PiggyBank $piggyBank, ?Account $account = null): string;
|
public function getCurrentAmount(PiggyBank $piggyBank, ?Account $account = null): string;
|
||||||
/**
|
|
||||||
* Get current amount saved in piggy bank.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all events.
|
* Get all events.
|
||||||
*/
|
*/
|
||||||
public function getEvents(PiggyBank $piggyBank): Collection;
|
public function getEvents(PiggyBank $piggyBank): Collection;
|
||||||
|
/**
|
||||||
|
* Get current amount saved in piggy bank.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for connecting to a piggy bank.
|
* Used for connecting to a piggy bank.
|
||||||
*/
|
*/
|
||||||
public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string;
|
public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string;
|
||||||
|
|
||||||
public function updateNote(PiggyBank $piggyBank, string $note): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return note for piggy bank.
|
* Return note for piggy bank.
|
||||||
*/
|
*/
|
||||||
@@ -113,6 +109,8 @@ interface PiggyBankRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function leftOnAccount(PiggyBank $piggyBank, Account $account, Carbon $date): string;
|
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 removeAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool;
|
||||||
|
|
||||||
public function removeAmountFromAll(PiggyBank $piggyBank, string $amount): void;
|
public function removeAmountFromAll(PiggyBank $piggyBank, string $amount): void;
|
||||||
@@ -148,4 +146,6 @@ interface PiggyBankRepositoryInterface
|
|||||||
* Update existing piggy bank.
|
* Update existing piggy bank.
|
||||||
*/
|
*/
|
||||||
public function update(PiggyBank $piggyBank, array $data): PiggyBank;
|
public function update(PiggyBank $piggyBank, array $data): PiggyBank;
|
||||||
|
|
||||||
|
public function updateNote(PiggyBank $piggyBank, string $note): void;
|
||||||
}
|
}
|
||||||
|
@@ -174,6 +174,18 @@ class UserGroupRepository implements UserGroupRepositoryInterface
|
|||||||
return UserGroup::all();
|
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
|
public function setUser(null|Authenticatable|User $user): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
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->user_group_id = $userGroup->id;
|
||||||
$this->user->save();
|
$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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -36,13 +36,13 @@ interface UserGroupRepositoryInterface
|
|||||||
{
|
{
|
||||||
public function destroy(UserGroup $userGroup): void;
|
public function destroy(UserGroup $userGroup): void;
|
||||||
|
|
||||||
public function getMembershipsFromGroupId(int $groupId): Collection;
|
|
||||||
|
|
||||||
public function get(): Collection;
|
public function get(): Collection;
|
||||||
|
|
||||||
|
public function getAll(): Collection;
|
||||||
|
|
||||||
public function getById(int $id): ?UserGroup;
|
public function getById(int $id): ?UserGroup;
|
||||||
|
|
||||||
public function getAll(): Collection;
|
public function getMembershipsFromGroupId(int $groupId): Collection;
|
||||||
|
|
||||||
public function setUser(null|Authenticatable|User $user): void;
|
public function setUser(null|Authenticatable|User $user): void;
|
||||||
|
|
||||||
|
@@ -117,6 +117,12 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\Override]
|
||||||
|
public function getAccountBalances(Account $account): Collection
|
||||||
|
{
|
||||||
|
return $account->accountBalances;
|
||||||
|
}
|
||||||
|
|
||||||
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
||||||
{
|
{
|
||||||
$type = $account->accountType->type;
|
$type = $account->accountType->type;
|
||||||
@@ -164,6 +170,15 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
return $account;
|
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
|
public function getAccountsById(array $accountIds): Collection
|
||||||
{
|
{
|
||||||
$query = $this->userGroup->accounts();
|
$query = $this->userGroup->accounts();
|
||||||
@@ -218,6 +233,57 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
return $query->get(['accounts.*']);
|
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
|
public function resetAccountOrder(): void
|
||||||
{
|
{
|
||||||
$sets = [
|
$sets = [
|
||||||
@@ -298,6 +364,15 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
return $query->get(['accounts.*']);
|
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
|
public function searchAccount(string $query, array $types, int $page, int $limit): Collection
|
||||||
{
|
{
|
||||||
// search by group, not by user
|
// search by group, not by user
|
||||||
@@ -331,79 +406,4 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
return $dbQuery->get(['accounts.*']);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -37,12 +37,6 @@ interface AccountRepositoryInterface
|
|||||||
{
|
{
|
||||||
public function countAccounts(array $types): int;
|
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 find(int $accountId): ?Account;
|
||||||
|
|
||||||
public function findByAccountNumber(string $number, array $types): ?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 findByName(string $name, array $types): ?Account;
|
||||||
|
|
||||||
|
public function getAccountBalances(Account $account): Collection;
|
||||||
|
|
||||||
public function getAccountCurrency(Account $account): ?TransactionCurrency;
|
public function getAccountCurrency(Account $account): ?TransactionCurrency;
|
||||||
|
|
||||||
public function getAccountBalances(Account $account): Collection;
|
public function getAccountTypes(Collection $accounts): Collection;
|
||||||
|
|
||||||
public function getAccountsById(array $accountIds): Collection;
|
public function getAccountsById(array $accountIds): Collection;
|
||||||
|
|
||||||
@@ -66,11 +62,15 @@ interface AccountRepositoryInterface
|
|||||||
|
|
||||||
public function getActiveAccountsByType(array $types): Collection;
|
public function getActiveAccountsByType(array $types): Collection;
|
||||||
|
|
||||||
|
public function getLastActivity(Collection $accounts): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return meta value for account. Null if not found.
|
* Return meta value for account. Null if not found.
|
||||||
*/
|
*/
|
||||||
public function getMetaValue(Account $account, string $field): ?string;
|
public function getMetaValue(Account $account, string $field): ?string;
|
||||||
|
|
||||||
|
public function getMetaValues(Collection $accounts, array $fields): Collection;
|
||||||
|
|
||||||
public function getObjectGroups(Collection $accounts): array;
|
public function getObjectGroups(Collection $accounts): array;
|
||||||
|
|
||||||
public function getUserGroup(): UserGroup;
|
public function getUserGroup(): UserGroup;
|
||||||
|
@@ -308,22 +308,6 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
|||||||
return $currency->code === config('firefly.default_currency', 'EUR');
|
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
|
public function searchCurrency(string $search, int $limit): Collection
|
||||||
{
|
{
|
||||||
$query = TransactionCurrency::where('enabled', true);
|
$query = TransactionCurrency::where('enabled', true);
|
||||||
@@ -388,4 +372,20 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
|||||||
|
|
||||||
return $service->update($currency, $data);
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -39,16 +39,19 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface
|
|||||||
// orderBy('date', 'DESC')->toRawSql();
|
// orderBy('date', 'DESC')->toRawSql();
|
||||||
return
|
return
|
||||||
$this->userGroup->currencyExchangeRates()
|
$this->userGroup->currencyExchangeRates()
|
||||||
->where(function (Builder $q1) use ($from, $to) {
|
->where(function (Builder $q1) use ($from, $to): void {
|
||||||
$q1->where(function (Builder $q) use ($from, $to) {
|
$q1->where(function (Builder $q) use ($from, $to): void {
|
||||||
$q->where('from_currency_id', $from->id)
|
$q->where('from_currency_id', $from->id)
|
||||||
->where('to_currency_id', $to->id);
|
->where('to_currency_id', $to->id)
|
||||||
})->orWhere(function (Builder $q) use ($from, $to) {
|
;
|
||||||
|
})->orWhere(function (Builder $q) use ($from, $to): void {
|
||||||
$q->where('from_currency_id', $to->id)
|
$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.*'])
|
||||||
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,8 +35,14 @@ use Illuminate\Contracts\Validation\ValidationRule;
|
|||||||
*/
|
*/
|
||||||
class IsUniqueAccount implements ValidationRule, DataAwareRule
|
class IsUniqueAccount implements ValidationRule, DataAwareRule
|
||||||
{
|
{
|
||||||
protected \Closure $fail;
|
|
||||||
protected array $data = [];
|
protected array $data = [];
|
||||||
|
protected \Closure $fail;
|
||||||
|
|
||||||
|
#[\Override]
|
||||||
|
public function setData(array $data): void
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
#[\Override]
|
#[\Override]
|
||||||
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
||||||
@@ -103,28 +109,6 @@ class IsUniqueAccount implements ValidationRule, DataAwareRule
|
|||||||
return null === $result;
|
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.
|
* TODO Duplicate from old validation class.
|
||||||
*
|
*
|
||||||
@@ -196,9 +180,25 @@ class IsUniqueAccount implements ValidationRule, DataAwareRule
|
|||||||
return 0 === auth()->user()->accounts()->where('name', $value)->count();
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,16 +28,15 @@ use FireflyIII\Enums\UserRoleEnum;
|
|||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\Validation\ValidationRule;
|
|
||||||
use Illuminate\Auth\Access\AuthorizationException;
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class IsAllowedGroupAction implements ValidationRule
|
class IsAllowedGroupAction implements ValidationRule
|
||||||
{
|
{
|
||||||
|
private array $acceptedRoles;
|
||||||
private string $className;
|
private string $className;
|
||||||
private string $methodName;
|
private string $methodName;
|
||||||
|
|
||||||
private array $acceptedRoles;
|
|
||||||
private UserGroupRepositoryInterface $repository;
|
private UserGroupRepositoryInterface $repository;
|
||||||
|
|
||||||
public function __construct(string $className, string $methodName)
|
public function __construct(string $className, string $methodName)
|
||||||
|
@@ -45,13 +45,6 @@ class Amount
|
|||||||
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
|
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",
|
* 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.
|
* as a currency, given two things: the currency required and the current locale.
|
||||||
@@ -86,6 +79,13 @@ class Amount
|
|||||||
return $result;
|
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
|
public function getAllCurrencies(): Collection
|
||||||
{
|
{
|
||||||
return TransactionCurrency::orderBy('code', 'ASC')->get();
|
return TransactionCurrency::orderBy('code', 'ASC')->get();
|
||||||
|
@@ -35,15 +35,6 @@ class ChartData
|
|||||||
$this->series = [];
|
$this->series = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(): array
|
|
||||||
{
|
|
||||||
if (0 === count($this->series)) {
|
|
||||||
throw new FireflyException('No series added to chart');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->series;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
@@ -64,4 +55,13 @@ class ChartData
|
|||||||
|
|
||||||
$this->series[] = $data;
|
$this->series[] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function render(): array
|
||||||
|
{
|
||||||
|
if (0 === count($this->series)) {
|
||||||
|
throw new FireflyException('No series added to chart');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->series;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -104,19 +104,6 @@ class FireflyConfig
|
|||||||
return $this->set($name, $default);
|
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
|
public function set(string $name, mixed $value): Configuration
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -170,4 +157,17 @@ class FireflyConfig
|
|||||||
{
|
{
|
||||||
return $this->set($name, $value);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,26 @@ use Illuminate\Support\MessageBag;
|
|||||||
*/
|
*/
|
||||||
trait FormSupport
|
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
|
* @param mixed $selected
|
||||||
*/
|
*/
|
||||||
@@ -56,26 +76,6 @@ trait FormSupport
|
|||||||
return $html;
|
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
|
protected function label(string $name, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
|
@@ -38,6 +38,7 @@ class AccountBalanceGrouped
|
|||||||
{
|
{
|
||||||
private array $accountIds;
|
private array $accountIds;
|
||||||
private string $carbonFormat;
|
private string $carbonFormat;
|
||||||
|
private ExchangeRateConverter $converter;
|
||||||
private array $currencies = [];
|
private array $currencies = [];
|
||||||
private array $data = [];
|
private array $data = [];
|
||||||
private TransactionCurrency $default;
|
private TransactionCurrency $default;
|
||||||
@@ -45,7 +46,6 @@ class AccountBalanceGrouped
|
|||||||
private array $journals = [];
|
private array $journals = [];
|
||||||
private string $preferredRange;
|
private string $preferredRange;
|
||||||
private Carbon $start;
|
private Carbon $start;
|
||||||
private ExchangeRateConverter $converter;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -139,51 +139,6 @@ class AccountBalanceGrouped
|
|||||||
$converter->summarize();
|
$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
|
private function processJournal(array $journal): void
|
||||||
{
|
{
|
||||||
// format the date according to the period
|
// format the date according to the period
|
||||||
@@ -292,4 +247,49 @@ class AccountBalanceGrouped
|
|||||||
|
|
||||||
return $rate;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,8 @@ use FireflyIII\Models\AccountType;
|
|||||||
*/
|
*/
|
||||||
trait AccountFilter
|
trait AccountFilter
|
||||||
{
|
{
|
||||||
protected array $types = [
|
protected array $types
|
||||||
|
= [
|
||||||
'all' => [
|
'all' => [
|
||||||
AccountTypeEnum::DEFAULT->value,
|
AccountTypeEnum::DEFAULT->value,
|
||||||
AccountType::CASH,
|
AccountType::CASH,
|
||||||
|
@@ -39,21 +39,11 @@ class ExchangeRateConverter
|
|||||||
{
|
{
|
||||||
// use ConvertsExchangeRates;
|
// use ConvertsExchangeRates;
|
||||||
private array $fallback = [];
|
private array $fallback = [];
|
||||||
|
private bool $ignoreSettings = false;
|
||||||
private bool $isPrepared = false;
|
private bool $isPrepared = false;
|
||||||
private bool $noPreparedRates = false;
|
private bool $noPreparedRates = false;
|
||||||
private array $prepared = [];
|
private array $prepared = [];
|
||||||
private int $queryCount = 0;
|
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
|
* @throws FireflyException
|
||||||
@@ -70,6 +60,11 @@ class ExchangeRateConverter
|
|||||||
return bcmul($amount, $rate);
|
return bcmul($amount, $rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function enabled(): bool
|
||||||
|
{
|
||||||
|
return false !== config('cer.enabled') || true === $this->ignoreSettings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
@@ -138,6 +133,11 @@ class ExchangeRateConverter
|
|||||||
return $rate;
|
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
|
private function getFromDB(int $from, int $to, string $date): ?string
|
||||||
{
|
{
|
||||||
if ($from === $to) {
|
if ($from === $to) {
|
||||||
@@ -338,6 +338,11 @@ class ExchangeRateConverter
|
|||||||
Log::debug(sprintf('Fallback rate %s > %s = %s', $to->code, $from->code, bcdiv('1', $fallback)));
|
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
|
public function summarize(): void
|
||||||
{
|
{
|
||||||
if (false === $this->enabled()) {
|
if (false === $this->enabled()) {
|
||||||
@@ -345,9 +350,4 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
Log::debug(sprintf('ExchangeRateConverter ran %d queries.', $this->queryCount));
|
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
Reference in New Issue
Block a user