mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-02 19:16:39 +00:00
Compare commits
34 Commits
develop-20
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
|
7504b21c3e | ||
|
b7dad8166d | ||
|
2da1b43c37 | ||
|
a606315884 | ||
|
295feedd77 | ||
|
d3b2748c8f | ||
|
1b4655fd70 | ||
|
05f67ef584 | ||
|
04ab7ba07d | ||
|
5806323970 | ||
|
ee260a3df7 | ||
|
7cb41fb333 | ||
|
d38adbfdc2 | ||
|
e6a6766ef1 | ||
|
a1e596491c | ||
|
9c920908a6 | ||
|
0014bffeb8 | ||
|
63c17f99b2 | ||
|
ec1e0e2807 | ||
|
2f16419a7b | ||
|
02c13859e7 | ||
|
57ec9b8e36 | ||
|
41ad35880d | ||
|
3aa946e028 | ||
|
53e46895aa | ||
|
c61389037d | ||
|
6172d60e00 | ||
|
f909f1d9ff | ||
|
55018ca046 | ||
|
19c746a865 | ||
|
503d2aa786 | ||
|
70d83ab501 | ||
|
edab602bb7 | ||
|
f9bcc4b1fa |
@@ -189,7 +189,7 @@ SEND_REPORT_JOURNALS=true
|
||||
ENABLE_EXTERNAL_MAP=false
|
||||
|
||||
#
|
||||
# Enable or disable exchange rate conversion. This function isn't used yet by Firefly III
|
||||
# Enable or disable exchange rate conversion.
|
||||
#
|
||||
ENABLE_EXCHANGE_RATES=false
|
||||
|
||||
|
@@ -34,6 +34,7 @@ use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
@@ -83,8 +84,8 @@ class AccountController extends Controller
|
||||
$return = [];
|
||||
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
|
||||
|
||||
// set date to end-of-day for account balance.
|
||||
$date->endOfDay();
|
||||
// set date to subday + end-of-day for account balance. so it is at $date 23:59:59
|
||||
$date->subDay()->endOfDay();
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($result as $account) {
|
||||
@@ -92,6 +93,8 @@ class AccountController extends Controller
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency;
|
||||
$useCurrency = $currency;
|
||||
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
|
||||
// this one is correct.
|
||||
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date);
|
||||
$key = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance';
|
||||
$useCurrency = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? $this->nativeCurrency : $currency;
|
||||
@@ -104,15 +107,20 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
$return[] = [
|
||||
'id' => (string) $account->id,
|
||||
'name' => $account->name,
|
||||
'name_with_balance' => $nameWithBalance,
|
||||
'type' => $account->accountType->type,
|
||||
'currency_id' => (string) $useCurrency->id,
|
||||
'currency_name' => $useCurrency->name,
|
||||
'currency_code' => $useCurrency->code,
|
||||
'currency_symbol' => $useCurrency->symbol,
|
||||
'currency_decimal_places' => $useCurrency->decimal_places,
|
||||
'id' => (string) $account->id,
|
||||
'name' => $account->name,
|
||||
'name_with_balance' => $nameWithBalance,
|
||||
'type' => $account->accountType->type,
|
||||
'currency_id' => (string) $useCurrency->id,
|
||||
'currency_name' => $useCurrency->name,
|
||||
'currency_code' => $useCurrency->code,
|
||||
'currency_symbol' => $useCurrency->symbol,
|
||||
'currency_decimal_places' => $useCurrency->decimal_places,
|
||||
'account_currency_id' => (string) $currency->id,
|
||||
'account_currency_name' => $currency->name,
|
||||
'account_currency_code' => $currency->code,
|
||||
'account_currency_symbol' => $currency->symbol,
|
||||
'account_currency_decimal_places' => $currency->decimal_places,
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
@@ -41,6 +42,8 @@ class TransactionController extends Controller
|
||||
private TransactionGroupRepositoryInterface $groupRepository;
|
||||
private JournalRepositoryInterface $repository;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||
|
||||
/**
|
||||
* TransactionController constructor.
|
||||
*/
|
||||
@@ -51,10 +54,12 @@ class TransactionController extends Controller
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->groupRepository->setUser($user);
|
||||
$this->groupRepository->setUserGroup($userGroup);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\V2\AbstractTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -59,6 +60,7 @@ abstract class Controller extends BaseController
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
protected const string CONTENT_TYPE = 'application/vnd.api+json';
|
||||
protected const string JSON_CONTENT_TYPE = 'application/json';
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Transaction;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Transaction\StoreRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Events\StoredTransactionGroup;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
@@ -37,6 +38,7 @@ use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -49,6 +51,8 @@ class StoreController extends Controller
|
||||
|
||||
private TransactionGroupRepositoryInterface $groupRepository;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
|
||||
|
||||
/**
|
||||
* TransactionController constructor.
|
||||
*/
|
||||
@@ -59,9 +63,11 @@ class StoreController extends Controller
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->groupRepository->setUser($admin);
|
||||
$this->groupRepository->setUserGroup($userGroup);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -79,61 +85,58 @@ class StoreController extends Controller
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
app('log')->debug('Now in API StoreController::store()');
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user();
|
||||
$data['user_group'] = $this->userGroup;
|
||||
|
||||
Log::channel('audit')
|
||||
->info('Store new transaction over API.', $data)
|
||||
;
|
||||
Log::channel('audit')->info('Store new transaction over API.', $data);
|
||||
|
||||
try {
|
||||
$transactionGroup = $this->groupRepository->store($data);
|
||||
} catch (DuplicateTransactionException $e) {
|
||||
app('log')->warning('Caught a duplicate transaction. Return error message.');
|
||||
$validator = \Validator::make(
|
||||
['transactions' => [['description' => $e->getMessage()]]],
|
||||
['transactions.0.description' => new IsDuplicateTransaction()]
|
||||
);
|
||||
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
|
||||
throw new ValidationException($validator);
|
||||
} catch (FireflyException $e) {
|
||||
app('log')->warning('Caught an exception. Return error message.');
|
||||
app('log')->error($e->getMessage());
|
||||
$message = sprintf('Internal exception: %s', $e->getMessage());
|
||||
$validator = \Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
|
||||
throw new ValidationException($validator);
|
||||
}
|
||||
app('preferences')->mark();
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
|
||||
|
||||
$manager = $this->getManager();
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
->setUserGroup($this->userGroup)
|
||||
// filter on transaction group.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
;
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
||||
}
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
@@ -21,25 +21,6 @@
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* ConvertDatesToUTC.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Models\AutoBudget;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\Bill;
|
||||
@@ -33,8 +34,14 @@ use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CorrectsAmounts extends Command
|
||||
{
|
||||
@@ -45,6 +52,8 @@ class CorrectsAmounts extends Command
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
// transfers must not have foreign currency info if both accounts have the same currency.
|
||||
$this->correctTransfers();
|
||||
// auto budgets must be positive
|
||||
$this->fixAutoBudgets();
|
||||
// available budgets must be positive
|
||||
@@ -62,6 +71,7 @@ class CorrectsAmounts extends Command
|
||||
// rule_triggers must be positive or zero (amount_less, amount_more, amount_is)
|
||||
$this->fixRuleTriggers();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -182,4 +192,63 @@ class CorrectsAmounts extends Command
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function correctTransfers(): void
|
||||
{
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$type = TransactionType::where('type', TransactionTypeEnum::TRANSFER->value)->first();
|
||||
$journals = TransactionJournal::where('transaction_type_id', $type->id)->get();
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$repository->setUser($journal->user);
|
||||
$native = Amount::getNativeCurrencyByUserGroup($journal->userGroup);
|
||||
|
||||
/** @var null|Transaction $source */
|
||||
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
|
||||
/** @var null|Transaction $destination */
|
||||
$destination = $journal->transactions()->where('amount', '>', 0)->first();
|
||||
if (null === $source || null === $destination) {
|
||||
continue;
|
||||
}
|
||||
if (null === $source->foreign_currency_id || null === $destination->foreign_currency_id) {
|
||||
continue;
|
||||
}
|
||||
$sourceAccount = $source->account;
|
||||
$destAccount = $destination->account;
|
||||
if (null === $sourceAccount || null === $destAccount) {
|
||||
continue;
|
||||
}
|
||||
$sourceCurrency = $repository->getAccountCurrency($sourceAccount) ?? $native;
|
||||
$destCurrency = $repository->getAccountCurrency($destAccount) ?? $native;
|
||||
|
||||
if ($sourceCurrency->id === $destCurrency->id) {
|
||||
Log::debug('Both accounts have the same currency. Removing foreign currency info.');
|
||||
$source->foreign_currency_id = null;
|
||||
$source->foreign_amount = null;
|
||||
$source->save();
|
||||
$destination->foreign_currency_id = null;
|
||||
$destination->foreign_amount = null;
|
||||
$destination->save();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// validate source
|
||||
if ($destCurrency->id !== $source->foreign_currency_id) {
|
||||
Log::debug(sprintf('Journal #%d: Transaction #%d refers to "%s" but should refer to "%s".', $journal->id, $source->id, $source->foreignCurrency->code, $destCurrency->code));
|
||||
$source->foreign_currency_id = $destCurrency->id;
|
||||
$source->save();
|
||||
}
|
||||
|
||||
// validate destination:
|
||||
if ($sourceCurrency->id !== $destination->foreign_currency_id) {
|
||||
Log::debug(sprintf('Journal #%d: Transaction #%d refers to "%s" but should refer to "%s".', $journal->id, $destination->id, $destination->foreignCurrency->code, $sourceCurrency->code));
|
||||
$destination->foreign_currency_id = $sourceCurrency->id;
|
||||
$destination->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,25 +21,6 @@
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* AddTimezonesToDates.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
|
||||
/**
|
||||
@@ -34,6 +35,7 @@ use FireflyIII\User;
|
||||
class TagFactory
|
||||
{
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
|
||||
public function findOrCreate(string $tag): ?Tag
|
||||
{
|
||||
@@ -101,6 +103,12 @@ class TagFactory
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->user = $user;
|
||||
$this->userGroup = $user->userGroup;
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,6 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\UniqueIban;
|
||||
use FireflyIII\Services\Internal\Update\AccountUpdateService;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\QueryException;
|
||||
|
||||
/**
|
||||
@@ -216,12 +215,4 @@ class TransactionFactory
|
||||
{
|
||||
$this->reconciled = $reconciled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
// empty function.
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,7 @@ class TransactionGroupFactory
|
||||
{
|
||||
private TransactionJournalFactory $journalFactory;
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
|
||||
/**
|
||||
* TransactionGroupFactory constructor.
|
||||
@@ -54,7 +56,8 @@ class TransactionGroupFactory
|
||||
public function create(array $data): TransactionGroup
|
||||
{
|
||||
app('log')->debug('Now in TransactionGroupFactory::create()');
|
||||
$this->journalFactory->setUser($this->user);
|
||||
$this->journalFactory->setUser($data['user']);
|
||||
$this->journalFactory->setUserGroup($data['user_group']);
|
||||
$this->journalFactory->setErrorOnHash($data['error_if_duplicate_hash'] ?? false);
|
||||
|
||||
try {
|
||||
@@ -76,7 +79,7 @@ class TransactionGroupFactory
|
||||
|
||||
$group = new TransactionGroup();
|
||||
$group->user()->associate($this->user);
|
||||
$group->userGroup()->associate($data['user_group'] ?? $this->user->userGroup);
|
||||
$group->userGroup()->associate($data['user_group']);
|
||||
$group->title = $title;
|
||||
$group->save();
|
||||
|
||||
@@ -92,4 +95,9 @@ class TransactionGroupFactory
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
@@ -69,6 +70,7 @@ class TransactionJournalFactory
|
||||
private PiggyBankRepositoryInterface $piggyRepository;
|
||||
private TransactionTypeRepositoryInterface $typeRepository;
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -176,7 +178,6 @@ class TransactionJournalFactory
|
||||
if (true === FireflyConfig::get('utc', false)->data) {
|
||||
$carbon->setTimezone('UTC');
|
||||
}
|
||||
// $carbon->setTimezone('UTC');
|
||||
|
||||
try {
|
||||
// validate source and destination using a new Validator.
|
||||
@@ -228,7 +229,7 @@ class TransactionJournalFactory
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
'user_group_id' => $this->user->user_group_id,
|
||||
'user_group_id' => $this->userGroup->id,
|
||||
'transaction_type_id' => $type->id,
|
||||
'bill_id' => $billId,
|
||||
'transaction_currency_id' => $currency->id,
|
||||
@@ -244,7 +245,6 @@ class TransactionJournalFactory
|
||||
|
||||
/** Create two transactions. */
|
||||
$transactionFactory = app(TransactionFactory::class);
|
||||
$transactionFactory->setUser($this->user);
|
||||
$transactionFactory->setJournal($journal);
|
||||
$transactionFactory->setAccount($sourceAccount);
|
||||
$transactionFactory->setCurrency($currency);
|
||||
@@ -263,7 +263,6 @@ class TransactionJournalFactory
|
||||
|
||||
/** @var TransactionFactory $transactionFactory */
|
||||
$transactionFactory = app(TransactionFactory::class);
|
||||
$transactionFactory->setUser($this->user);
|
||||
$transactionFactory->setJournal($journal);
|
||||
$transactionFactory->setAccount($destinationAccount);
|
||||
$transactionFactory->setAccountInformation($destInfo);
|
||||
@@ -404,7 +403,8 @@ class TransactionJournalFactory
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->user = $user;
|
||||
$this->userGroup = $user->userGroup;
|
||||
$this->currencyRepository->setUser($this->user);
|
||||
$this->tagFactory->setUser($user);
|
||||
$this->billRepository->setUser($this->user);
|
||||
@@ -414,6 +414,18 @@ class TransactionJournalFactory
|
||||
$this->accountRepository->setUser($this->user);
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
$this->currencyRepository->setUserGroup($userGroup);
|
||||
$this->tagFactory->setUserGroup($userGroup);
|
||||
$this->billRepository->setUserGroup($userGroup);
|
||||
$this->budgetRepository->setUserGroup($userGroup);
|
||||
$this->categoryRepository->setUserGroup($userGroup);
|
||||
$this->piggyRepository->setUserGroup($userGroup);
|
||||
$this->accountRepository->setUserGroup($userGroup);
|
||||
}
|
||||
|
||||
private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
|
@@ -33,6 +33,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class MonthReportGenerator.
|
||||
@@ -52,10 +53,9 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
{
|
||||
$auditData = [];
|
||||
$dayBefore = clone $this->start;
|
||||
$dayBefore->subDay();
|
||||
|
||||
// move to end of day
|
||||
$dayBefore->endOfDay();
|
||||
// set date to subday + end-of-day for account balance. so it is at $date 23:59:59
|
||||
$dayBefore->subDay()->endOfDay();
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($this->accounts as $account) {
|
||||
@@ -136,6 +136,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
;
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$journals = array_reverse($journals, true);
|
||||
// this call is correct.
|
||||
Log::debug(sprintf('getAuditReport: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$dayBeforeBalance = Steam::finalAccountBalance($account, $date);
|
||||
$startBalance = $dayBeforeBalance['balance'];
|
||||
$defaultCurrency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup);
|
||||
@@ -170,6 +172,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
$journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date');
|
||||
}
|
||||
$locale = app('steam')->getLocale();
|
||||
// call is correct.
|
||||
Log::debug(sprintf('getAuditReport end: Call finalAccountBalance with date/time "%s"', $this->end->toIso8601String()));
|
||||
|
||||
return [
|
||||
'journals' => $journals,
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
|
||||
@@ -81,6 +82,8 @@ class AccountObserver
|
||||
foreach ($account->piggyBanks()->get() as $piggy) {
|
||||
$piggy->accounts()->detach($account);
|
||||
}
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($account->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
@@ -46,6 +47,7 @@ class BillObserver
|
||||
$repository->setUser($bill->user);
|
||||
|
||||
// app('log')->debug('Observe "deleting" of a bill.');
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($bill->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
@@ -39,6 +40,7 @@ class BudgetObserver
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
$repository->setUser($budget->user);
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($budget->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
|
||||
@@ -38,6 +39,7 @@ class CategoryObserver
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
$repository->setUser($category->user);
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($category->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
@@ -50,6 +51,7 @@ class PiggyBankObserver
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
$repository->setUser($piggyBank->accounts()->first()->user);
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($piggyBank->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
|
||||
@@ -38,6 +39,7 @@ class RecurrenceObserver
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
$repository->setUser($recurrence->user);
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($recurrence->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
|
||||
@@ -38,6 +39,7 @@ class TagObserver
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
$repository->setUser($tag->user);
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($tag->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
|
||||
@@ -45,6 +46,8 @@ class TransactionJournalObserver
|
||||
$transaction->delete();
|
||||
}
|
||||
});
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($transactionJournal->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
|
@@ -258,7 +258,12 @@ trait AccountCollection
|
||||
if (null === $account) {
|
||||
continue;
|
||||
}
|
||||
$balance = Steam::finalAccountBalance($account, $transaction['date']);
|
||||
// the balance must be found BEFORE the transaction date.
|
||||
// so sub one second. This is not perfect, but works well enough.
|
||||
$date = clone $transaction['date'];
|
||||
$date->subSecond();
|
||||
Log::debug(sprintf('accountBalanceIs: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date);
|
||||
$result = bccomp($balance['balance'], $value);
|
||||
Log::debug(sprintf('"%s" vs "%s" is %d', $balance['balance'], $value, $result));
|
||||
|
||||
|
@@ -79,6 +79,7 @@ class NetWorth implements NetWorthInterface
|
||||
Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s')));
|
||||
$default = Amount::getNativeCurrency();
|
||||
$netWorth = [];
|
||||
Log::debug(sprintf('NetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s')));
|
||||
$balances = Steam::finalAccountsBalance($accounts, $date);
|
||||
|
||||
/** @var Account $account */
|
||||
@@ -159,6 +160,7 @@ class NetWorth implements NetWorthInterface
|
||||
*/
|
||||
$accounts = $this->getAccounts();
|
||||
$return = [];
|
||||
Log::debug(sprintf('SumNetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s')));
|
||||
$balances = Steam::finalAccountsBalance($accounts, $date);
|
||||
foreach ($accounts as $account) {
|
||||
$currency = $this->getRepository()->getAccountCurrency($account);
|
||||
|
@@ -33,6 +33,7 @@ use FireflyIII\Support\Http\Controllers\BasicDataSupport;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
@@ -90,9 +91,11 @@ class IndexController extends Controller
|
||||
$start->subDay();
|
||||
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
$startBalances = app('steam')->finalAccountsBalance($accounts, $start);
|
||||
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
||||
$activities = app('steam')->getLastActivities($ids);
|
||||
Log::debug(sprintf('inactive start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('inactive end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
||||
$activities = Steam::getLastActivities($ids);
|
||||
|
||||
|
||||
$accounts->each(
|
||||
@@ -102,7 +105,7 @@ class IndexController extends Controller
|
||||
$account->startBalances = Steam::filterAccountBalance($startBalances[$account->id] ?? [], $account, $this->convertToNative, $currency);
|
||||
$account->endBalances = Steam::filterAccountBalance($endBalances[$account->id] ?? [], $account, $this->convertToNative, $currency);
|
||||
$account->differences = $this->subtract($account->startBalances, $account->endBalances);
|
||||
$account->interest = app('steam')->bcround($this->repository->getMetaValue($account, 'interest'), 4);
|
||||
$account->interest = Steam::bcround($this->repository->getMetaValue($account, 'interest'), 4);
|
||||
$account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')));
|
||||
$account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type));
|
||||
$account->current_debt = '0';
|
||||
@@ -153,9 +156,11 @@ class IndexController extends Controller
|
||||
$start->subDay();
|
||||
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
$startBalances = app('steam')->finalAccountsBalance($accounts, $start);
|
||||
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
||||
$activities = app('steam')->getLastActivities($ids);
|
||||
Log::debug(sprintf('index start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('index end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
||||
$activities = Steam::getLastActivities($ids);
|
||||
|
||||
|
||||
$accounts->each(
|
||||
@@ -168,7 +173,7 @@ class IndexController extends Controller
|
||||
$account->endBalances = Steam::filterAccountBalance($endBalances[$account->id] ?? [], $account, $this->convertToNative, $currency);
|
||||
$account->differences = $this->subtract($account->startBalances, $account->endBalances);
|
||||
$account->lastActivityDate = $this->isInArrayDate($activities, $account->id);
|
||||
$account->interest = app('steam')->bcround($interest, 4);
|
||||
$account->interest = Steam::bcround($interest, 4);
|
||||
$account->interestPeriod = (string) trans(
|
||||
sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))
|
||||
);
|
||||
|
@@ -39,6 +39,7 @@ use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
@@ -113,7 +114,10 @@ class ReconcileController extends Controller
|
||||
$end->endOfDay();
|
||||
|
||||
$startDate = clone $start;
|
||||
$startDate->subDay()->endOfDay();
|
||||
$startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59
|
||||
// both are validated and are correct.
|
||||
Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String()));
|
||||
Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places);
|
||||
$endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places);
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
|
||||
|
@@ -37,6 +37,7 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
@@ -120,12 +121,7 @@ class ShowController extends Controller
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setAccounts(new Collection([$account]))
|
||||
->setLimit($pageSize)
|
||||
->setPage($page)->withAccountInformation()->withCategoryInformation()
|
||||
->setRange($start, $end)
|
||||
;
|
||||
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation()->setRange($start, $end);
|
||||
|
||||
// this search will not include transaction groups where this asset account (or liability)
|
||||
// is just part of ONE of the journals. To force this:
|
||||
@@ -135,7 +131,14 @@ class ShowController extends Controller
|
||||
|
||||
$groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||
$showAll = false;
|
||||
$balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToNative, $accountCurrency);
|
||||
// correct
|
||||
$now = today()->endOfDay();
|
||||
if ($now->gt($end) || $now->lt($start)) {
|
||||
$now = $end;
|
||||
}
|
||||
|
||||
Log::debug(sprintf('show: Call finalAccountBalance with date/time "%s"', $now->toIso8601String()));
|
||||
$balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToNative, $accountCurrency);
|
||||
|
||||
return view(
|
||||
'accounts.show',
|
||||
@@ -200,6 +203,8 @@ class ShowController extends Controller
|
||||
$groups->setPath(route('accounts.show.all', [$account->id]));
|
||||
$chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
||||
$showAll = true;
|
||||
// correct
|
||||
Log::debug(sprintf('showAll: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToNative, $accountCurrency);
|
||||
|
||||
return view(
|
||||
|
@@ -109,6 +109,8 @@ class AccountController extends Controller
|
||||
$accountNames = $this->extractNames($accounts);
|
||||
|
||||
// grab all balances
|
||||
Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
||||
|
||||
@@ -335,7 +337,7 @@ class AccountController extends Controller
|
||||
$start = clone session('start', today(config('app.timezone'))->startOfMonth());
|
||||
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
||||
$defaultSet = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
||||
Log::debug('Default set is ', $defaultSet);
|
||||
// Log::debug('Default set is ', $defaultSet);
|
||||
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
|
||||
$frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data;
|
||||
Log::debug('Frontpage preference set is ', $frontpageArray);
|
||||
@@ -422,8 +424,8 @@ class AccountController extends Controller
|
||||
{
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
// TODO not sure if these date ranges will work as expected.
|
||||
Log::debug(sprintf('Now in period("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
$chartData = [];
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty('chart.account.period');
|
||||
$cache->addProperty($start);
|
||||
@@ -452,7 +454,7 @@ class AccountController extends Controller
|
||||
$range = Steam::filterAccountBalances($range, $account, $this->convertToNative, $accountCurrency);
|
||||
|
||||
// temp, get end balance.
|
||||
Log::debug('temp get end balance');
|
||||
Log::debug(sprintf('period: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
Steam::finalAccountBalance($account, $end);
|
||||
Log::debug('END temp get end balance done');
|
||||
|
||||
@@ -505,7 +507,7 @@ class AccountController extends Controller
|
||||
$chartData = [];
|
||||
|
||||
foreach ($return as $key => $info) {
|
||||
if (3 === strlen($key)) {
|
||||
if ('balance' !== $key && 'native_balance' !== $key) {
|
||||
// assume it's a currency:
|
||||
$setCurrency = $this->currencyRepository->findByCode($key);
|
||||
$info['currency_symbol'] = $setCurrency->symbol;
|
||||
@@ -575,6 +577,8 @@ class AccountController extends Controller
|
||||
$accountNames = $this->extractNames($accounts);
|
||||
|
||||
// grab all balances
|
||||
Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
||||
|
||||
|
@@ -168,15 +168,14 @@ class BudgetController extends Controller
|
||||
}
|
||||
$locale = app('steam')->getLocale();
|
||||
$entries = [];
|
||||
$amount = $budgetLimit->amount;
|
||||
$amount = $budgetLimit->amount ?? '0';
|
||||
$budgetCollection = new Collection([$budget]);
|
||||
$currency = $budgetLimit->transactionCurrency;
|
||||
if ($this->convertToNative) {
|
||||
$amount = $budgetLimit->native_amount;
|
||||
$amount = $budgetLimit->native_amount ?? '0';
|
||||
$currency = $this->defaultCurrency;
|
||||
}
|
||||
|
||||
|
||||
while ($start <= $end) {
|
||||
$current = clone $start;
|
||||
$expenses = $this->opsRepository->sumExpenses($current, $current, null, $budgetCollection, $budgetLimit->transactionCurrency);
|
||||
|
@@ -100,7 +100,10 @@ class ReportController extends Controller
|
||||
|
||||
while ($current < $end) {
|
||||
// get balances by date, grouped by currency.
|
||||
$result = $helper->byAccounts($filtered, $current);
|
||||
$balanceCurrent = clone $current;
|
||||
$balanceCurrent->subDay()->endOfDay(); // go to correct moment.
|
||||
Log::debug(sprintf('Call byAccounts("%s")', $balanceCurrent->format('Y-m-d H:i:s')));
|
||||
$result = $helper->byAccounts($filtered, $balanceCurrent);
|
||||
|
||||
// loop result, add to array.
|
||||
/** @var array $netWorthItem */
|
||||
|
@@ -259,7 +259,7 @@ class DebugController extends Controller
|
||||
$system = $this->getSystemInformation();
|
||||
$docker = $this->getBuildInfo();
|
||||
$app = $this->getAppInfo();
|
||||
$user = $this->getuserInfo();
|
||||
$user = $this->getUserInfo();
|
||||
|
||||
return (string) view('partials.debug-table', compact('system', 'docker', 'app', 'user'));
|
||||
}
|
||||
|
@@ -195,15 +195,23 @@ class ReconcileController extends Controller
|
||||
$startDate->subDay();
|
||||
|
||||
$currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency;
|
||||
// correct
|
||||
Log::debug(sprintf('transactions: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String()));
|
||||
Log::debug(sprintf('transactions2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places);
|
||||
$endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places);
|
||||
|
||||
// get the transactions
|
||||
$selectionStart = clone $start;
|
||||
$selectionStart->startOfDay();
|
||||
$selectionStart->subDays(3);
|
||||
$selectionEnd = clone $end;
|
||||
$selectionEnd->endOfDay();
|
||||
$selectionEnd->addDays(3);
|
||||
|
||||
// to make sure the bar is in the right place:
|
||||
$start->startOfDay();
|
||||
|
||||
// grab transactions:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
|
29
app/Http/Controllers/Preferences/NotificationsController.php
Normal file
29
app/Http/Controllers/Preferences/NotificationsController.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* NotificationsController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Preferences;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
class NotificationsController extends Controller {}
|
@@ -43,6 +43,7 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
@@ -223,7 +224,9 @@ class ConvertController extends Controller
|
||||
// group accounts:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$balance = Steam::finalAccountBalance($account, today()->endOfDay())['balance'];
|
||||
$date = today()->endOfDay();
|
||||
Log::debug(sprintf('getLiabilities: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date)['balance'];
|
||||
$currency = $this->accountRepository->getAccountCurrency($account) ?? $this->defaultCurrency;
|
||||
$role = 'l_'.$account->accountType->type;
|
||||
$key = (string) trans('firefly.opt_group_'.$role);
|
||||
@@ -245,7 +248,9 @@ class ConvertController extends Controller
|
||||
// group accounts:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$balance = Steam::finalAccountBalance($account, today()->endOfDay())['balance'];
|
||||
$date = today()->endOfDay();
|
||||
Log::debug(sprintf('getAssetAccounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date)['balance'];
|
||||
$currency = $this->accountRepository->getAccountCurrency($account) ?? $this->defaultCurrency;
|
||||
$role = (string) $this->accountRepository->getMetaValue($account, 'account_role');
|
||||
if ('' === $role) {
|
||||
|
@@ -419,9 +419,7 @@ class CreateRecurringTransactions implements ShouldQueue
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$single = [
|
||||
'type' => null === $transaction?->transactionType?->type ?
|
||||
strtolower($recurrence->transactionType->type) :
|
||||
strtolower($transaction->transactionType->type),
|
||||
'type' => null === $transaction?->transactionType?->type ? strtolower($recurrence->transactionType->type) : strtolower($transaction->transactionType->type), // @phpstan-ignore-line
|
||||
'date' => $date,
|
||||
'user' => $recurrence->user_id,
|
||||
'currency_id' => $transaction->transaction_currency_id,
|
||||
|
@@ -112,6 +112,11 @@ class TransactionJournal extends Model
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function userGroup(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(UserGroup::class);
|
||||
}
|
||||
|
||||
public function attachments(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Attachment::class, 'attachable');
|
||||
|
@@ -40,6 +40,7 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
|
||||
use FireflyIII\Services\Internal\Update\AccountUpdateService;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
@@ -51,7 +52,7 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class AccountRepository implements AccountRepositoryInterface
|
||||
{
|
||||
private User $user;
|
||||
use UserGroupTrait;
|
||||
|
||||
/**
|
||||
* Moved here from account CRUD.
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -149,6 +150,8 @@ interface AccountRepositoryInterface
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
public function store(array $data): Account;
|
||||
|
||||
public function update(Account $account, array $data): Account;
|
||||
|
@@ -29,9 +29,11 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class AccountTasker.
|
||||
@@ -46,10 +48,13 @@ class AccountTasker implements AccountTaskerInterface
|
||||
public function getAccountReport(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$yesterday = clone $start;
|
||||
$yesterday->subDay();
|
||||
$startSet = app('steam')->finalAccountsBalance($accounts, $yesterday);
|
||||
$endSet = app('steam')->finalAccountsBalance($accounts, $end);
|
||||
app('log')->debug('Start of accountreport');
|
||||
$yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including.
|
||||
$end->endOfDay(); // needs to be end of day to be correct.
|
||||
Log::debug(sprintf('getAccountReport: finalAccountsBalance("%s")', $yesterday->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('getAccountReport: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
||||
$startSet = Steam::finalAccountsBalance($accounts, $yesterday);
|
||||
$endSet = Steam::finalAccountsBalance($accounts, $end);
|
||||
Log::debug('Start of accountreport');
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
@@ -90,10 +95,10 @@ class AccountTasker implements AccountTaskerInterface
|
||||
$entry['end_balance'] = $endSet[$account->id]['balance'] ?? '0';
|
||||
|
||||
// first journal exists, and is on start, then this is the actual opening balance:
|
||||
if (null !== $first && $first->date->isSameDay($start) && TransactionTypeEnum::OPENING_BALANCE->value === $first->transactionType->type) {
|
||||
app('log')->debug(sprintf('Date of first journal for %s is %s', $account->name, $first->date->format('Y-m-d')));
|
||||
if (null !== $first && $first->date->isSameDay($yesterday) && TransactionTypeEnum::OPENING_BALANCE->value === $first->transactionType->type) {
|
||||
Log::debug(sprintf('Date of first journal for %s is %s', $account->name, $first->date->format('Y-m-d')));
|
||||
$entry['start_balance'] = $first->transactions()->where('account_id', $account->id)->first()->amount;
|
||||
app('log')->debug(sprintf('Account %s was opened on %s, so opening balance is %f', $account->name, $start->format('Y-m-d'), $entry['start_balance']));
|
||||
Log::debug(sprintf('Account %s was opened on %s, so opening balance is %f', $account->name, $yesterday->format('Y-m-d'), $entry['start_balance']));
|
||||
}
|
||||
$return['sums'][$currency->id]['start'] = bcadd($return['sums'][$currency->id]['start'], $entry['start_balance']);
|
||||
$return['sums'][$currency->id]['end'] = bcadd($return['sums'][$currency->id]['end'], $entry['end_balance']);
|
||||
@@ -173,7 +178,7 @@ class AccountTasker implements AccountTaskerInterface
|
||||
];
|
||||
$report['accounts'][$key]['sum'] = bcadd($report['accounts'][$key]['sum'], $journal['amount']);
|
||||
|
||||
app('log')->debug(sprintf('Sum for %s is now %s', $journal['destination_account_name'], $report['accounts'][$key]['sum']));
|
||||
Log::debug(sprintf('Sum for %s is now %s', $journal['destination_account_name'], $report['accounts'][$key]['sum']));
|
||||
|
||||
++$report['accounts'][$key]['count'];
|
||||
}
|
||||
|
@@ -38,8 +38,7 @@ use FireflyIII\Services\Internal\Destroy\BillDestroyService;
|
||||
use FireflyIII\Services\Internal\Update\BillUpdateService;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -51,8 +50,7 @@ use Illuminate\Support\Facades\Log;
|
||||
class BillRepository implements BillRepositoryInterface
|
||||
{
|
||||
use CreatesObjectGroups;
|
||||
|
||||
private User $user;
|
||||
use UserGroupTrait;
|
||||
|
||||
public function billEndsWith(string $query, int $limit): Collection
|
||||
{
|
||||
@@ -294,13 +292,6 @@ class BillRepository implements BillRepositoryInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void
|
||||
{
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
||||
public function getPaginator(int $size): LengthAwarePaginator
|
||||
{
|
||||
return $this->user->bills()
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Bill;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -40,6 +41,8 @@ interface BillRepositoryInterface
|
||||
|
||||
public function billStartsWith(string $query, int $limit): Collection;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
/**
|
||||
* Add correct order to bills.
|
||||
*/
|
||||
|
@@ -41,8 +41,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\BudgetDestroyService;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -52,7 +51,7 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
class BudgetRepository implements BudgetRepositoryInterface
|
||||
{
|
||||
private User $user;
|
||||
use UserGroupTrait;
|
||||
|
||||
public function budgetEndsWith(string $query, int $limit): Collection
|
||||
{
|
||||
@@ -154,13 +153,6 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void
|
||||
{
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
||||
public function getActiveBudgets(): Collection
|
||||
{
|
||||
return $this->user->budgets()->where('active', true)
|
||||
|
@@ -27,6 +27,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\AutoBudget;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -40,6 +41,8 @@ interface BudgetRepositoryInterface
|
||||
|
||||
public function budgetStartsWith(string $query, int $limit): Collection;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
/**
|
||||
* Returns the amount that is budgeted in a period.
|
||||
*/
|
||||
|
@@ -214,7 +214,6 @@ class OperationsRepository implements OperationsRepositoryInterface
|
||||
Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
||||
// because those expenses only become expenses once they move from the liability to the friend.
|
||||
|
||||
// 2024-12-24 disable the exclusion for now.
|
||||
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
@@ -245,7 +244,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
||||
}
|
||||
if (null !== $currency) {
|
||||
Log::debug(sprintf('Limit to currency %s', $currency->code));
|
||||
$collector->setNormalCurrency($currency);
|
||||
$collector->setCurrency($currency);
|
||||
}
|
||||
$collector->setBudgets($budgets);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
@@ -33,6 +33,7 @@ use FireflyIII\Models\RecurrenceTransactionMeta;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Services\Internal\Destroy\CategoryDestroyService;
|
||||
use FireflyIII\Services\Internal\Update\CategoryUpdateService;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -43,7 +44,7 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
private User $user;
|
||||
use UserGroupTrait;
|
||||
|
||||
public function categoryEndsWith(string $query, int $limit): Collection
|
||||
{
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Category;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -88,6 +89,8 @@ interface CategoryRepositoryInterface
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
|
@@ -36,6 +36,7 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -48,7 +49,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
{
|
||||
use ModifiesPiggyBanks;
|
||||
|
||||
private User $user;
|
||||
use UserGroupTrait;
|
||||
|
||||
public function destroyAll(): void
|
||||
{
|
||||
@@ -370,6 +371,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
public function leftOnAccount(PiggyBank $piggyBank, Account $account, Carbon $date): string
|
||||
{
|
||||
Log::debug(sprintf('leftOnAccount("%s","%s","%s")', $piggyBank->name, $account->name, $date->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('leftOnAccount: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date)['balance'];
|
||||
|
||||
Log::debug(sprintf('Balance is: %s', $balance));
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -137,6 +138,8 @@ interface PiggyBankRepositoryInterface
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
/**
|
||||
* Store new piggy bank.
|
||||
*
|
||||
|
@@ -43,8 +43,7 @@ use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService;
|
||||
use FireflyIII\Services\Internal\Update\GroupUpdateService;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
@@ -53,7 +52,7 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class TransactionGroupRepository implements TransactionGroupRepositoryInterface
|
||||
{
|
||||
private User $user;
|
||||
use UserGroupTrait;
|
||||
|
||||
public function countAttachments(int $journalId): int
|
||||
{
|
||||
@@ -163,13 +162,6 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void
|
||||
{
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the note text for a journal (by ID).
|
||||
*/
|
||||
@@ -408,7 +400,8 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
|
||||
{
|
||||
/** @var TransactionGroupFactory $factory */
|
||||
$factory = app(TransactionGroupFactory::class);
|
||||
$factory->setUser($this->user);
|
||||
$factory->setUser($data['user']);
|
||||
$factory->setUserGroup($data['user_group']);
|
||||
|
||||
try {
|
||||
return $factory->create($data);
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
@@ -99,6 +100,8 @@ interface TransactionGroupRepositoryInterface
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
/**
|
||||
* Create a new transaction group.
|
||||
*
|
||||
|
@@ -659,9 +659,10 @@ trait AccountServiceTrait
|
||||
|
||||
// submit to factory:
|
||||
$submission = [
|
||||
'group_title' => null,
|
||||
'user' => $account->user_id,
|
||||
'transactions' => [
|
||||
'group_title' => null,
|
||||
'user' => $account->user,
|
||||
'user_group' => $account->user->userGroup,
|
||||
'transactions' => [
|
||||
[
|
||||
'type' => 'Opening balance',
|
||||
'date' => $openingBalanceDate,
|
||||
@@ -669,7 +670,8 @@ trait AccountServiceTrait
|
||||
'source_name' => $sourceName,
|
||||
'destination_id' => $destId,
|
||||
'destination_name' => $destName,
|
||||
'user' => $account->user_id,
|
||||
'user' => $account->user,
|
||||
'user_group' => $account->user->userGroup,
|
||||
'currency_id' => $currency->id,
|
||||
'order' => 0,
|
||||
'amount' => $amount,
|
||||
|
@@ -203,8 +203,7 @@ class FrontpageChartGenerator
|
||||
$amount = $limit->native_amount;
|
||||
Log::debug(sprintf('Amount is now "%s".', $amount));
|
||||
}
|
||||
|
||||
|
||||
$amount = null === $amount ? '0' : $amount;
|
||||
$sumSpent = bcmul($entry['sum'], '-1'); // spent
|
||||
$data[0]['entries'][$title] ??= '0';
|
||||
$data[1]['entries'][$title] ??= '0';
|
||||
|
@@ -88,6 +88,11 @@ class ExchangeRateConverter
|
||||
|
||||
return '1';
|
||||
}
|
||||
if ($from->id === $to->id) {
|
||||
Log::debug('ExchangeRateConverter: From and to are the same, return "1".');
|
||||
|
||||
return '1';
|
||||
}
|
||||
$rate = $this->getRate($from, $to, $date);
|
||||
|
||||
return '0' === $rate ? '1' : $rate;
|
||||
@@ -103,7 +108,7 @@ class ExchangeRateConverter
|
||||
|
||||
// find in cache
|
||||
if (null !== $res) {
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return cached rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return cached rate from %s to %s on %s.', $from->code, $to->code, $date->format('Y-m-d')));
|
||||
|
||||
return $res;
|
||||
}
|
||||
@@ -112,7 +117,7 @@ class ExchangeRateConverter
|
||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
Cache::forever($key, $rate);
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from %s to %s on %s.', $from->code, $to->code, $date->format('Y-m-d')));
|
||||
|
||||
return $rate;
|
||||
}
|
||||
@@ -122,7 +127,7 @@ class ExchangeRateConverter
|
||||
if (null !== $rate) {
|
||||
$rate = bcdiv('1', $rate);
|
||||
Cache::forever($key, $rate);
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return inverse DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return inverse DB rate from %s to %s on %s.', $from->code, $to->code, $date->format('Y-m-d')));
|
||||
|
||||
return $rate;
|
||||
}
|
||||
@@ -133,14 +138,14 @@ class ExchangeRateConverter
|
||||
|
||||
// combined (if present), they can be used to calculate the necessary conversion rate.
|
||||
if (0 === bccomp('0', $first) || 0 === bccomp('0', $second)) {
|
||||
Log::warning(sprintf('$first is "%s" and $second is "%s"', $first, $second));
|
||||
Log::warning(sprintf('There is not enough information to convert %s to %s on date %s', $from->code, $to->code, $date->format('Y-m-d')));
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
||||
$second = bcdiv('1', $second);
|
||||
$rate = bcmul($first, $second);
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from %s to %s on %s.', $from->code, $to->code, $date->format('Y-m-d')));
|
||||
Cache::forever($key, $rate);
|
||||
|
||||
return $rate;
|
||||
@@ -154,6 +159,8 @@ class ExchangeRateConverter
|
||||
private function getFromDB(int $from, int $to, string $date): ?string
|
||||
{
|
||||
if ($from === $to) {
|
||||
Log::debug('ExchangeRateConverter: From and to are the same, return "1".');
|
||||
|
||||
return '1';
|
||||
}
|
||||
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
||||
@@ -173,7 +180,7 @@ class ExchangeRateConverter
|
||||
if ('' === $rate) {
|
||||
return null;
|
||||
}
|
||||
Log::debug(sprintf('ExchangeRateConverter: Found !cached! rate from #%d to #%d on %s.', $from, $to, $date));
|
||||
Log::debug(sprintf('ExchangeRateConverter: Found cached rate from #%d to #%d on %s.', $from, $to, $date));
|
||||
|
||||
return $rate;
|
||||
}
|
||||
|
@@ -38,6 +38,8 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
trait ValidatesUserGroupTrait
|
||||
{
|
||||
protected ?UserGroup $userGroup = null;
|
||||
|
||||
/**
|
||||
* An "undocumented" filter
|
||||
*
|
||||
@@ -59,7 +61,7 @@ trait ValidatesUserGroupTrait
|
||||
$user = auth()->user();
|
||||
$groupId = 0;
|
||||
if (!$request->has('user_group_id')) {
|
||||
$groupId = $user->user_group_id;
|
||||
$groupId = (int) $user->user_group_id;
|
||||
Log::debug(sprintf('validateUserGroup: no user group submitted, use default group #%d.', $groupId));
|
||||
}
|
||||
if ($request->has('user_group_id')) {
|
||||
@@ -98,6 +100,7 @@ trait ValidatesUserGroupTrait
|
||||
foreach ($roles as $role) {
|
||||
if ($user->hasRoleInGroupOrOwner($group, $role)) {
|
||||
Log::debug(sprintf('validateUserGroup: User has role "%s" in group #%d, return the group.', $role->value, $groupId));
|
||||
$this->userGroup = $group;
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ trait ChartGeneration
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.');
|
||||
Log::debug('Regenerate chart.account.account-balance-chart from scratch.');
|
||||
$locale = app('steam')->getLocale();
|
||||
|
||||
/** @var GeneratorInterface $generator */
|
||||
@@ -77,8 +77,9 @@ trait ChartGeneration
|
||||
Log::debug(sprintf('Now at account #%d ("%s)', $account->id, $account->name));
|
||||
$currency = $accountRepos->getAccountCurrency($account) ?? $default;
|
||||
$useNative = $convertToNative && $default->id !== $currency->id;
|
||||
$field = $useNative ? 'native_balance' : 'balance';
|
||||
$field = $convertToNative ? 'native_balance' : 'balance';
|
||||
$currency = $useNative ? $default : $currency;
|
||||
Log::debug(sprintf('Will use field %s', $field));
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
@@ -88,6 +89,7 @@ trait ChartGeneration
|
||||
$currentStart = clone $start;
|
||||
$range = Steam::finalAccountBalanceInRange($account, clone $start, clone $end, $this->convertToNative);
|
||||
$previous = array_values($range)[0];
|
||||
Log::debug(sprintf('Start balance for account #%d ("%s) is', $account->id, $account->name), $previous);
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = trim($currentStart->isoFormat((string) trans('config.month_and_day_js', [], $locale)));
|
||||
|
@@ -51,6 +51,7 @@ class TransactionSummarizer
|
||||
|
||||
public function groupByCurrencyId(array $journals, string $method = 'negative'): array
|
||||
{
|
||||
Log::debug(sprintf('Now in groupByCurrencyId(array, "%s")', $method));
|
||||
$array = [];
|
||||
foreach ($journals as $journal) {
|
||||
$field = 'amount';
|
||||
@@ -61,6 +62,10 @@ class TransactionSummarizer
|
||||
$currencySymbol = $journal['currency_symbol'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$currencyDecimalPlaces = $journal['currency_decimal_places'];
|
||||
|
||||
// prepare foreign currency info:
|
||||
$foreignCurrencyId = 0;
|
||||
|
||||
if ($this->convertToNative) {
|
||||
// if convert to native, use the native amount yes or no?
|
||||
$useNative = $this->default->id !== (int) $journal['currency_id'];
|
||||
@@ -85,8 +90,18 @@ class TransactionSummarizer
|
||||
}
|
||||
}
|
||||
if (!$this->convertToNative) {
|
||||
// default to the normal amount, but also
|
||||
Log::debug(sprintf('Journal #%d also includes foreign amount (foreign is %s)', $journal['transaction_journal_id'], $journal['foreign_currency_code']));
|
||||
// use foreign amount?
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$foreignCurrencyName = $journal['foreign_currency_name'];
|
||||
$foreignCurrencySymbol = $journal['foreign_currency_symbol'];
|
||||
$foreignCurrencyCode = $journal['foreign_currency_code'];
|
||||
$foreignCurrencyDecimalPlaces = $journal['foreign_currency_decimal_places'];
|
||||
}
|
||||
}
|
||||
|
||||
// first process normal amount
|
||||
$amount = (string) ($journal[$field] ?? '0');
|
||||
$array[$currencyId] ??= [
|
||||
'sum' => '0',
|
||||
@@ -96,12 +111,34 @@ class TransactionSummarizer
|
||||
'currency_code' => $currencyCode,
|
||||
'currency_decimal_places' => $currencyDecimalPlaces,
|
||||
];
|
||||
|
||||
if ('positive' === $method) {
|
||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->positive($amount));
|
||||
}
|
||||
if ('negative' === $method) {
|
||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($amount));
|
||||
}
|
||||
|
||||
// then process foreign amount, if it exists.
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$amount = (string) ($journal['foreign_amount'] ?? '0');
|
||||
$array[$foreignCurrencyId] ??= [
|
||||
'sum' => '0',
|
||||
'currency_id' => $foreignCurrencyId,
|
||||
'currency_name' => $foreignCurrencyName,
|
||||
'currency_symbol' => $foreignCurrencySymbol,
|
||||
'currency_code' => $foreignCurrencyCode,
|
||||
'currency_decimal_places' => $foreignCurrencyDecimalPlaces,
|
||||
];
|
||||
|
||||
if ('positive' === $method) {
|
||||
$array[$foreignCurrencyId]['sum'] = bcadd($array[$foreignCurrencyId]['sum'], app('steam')->positive($amount));
|
||||
}
|
||||
if ('negative' === $method) {
|
||||
$array[$foreignCurrencyId]['sum'] = bcadd($array[$foreignCurrencyId]['sum'], app('steam')->negative($amount));
|
||||
}
|
||||
}
|
||||
|
||||
// $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->{$method}($amount));
|
||||
// Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount));
|
||||
}
|
||||
|
@@ -24,30 +24,48 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Repositories\UserGroup;
|
||||
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\GroupMembership;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Trait UserGroupTrait
|
||||
*/
|
||||
trait UserGroupTrait
|
||||
{
|
||||
protected User $user;
|
||||
protected UserGroup $userGroup;
|
||||
protected ?User $user = null;
|
||||
protected ?UserGroup $userGroup = null;
|
||||
|
||||
public function getUserGroup(): UserGroup
|
||||
{
|
||||
return $this->userGroup;
|
||||
}
|
||||
|
||||
public function checkUserGroupAccess(UserRoleEnum $role): bool
|
||||
{
|
||||
$result = $this->user->hasRoleInGroupOrOwner($this->userGroup, $role);
|
||||
if ($result) {
|
||||
Log::debug(sprintf('User #%d has role %s in group #%d or is owner/full.', $this->user->id, $role->value, $this->userGroup->id));
|
||||
|
||||
return true;
|
||||
}
|
||||
Log::warning(sprintf('User #%d DOES NOT have role %s in group #%d.', $this->user->id, $role->value, $this->userGroup->id));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO This method does not check if the user has access to this particular user group.
|
||||
*/
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
if (null === $this->user) {
|
||||
Log::warning(sprintf('User is not set in repository %s', static::class));
|
||||
}
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
@@ -62,7 +80,11 @@ trait UserGroupTrait
|
||||
throw new FireflyException(sprintf('User #%d has no user group.', $user->id));
|
||||
}
|
||||
$this->userGroup = $user->userGroup;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new FireflyException(sprintf('Object is of class %s, not User.', get_class($user)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +92,7 @@ trait UserGroupTrait
|
||||
*/
|
||||
public function setUserGroupById(int $userGroupId): void
|
||||
{
|
||||
$memberships = GroupMembership::where('user_id', $this->user->id)
|
||||
$memberships = GroupMembership::where('user_id', $this->user->id)
|
||||
->where('user_group_id', $userGroupId)
|
||||
->count()
|
||||
;
|
||||
@@ -79,10 +101,10 @@ trait UserGroupTrait
|
||||
}
|
||||
|
||||
/** @var null|UserGroup $userGroup */
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
if (null === $userGroup) {
|
||||
throw new FireflyException(sprintf('Cannot find administration for user #%d', $this->user->id));
|
||||
}
|
||||
$this->userGroup = $userGroup;
|
||||
$this->setUserGroup($userGroup);
|
||||
}
|
||||
}
|
||||
|
@@ -63,13 +63,10 @@ abstract class Node
|
||||
|
||||
return false;
|
||||
}
|
||||
if ($compare instanceof NodeGroup) {
|
||||
if ($compare instanceof NodeGroup && $this instanceof NodeGroup) {
|
||||
if (count($compare->getNodes()) !== count($this->getNodes())) {
|
||||
Log::debug(sprintf('Return false because node count is different. Original is %d, compare is %d', count($this->getNodes()), count($compare->getNodes())));
|
||||
|
||||
// var_dump($this);
|
||||
// var_dump($compare);
|
||||
// exit;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -80,10 +77,6 @@ abstract class Node
|
||||
foreach ($this->getNodes() as $index => $node) {
|
||||
if (false === $node->equals($compare->getNodes()[$index])) {
|
||||
Log::debug('Return false because nodes are different!');
|
||||
var_dump($this);
|
||||
var_dump($compare);
|
||||
|
||||
exit;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -152,12 +152,12 @@ class QueryParser implements QueryParserInterface
|
||||
|
||||
case ':':
|
||||
$skipNext = false;
|
||||
if ('' === $tokenUnderConstruction) { // @phpstan-ignore-line
|
||||
if ('' === $tokenUnderConstruction) {
|
||||
// In any other location, it's just a normal character
|
||||
$tokenUnderConstruction .= $char;
|
||||
$skipNext = true;
|
||||
}
|
||||
if ('' !== $tokenUnderConstruction && !$skipNext) {
|
||||
if ('' !== $tokenUnderConstruction && !$skipNext) { // @phpstan-ignore-line
|
||||
Log::debug(sprintf('Turns out that "%s" is a field name. Reset the token.', $tokenUnderConstruction));
|
||||
// If we meet a colon with a left-hand side string, we know we're in a field and are about to set up the value
|
||||
$fieldName = $tokenUnderConstruction;
|
||||
|
@@ -59,8 +59,8 @@ class Steam
|
||||
public function finalAccountBalanceInRange(Account $account, Carbon $start, Carbon $end, bool $convertToNative): array
|
||||
{
|
||||
// expand period.
|
||||
$start->subDay()->endOfDay(); // go to END of day to get the balance at the END of the day.
|
||||
$end->addDay()->startOfDay(); // go to START of day to get the balance at the END of the previous day (see ahead).
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
Log::debug(sprintf('finalAccountBalanceInRange(#%d, %s, %s)', $account->id, $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
|
||||
// set up cache
|
||||
@@ -68,6 +68,7 @@ class Steam
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty('final-balance-in-range');
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($convertToNative);
|
||||
$cache->addProperty($end);
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
@@ -75,13 +76,22 @@ class Steam
|
||||
|
||||
$balances = [];
|
||||
$formatted = $start->format('Y-m-d');
|
||||
$startBalance = $this->finalAccountBalance($account, $start);
|
||||
/*
|
||||
* To make sure the start balance is correct, we need to get the balance at the exact end of the previous day.
|
||||
* Since we just did "startOfDay" we can do subDay()->endOfDay() to get the correct moment.
|
||||
* THAT will be the start balance.
|
||||
*/
|
||||
$request = clone $start;
|
||||
$request->subDay()->endOfDay();
|
||||
Log::debug(sprintf('finalAccountBalanceInRange: Call finalAccountBalance with date/time "%s"', $request->toIso8601String()));
|
||||
$startBalance = $this->finalAccountBalance($account, $request);
|
||||
$nativeCurrency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup);
|
||||
$accountCurrency = $this->getAccountCurrency($account);
|
||||
$hasCurrency = null !== $accountCurrency;
|
||||
$currency = $accountCurrency ?? $nativeCurrency;
|
||||
Log::debug(sprintf('Currency is %s', $currency->code));
|
||||
|
||||
|
||||
// set start balances:
|
||||
$startBalance[$currency->code] ??= '0';
|
||||
if ($hasCurrency) {
|
||||
@@ -100,10 +110,11 @@ class Steam
|
||||
Log::debug('Final start balance: ', $startBalance);
|
||||
|
||||
// sums up the balance changes per day.
|
||||
Log::debug(sprintf('Date >= %s and <= %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
$set = $account->transactions()
|
||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transaction_journals.date', '>', $start->format('Y-m-d H:i:s'))
|
||||
->where('transaction_journals.date', '<', $end->format('Y-m-d H:i:s'))
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
||||
->groupBy('transaction_journals.date')
|
||||
->groupBy('transactions.transaction_currency_id')
|
||||
->orderBy('transaction_journals.date', 'ASC')
|
||||
@@ -137,6 +148,8 @@ class Steam
|
||||
$entryCurrency = $currencies[$entry->transaction_currency_id];
|
||||
|
||||
Log::debug(sprintf('Processing transaction(s) on moment %s', $carbon->format('Y-m-d H:i:s')));
|
||||
|
||||
// add amount to current balance in currency code.
|
||||
$currentBalance[$entryCurrency->code] ??= '0';
|
||||
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, $currentBalance[$entryCurrency->code]);
|
||||
|
||||
@@ -145,9 +158,14 @@ class Steam
|
||||
$currentBalance['balance'] = bcadd($currentBalance['balance'], $sumOfDay);
|
||||
}
|
||||
// if convert to native add the converted amount to "native_balance".
|
||||
// if there is a request to convert, convert to "native_balance" and use "balance" for whichever amount is in the native currency.
|
||||
if ($convertToNative) {
|
||||
$nativeSumOfDay = $converter->convert($entryCurrency, $nativeCurrency, $carbon, $sumOfDay);
|
||||
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeSumOfDay);
|
||||
if ($currency->id === $entryCurrency->id) {
|
||||
$currentBalance['balance'] = bcadd($currentBalance['balance'], $sumOfDay);
|
||||
}
|
||||
|
||||
}
|
||||
// just set it.
|
||||
$balances[$carbonKey] = $currentBalance;
|
||||
@@ -161,6 +179,7 @@ class Steam
|
||||
|
||||
public function finalAccountsBalance(Collection $accounts, Carbon $date): array
|
||||
{
|
||||
Log::debug(sprintf('finalAccountsBalance: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balances = [];
|
||||
foreach ($accounts as $account) {
|
||||
$balances[$account->id] = $this->finalAccountBalance($account, $date);
|
||||
@@ -257,6 +276,8 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns smaller than or equal to, so be careful with END OF DAY.
|
||||
*
|
||||
* Returns the balance of an account at exact moment given. Array with at least one value.
|
||||
* Always returns:
|
||||
* "balance": balance in the account's currency OR user's native currency if the account has no currency
|
||||
@@ -275,7 +296,7 @@ class Steam
|
||||
$cache->addProperty($date);
|
||||
if ($cache->has()) {
|
||||
// Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
// return $cache->get();
|
||||
return $cache->get();
|
||||
}
|
||||
Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
|
||||
@@ -354,8 +375,8 @@ class Steam
|
||||
$defaultCurrency = app('amount')->getNativeCurrency();
|
||||
if ($convertToNative) {
|
||||
if ($defaultCurrency->id === $currency?->id) {
|
||||
Log::debug(sprintf('Unset "native_balance" and [%s] for account #%d', $defaultCurrency->code, $account->id));
|
||||
unset($set['native_balance'], $set[$defaultCurrency->code]);
|
||||
Log::debug(sprintf('Unset [%s] for account #%d (no longer unset "native_balance")', $defaultCurrency->code, $account->id));
|
||||
unset($set[$defaultCurrency->code]);
|
||||
}
|
||||
// todo rethink this logic.
|
||||
if (null !== $currency && $defaultCurrency->id !== $currency->id) {
|
||||
|
@@ -114,7 +114,7 @@ class AmountFormat extends AbstractExtension
|
||||
static function (string $amount, string $code, ?bool $coloured = null): string {
|
||||
$coloured ??= true;
|
||||
|
||||
/** @var TransactionCurrency $currency */
|
||||
/** @var null|TransactionCurrency $currency */
|
||||
$currency = TransactionCurrency::whereCode($code)->first();
|
||||
if (null === $currency) {
|
||||
Log::error(sprintf('Could not find currency with code "%s". Fallback to native currency.', $code));
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\CommonMark\GithubFlavoredMarkdownConverter;
|
||||
use Route;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
@@ -67,6 +68,7 @@ class General extends AbstractExtension
|
||||
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
Log::debug(sprintf('twig balance: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$info = Steam::finalAccountBalance($account, $date);
|
||||
$currency = Steam::getAccountCurrency($account);
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
/**
|
||||
@@ -106,6 +107,7 @@ class AccountTransformer extends AbstractTransformer
|
||||
$order = null;
|
||||
}
|
||||
// balance, native balance, virtual balance, native virtual balance?
|
||||
Log::debug(sprintf('transform: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$finalBalance = Steam::finalAccountBalance($account, $date);
|
||||
if ($convertToNative) {
|
||||
$finalBalance['balance'] = $finalBalance[$currencyCode] ?? '0';
|
||||
|
@@ -54,7 +54,7 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
||||
public function transform(PiggyBankEvent $event): array
|
||||
{
|
||||
// get account linked to piggy bank
|
||||
$account = $event->piggyBank->account;
|
||||
$account = $event->piggyBank->accounts()->first();
|
||||
|
||||
// set up repositories.
|
||||
$this->repository->setUser($account->user);
|
||||
|
@@ -183,6 +183,8 @@ class AccountTransformer extends AbstractTransformer
|
||||
$bEnd = [];
|
||||
|
||||
try {
|
||||
Log::debug(sprintf('v2 transformer: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('v2 transformer: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
||||
$bStart = app('steam')->finalAccountsBalance($accounts, $start);
|
||||
$bEnd = app('steam')->finalAccountsBalance($accounts, $end);
|
||||
} catch (FireflyException $e) {
|
||||
|
13
changelog.md
13
changelog.md
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 6.2.6 - 2025-02-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- [Issue 9797](https://github.com/firefly-iii/firefly-iii/issues/9797) (All account charts show a horizontal line) reported by @avee87
|
||||
- [Issue 9806](https://github.com/firefly-iii/firefly-iii/issues/9806) (Exchange Rates table fails to load when language is not English) reported by @polter-rnd
|
||||
- [Issue 9807](https://github.com/firefly-iii/firefly-iii/issues/9807) (Start Date of Reconciliation Period Incorrectly Excludes Transactions for That Day) reported by @pwschattenberg
|
||||
- [Issue 9808](https://github.com/firefly-iii/firefly-iii/issues/9808) (Default financial report line graph shows a different balance than the text) reported by @mtaygur
|
||||
- [Issue 9810](https://github.com/firefly-iii/firefly-iii/issues/9810) (Foreign amount not taken into consideration for budget spent/leaving) reported by @M4xS0ch
|
||||
- [Issue 9821](https://github.com/firefly-iii/firefly-iii/issues/9821) (piggy events api 500 error) reported by @4e868df3
|
||||
- [Issue 9826](https://github.com/firefly-iii/firefly-iii/issues/9826) (Wrong account balance) reported by @fabienfitoussi
|
||||
|
||||
## 6.2.5 - 2025-02-08
|
||||
|
||||
### Fixed
|
||||
@@ -13,6 +25,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- [Discussion 9780](https://github.com/orgs/firefly-iii/discussions/9780) (Rules or webhook precedence?) started by @joeshmoe57
|
||||
- [Issue 9781](https://github.com/firefly-iii/firefly-iii/issues/9781) (Search key `has_any_external_url:false` returns all transactions) reported by @joeshmoe57
|
||||
- [Issue 9783](https://github.com/firefly-iii/firefly-iii/issues/9783) (Subscriptions: Make "Not expected this period" and "expected x days from now" different colors) reported by @SteffoSpieler
|
||||
- [Issue 9784](https://github.com/firefly-iii/firefly-iii/issues/9784) (Transfers with external currency not considered for account balance?) reported by @pvieira84
|
||||
- [Issue 9786](https://github.com/firefly-iii/firefly-iii/issues/9786) (The error 500 information page has non-clickable links to github and the debug page) reported by @tjmv
|
||||
- [Issue 9787](https://github.com/firefly-iii/firefly-iii/issues/9787) (Twig general template error formatting TransactionCurrency on main page) reported by @tjmv
|
||||
- [Issue 9789](https://github.com/firefly-iii/firefly-iii/issues/9789) (Can't open expense and revenue accounts view) reported by @puffer-duck
|
||||
|
76
composer.lock
generated
76
composer.lock
generated
@@ -1874,16 +1874,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v11.41.3",
|
||||
"version": "v11.42.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "3ef433d5865f30a19b6b1be247586068399b59cc"
|
||||
"reference": "006375ba67e830e87daa7b52ab65163ba3508d26"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/3ef433d5865f30a19b6b1be247586068399b59cc",
|
||||
"reference": "3ef433d5865f30a19b6b1be247586068399b59cc",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/006375ba67e830e87daa7b52ab65163ba3508d26",
|
||||
"reference": "006375ba67e830e87daa7b52ab65163ba3508d26",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1991,11 +1991,11 @@
|
||||
"league/flysystem-read-only": "^3.25.1",
|
||||
"league/flysystem-sftp-v3": "^3.25.1",
|
||||
"mockery/mockery": "^1.6.10",
|
||||
"orchestra/testbench-core": "^9.6",
|
||||
"orchestra/testbench-core": "^9.9.4",
|
||||
"pda/pheanstalk": "^5.0.6",
|
||||
"php-http/discovery": "^1.15",
|
||||
"phpstan/phpstan": "^1.11.5",
|
||||
"phpunit/phpunit": "^10.5.35|^11.3.6",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1",
|
||||
"predis/predis": "^2.3",
|
||||
"resend/resend-php": "^0.10.0",
|
||||
"symfony/cache": "^7.0.3",
|
||||
@@ -2027,7 +2027,7 @@
|
||||
"mockery/mockery": "Required to use mocking (^1.6).",
|
||||
"pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).",
|
||||
"php-http/discovery": "Required to use PSR-7 bridging features (^1.15).",
|
||||
"phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).",
|
||||
"phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).",
|
||||
"predis/predis": "Required to use the predis connector (^2.3).",
|
||||
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).",
|
||||
@@ -2085,7 +2085,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-01-30T13:25:22+00:00"
|
||||
"time": "2025-02-11T17:17:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
@@ -2165,16 +2165,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
"version": "v0.3.4",
|
||||
"version": "v0.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/prompts.git",
|
||||
"reference": "abeaa2ba4294247d5409490d1ca1bc6248087011"
|
||||
"reference": "57b8f7efe40333cdb925700891c7d7465325d3b1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/prompts/zipball/abeaa2ba4294247d5409490d1ca1bc6248087011",
|
||||
"reference": "abeaa2ba4294247d5409490d1ca1bc6248087011",
|
||||
"url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1",
|
||||
"reference": "57b8f7efe40333cdb925700891c7d7465325d3b1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2218,9 +2218,9 @@
|
||||
"description": "Add beautiful and user-friendly forms to your command-line applications.",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/prompts/issues",
|
||||
"source": "https://github.com/laravel/prompts/tree/v0.3.4"
|
||||
"source": "https://github.com/laravel/prompts/tree/v0.3.5"
|
||||
},
|
||||
"time": "2025-01-24T15:41:01+00:00"
|
||||
"time": "2025-02-11T13:34:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sanctum",
|
||||
@@ -2288,16 +2288,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v2.0.2",
|
||||
"version": "v2.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/serializable-closure.git",
|
||||
"reference": "2e1a362527783bcab6c316aad51bf36c5513ae44"
|
||||
"reference": "f379c13663245f7aa4512a7869f62eb14095f23f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/2e1a362527783bcab6c316aad51bf36c5513ae44",
|
||||
"reference": "2e1a362527783bcab6c316aad51bf36c5513ae44",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f379c13663245f7aa4512a7869f62eb14095f23f",
|
||||
"reference": "f379c13663245f7aa4512a7869f62eb14095f23f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2345,7 +2345,7 @@
|
||||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"time": "2025-01-24T15:42:37+00:00"
|
||||
"time": "2025-02-11T15:03:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/slack-notification-channel",
|
||||
@@ -3703,16 +3703,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "3.8.4",
|
||||
"version": "3.8.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/CarbonPHP/carbon.git",
|
||||
"reference": "129700ed449b1f02d70272d2ac802357c8c30c58"
|
||||
"reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58",
|
||||
"reference": "129700ed449b1f02d70272d2ac802357c8c30c58",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/b1a53a27898639579a67de42e8ced5d5386aa9a4",
|
||||
"reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3788,8 +3788,8 @@
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://carbon.nesbot.com/docs",
|
||||
"issues": "https://github.com/briannesbitt/Carbon/issues",
|
||||
"source": "https://github.com/briannesbitt/Carbon"
|
||||
"issues": "https://github.com/CarbonPHP/carbon/issues",
|
||||
"source": "https://github.com/CarbonPHP/carbon"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3805,7 +3805,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-12-27T09:25:35+00:00"
|
||||
"time": "2025-02-11T16:28:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
@@ -10973,16 +10973,16 @@
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.12.1",
|
||||
"version": "1.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
|
||||
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
|
||||
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
|
||||
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11021,7 +11021,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11029,7 +11029,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-08T17:47:46+00:00"
|
||||
"time": "2025-02-12T12:17:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
@@ -11344,16 +11344,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.3",
|
||||
"version": "2.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "64ae44e48214f3deebdaeebf2694297a10a2bea9"
|
||||
"reference": "8f99e18eb775dbaf6460c95fa0b65312da9c746a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/64ae44e48214f3deebdaeebf2694297a10a2bea9",
|
||||
"reference": "64ae44e48214f3deebdaeebf2694297a10a2bea9",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/8f99e18eb775dbaf6460c95fa0b65312da9c746a",
|
||||
"reference": "8f99e18eb775dbaf6460c95fa0b65312da9c746a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11398,7 +11398,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-07T15:05:24+00:00"
|
||||
"time": "2025-02-10T08:25:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
|
@@ -81,7 +81,7 @@ return [
|
||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2025-02-08',
|
||||
'version' => 'develop/2025-02-12',
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 25,
|
||||
|
||||
|
@@ -159,7 +159,7 @@ return new class () extends Migration {
|
||||
Schema::dropIfExists('account_piggy_bank');
|
||||
}
|
||||
|
||||
protected static function hasForeign(string $table, string $column)
|
||||
protected static function hasForeign(string $table, string $column): bool
|
||||
{
|
||||
|
||||
$foreignKeysDefinitions = Schema::getForeignKeys($table);
|
||||
|
172
package-lock.json
generated
172
package-lock.json
generated
@@ -79,9 +79,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.26.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz",
|
||||
"integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
|
||||
"integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -89,22 +89,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz",
|
||||
"integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz",
|
||||
"integrity": "sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/generator": "^7.26.5",
|
||||
"@babel/generator": "^7.26.8",
|
||||
"@babel/helper-compilation-targets": "^7.26.5",
|
||||
"@babel/helper-module-transforms": "^7.26.0",
|
||||
"@babel/helpers": "^7.26.7",
|
||||
"@babel/parser": "^7.26.7",
|
||||
"@babel/template": "^7.25.9",
|
||||
"@babel/traverse": "^7.26.7",
|
||||
"@babel/types": "^7.26.7",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/template": "^7.26.8",
|
||||
"@babel/traverse": "^7.26.8",
|
||||
"@babel/types": "^7.26.8",
|
||||
"@types/gensync": "^1.0.0",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
@@ -130,14 +131,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.26.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz",
|
||||
"integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.8.tgz",
|
||||
"integrity": "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.26.5",
|
||||
"@babel/types": "^7.26.5",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/types": "^7.26.8",
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jsesc": "^3.0.2"
|
||||
@@ -442,13 +443,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz",
|
||||
"integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz",
|
||||
"integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.26.7"
|
||||
"@babel/types": "^7.26.8"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -667,15 +668,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-async-generator-functions": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz",
|
||||
"integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz",
|
||||
"integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.25.9",
|
||||
"@babel/helper-plugin-utils": "^7.26.5",
|
||||
"@babel/helper-remap-async-to-generator": "^7.25.9",
|
||||
"@babel/traverse": "^7.25.9"
|
||||
"@babel/traverse": "^7.26.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -1340,14 +1341,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-runtime": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz",
|
||||
"integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.8.tgz",
|
||||
"integrity": "sha512-H0jlQxFMI0Q8SyGPsj9pO3ygVQRxPkIGytsL3m1Zqca8KrCPpMlvh+e2dxknqdfS8LFwBw+PpiYPD9qy/FPQpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.25.9",
|
||||
"@babel/helper-plugin-utils": "^7.25.9",
|
||||
"@babel/helper-plugin-utils": "^7.26.5",
|
||||
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
||||
"babel-plugin-polyfill-corejs3": "^0.10.6",
|
||||
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
||||
@@ -1420,13 +1421,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-template-literals": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz",
|
||||
"integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz",
|
||||
"integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.25.9"
|
||||
"@babel/helper-plugin-utils": "^7.26.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -1519,13 +1520,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.7.tgz",
|
||||
"integrity": "sha512-Ycg2tnXwixaXOVb29rana8HNPgLVBof8qqtNQ9LE22IoyZboQbGSxI6ZySMdW3K5nAe6gu35IaJefUJflhUFTQ==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.8.tgz",
|
||||
"integrity": "sha512-um7Sy+2THd697S4zJEfv/U5MHGJzkN2xhtsR3T/SWRbVSic62nbISh51VVfU9JiO/L/Z97QczHTaFVkOU8IzNg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.26.5",
|
||||
"@babel/compat-data": "^7.26.8",
|
||||
"@babel/helper-compilation-targets": "^7.26.5",
|
||||
"@babel/helper-plugin-utils": "^7.26.5",
|
||||
"@babel/helper-validator-option": "^7.25.9",
|
||||
@@ -1539,7 +1540,7 @@
|
||||
"@babel/plugin-syntax-import-attributes": "^7.26.0",
|
||||
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.25.9",
|
||||
"@babel/plugin-transform-async-generator-functions": "^7.25.9",
|
||||
"@babel/plugin-transform-async-generator-functions": "^7.26.8",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.25.9",
|
||||
"@babel/plugin-transform-block-scoped-functions": "^7.26.5",
|
||||
"@babel/plugin-transform-block-scoping": "^7.25.9",
|
||||
@@ -1582,7 +1583,7 @@
|
||||
"@babel/plugin-transform-shorthand-properties": "^7.25.9",
|
||||
"@babel/plugin-transform-spread": "^7.25.9",
|
||||
"@babel/plugin-transform-sticky-regex": "^7.25.9",
|
||||
"@babel/plugin-transform-template-literals": "^7.25.9",
|
||||
"@babel/plugin-transform-template-literals": "^7.26.8",
|
||||
"@babel/plugin-transform-typeof-symbol": "^7.26.7",
|
||||
"@babel/plugin-transform-unicode-escapes": "^7.25.9",
|
||||
"@babel/plugin-transform-unicode-property-regex": "^7.25.9",
|
||||
@@ -1590,9 +1591,9 @@
|
||||
"@babel/plugin-transform-unicode-sets-regex": "^7.25.9",
|
||||
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
||||
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
||||
"babel-plugin-polyfill-corejs3": "^0.10.6",
|
||||
"babel-plugin-polyfill-corejs3": "^0.11.0",
|
||||
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
||||
"core-js-compat": "^3.38.1",
|
||||
"core-js-compat": "^3.40.0",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1602,6 +1603,20 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz",
|
||||
"integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.3",
|
||||
"core-js-compat": "^3.40.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
@@ -1640,32 +1655,32 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
|
||||
"integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.8.tgz",
|
||||
"integrity": "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.25.9",
|
||||
"@babel/parser": "^7.25.9",
|
||||
"@babel/types": "^7.25.9"
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/types": "^7.26.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz",
|
||||
"integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.8.tgz",
|
||||
"integrity": "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/generator": "^7.26.5",
|
||||
"@babel/parser": "^7.26.7",
|
||||
"@babel/template": "^7.25.9",
|
||||
"@babel/types": "^7.26.7",
|
||||
"@babel/generator": "^7.26.8",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/template": "^7.26.8",
|
||||
"@babel/types": "^7.26.8",
|
||||
"debug": "^4.3.1",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
@@ -1674,9 +1689,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz",
|
||||
"integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz",
|
||||
"integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3032,6 +3047,13 @@
|
||||
"@types/send": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/gensync": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz",
|
||||
"integrity": "sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
|
||||
@@ -4158,9 +4180,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bootstrap5-autocomplete": {
|
||||
"version": "1.1.35",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap5-autocomplete/-/bootstrap5-autocomplete-1.1.35.tgz",
|
||||
"integrity": "sha512-vZAOef3lGrpGGnnIKTJlqiqv6wsx0Wr31/mc010mJmHF1eXJd28jzfGn7ol8eOI/7FiDcm3wd/1VTWku40vLbQ==",
|
||||
"version": "1.1.36",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap5-autocomplete/-/bootstrap5-autocomplete-1.1.36.tgz",
|
||||
"integrity": "sha512-fZpklymmrwAls3n6YDMua2msnBB4pwmJgJgqMayHLfnvvc2dhKWwp/qu0pGJI99S8TwC+ZDjYtEsfl+4/FEZhg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bootstrap5-tags": {
|
||||
@@ -4448,9 +4470,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001698",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001698.tgz",
|
||||
"integrity": "sha512-xJ3km2oiG/MbNU8G6zIq6XRZ6HtAOVXsbOrP/blGazi52kc5Yy7b6sDA5O+FbROzRrV7BSTllLHuNvmawYUJjw==",
|
||||
"version": "1.0.30001699",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz",
|
||||
"integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -4735,9 +4757,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/compression": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz",
|
||||
"integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==",
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz",
|
||||
"integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5663,9 +5685,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.96",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.96.tgz",
|
||||
"integrity": "sha512-8AJUW6dh75Fm/ny8+kZKJzI1pgoE8bKLZlzDU2W1ENd+DXKJrx7I7l9hb8UWR4ojlnb5OlixMt00QWiYJoVw1w==",
|
||||
"version": "1.5.97",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.97.tgz",
|
||||
"integrity": "sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
@@ -8854,9 +8876,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
|
||||
"integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
|
||||
"version": "8.5.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz",
|
||||
"integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -10871,9 +10893,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.38.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.38.1.tgz",
|
||||
"integrity": "sha512-GWANVlPM/ZfYzuPHjq0nxT+EbOEDDN3Jwhwdg1D8TU8oSkktp8w64Uq4auuGLxFSoNTRDncTq2hQHX1Ld9KHkA==",
|
||||
"version": "5.38.2",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.38.2.tgz",
|
||||
"integrity": "sha512-w8CXxxbFA5zfNsR/i8HZq5bvn18AK0O9jj7hyo1YqkovLxEFa0uP0LCVGZRqiRaKRFxXhELBp8SteeAjEnfeJg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
|
@@ -381,7 +381,7 @@ export default {
|
||||
this.totalPages = parseInt(response.data.meta.pagination.total_pages);
|
||||
this.loading = false;
|
||||
this.rates = Object.values(this.tempRates);
|
||||
console.log('Do not download more pages. Now on page ' + this.page + ' of ' + this.totalPages);
|
||||
// console.log('Do not download more pages. Now on page ' + this.page + ' of ' + this.totalPages);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@@ -36,7 +36,6 @@
|
||||
class="form-control"
|
||||
data-role="input"
|
||||
type="text"
|
||||
v-on:keypress="handleEnter"
|
||||
v-on:submit.prevent>
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
@@ -217,7 +216,7 @@ export default {
|
||||
}
|
||||
},
|
||||
selectedItem: function (e) {
|
||||
// console.log('In SelectedItem()');
|
||||
console.log('In SelectedItem()');
|
||||
if (typeof this.name === 'undefined') {
|
||||
// console.log('Is undefined');
|
||||
return;
|
||||
@@ -239,12 +238,6 @@ export default {
|
||||
this.name = '';
|
||||
// some event?
|
||||
this.$emit('clear:value')
|
||||
},
|
||||
handleEnter: function (e) {
|
||||
// TODO feels sloppy. Can be removed.
|
||||
if (e.keyCode === 13) {
|
||||
//e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -922,6 +922,12 @@ export default {
|
||||
allowed_types: this.transactions[index].source_account.allowed_types,
|
||||
default_allowed_types: ['Asset account', 'Revenue account', 'Loan', 'Debt', 'Mortgage']
|
||||
};
|
||||
if(model.hasOwnProperty('account_currency_id') && null !== model.account_currency_id) {
|
||||
this.transactions[index].source_account.currency_id = model.account_currency_id;
|
||||
this.transactions[index].source_account.currency_name = model.account_currency_name;
|
||||
this.transactions[index].source_account.currency_code = model.account_currency_code;
|
||||
this.transactions[index].source_account.currency_decimal_places = model.account_currency_decimal_places;
|
||||
}
|
||||
|
||||
// force types on destination selector.
|
||||
this.transactions[index].destination_account.allowed_types = window.allowedOpposingTypes.source[model.type];
|
||||
@@ -946,6 +952,12 @@ export default {
|
||||
allowed_types: this.transactions[index].destination_account.allowed_types,
|
||||
default_allowed_types: ['Asset account', 'Expense account', 'Loan', 'Debt', 'Mortgage']
|
||||
};
|
||||
if(model.hasOwnProperty('account_currency_id') && null !== model.account_currency_id) {
|
||||
this.transactions[index].destination_account.currency_id = model.account_currency_id;
|
||||
this.transactions[index].destination_account.currency_name = model.account_currency_name;
|
||||
this.transactions[index].destination_account.currency_code = model.account_currency_code;
|
||||
this.transactions[index].destination_account.currency_decimal_places = model.account_currency_decimal_places;
|
||||
}
|
||||
|
||||
// force types on destination selector.
|
||||
this.transactions[index].source_account.allowed_types = window.allowedOpposingTypes.destination[model.type];
|
||||
|
@@ -155,8 +155,8 @@
|
||||
v-bind:title="$t('form.foreign_amount')"
|
||||
></foreign-amount>
|
||||
<reconciled v-show="isReconciled"
|
||||
v-model="transaction.reconciled"
|
||||
:error="transaction.errors.reconciled"
|
||||
v-model="transaction.reconciled"
|
||||
:error="transaction.errors.reconciled"
|
||||
></reconciled>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
@@ -322,6 +322,12 @@ export default {
|
||||
currency_decimal_places: model.currency_decimal_places,
|
||||
allowed_types: this.transactions[index].source_account.allowed_types
|
||||
};
|
||||
if(model.hasOwnProperty('account_currency_id') && null !== model.account_currency_id) {
|
||||
this.transactions[index].source_account.currency_id = model.account_currency_id;
|
||||
this.transactions[index].source_account.currency_name = model.account_currency_name;
|
||||
this.transactions[index].source_account.currency_code = model.account_currency_code;
|
||||
this.transactions[index].source_account.currency_decimal_places = model.account_currency_decimal_places;
|
||||
}
|
||||
},
|
||||
selectedDestinationAccount(index, model) {
|
||||
if (typeof model === 'string') {
|
||||
@@ -341,6 +347,12 @@ export default {
|
||||
currency_decimal_places: model.currency_decimal_places,
|
||||
allowed_types: this.transactions[index].destination_account.allowed_types
|
||||
};
|
||||
if(model.hasOwnProperty('account_currency_id') && null !== model.account_currency_id) {
|
||||
this.transactions[index].destination_account.currency_id = model.account_currency_id;
|
||||
this.transactions[index].destination_account.currency_name = model.account_currency_name;
|
||||
this.transactions[index].destination_account.currency_code = model.account_currency_code;
|
||||
this.transactions[index].destination_account.currency_decimal_places = model.account_currency_decimal_places;
|
||||
}
|
||||
},
|
||||
clearSource(index) {
|
||||
// reset source account:
|
||||
@@ -437,7 +449,7 @@ export default {
|
||||
//console.log('EditTransaction: processIncomingGroupRow()');
|
||||
this.setTransactionType(transaction.type);
|
||||
|
||||
if(true === transaction.reconciled) {
|
||||
if (true === transaction.reconciled) {
|
||||
this.isReconciled = true;
|
||||
}
|
||||
|
||||
@@ -528,7 +540,16 @@ export default {
|
||||
allowed_types: window.expectedSourceTypes.destination[this.ucFirst(transaction.type)]
|
||||
}
|
||||
};
|
||||
if(null === transaction.foreign_amount) {
|
||||
// if transaction type is transfer, the destination currency_id etc. MUST match the actual account currency info.
|
||||
if ('transfer' === transaction.type && null !== transaction.foreign_currency_code) {
|
||||
result.destination_account.currency_id = transaction.foreign_currency_id;
|
||||
result.destination_account.currency_name = transaction.foreign_currency_name;
|
||||
result.destination_account.currency_code = transaction.foreign_currency_code;
|
||||
result.destination_account.currency_decimal_places = transaction.foreign_currency_decimal_places;
|
||||
}
|
||||
|
||||
|
||||
if (null === transaction.foreign_amount) {
|
||||
result.foreign_amount.amount = '';
|
||||
}
|
||||
this.transactions.push(result);
|
||||
@@ -736,7 +757,7 @@ export default {
|
||||
if (parseInt(row.piggy_bank) > 0) {
|
||||
currentArray.piggy_bank_id = parseInt(row.piggy_bank);
|
||||
}
|
||||
if(this.isReconciled && !this.storeAsNew && true === row.reconciled) {
|
||||
if (this.isReconciled && !this.storeAsNew && true === row.reconciled) {
|
||||
// drop content from array:
|
||||
delete currentArray.source_id;
|
||||
delete currentArray.source_name;
|
||||
@@ -748,7 +769,7 @@ export default {
|
||||
delete currentArray.currency_id;
|
||||
currentArray.reconciled = true;
|
||||
}
|
||||
if(true === row.isReconciled) {
|
||||
if (true === row.isReconciled) {
|
||||
this.isReconciled = false;
|
||||
}
|
||||
|
||||
@@ -801,10 +822,16 @@ export default {
|
||||
this.setDefaultErrors();
|
||||
// do message if update or new:
|
||||
if (this.storeAsNew) {
|
||||
this.success_message = this.$t('firefly.transaction_new_stored_link', {ID: groupId, title: this.escapeHtml(title)});
|
||||
this.success_message = this.$t('firefly.transaction_new_stored_link', {
|
||||
ID: groupId,
|
||||
title: this.escapeHtml(title)
|
||||
});
|
||||
this.error_message = '';
|
||||
} else {
|
||||
this.success_message = this.$t('firefly.transaction_updated_link', {ID: groupId, title: this.escapeHtml(title)});
|
||||
this.success_message = this.$t('firefly.transaction_updated_link', {
|
||||
ID: groupId,
|
||||
title: this.escapeHtml(title)
|
||||
});
|
||||
this.error_message = '';
|
||||
}
|
||||
} else {
|
||||
|
@@ -19,205 +19,213 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<!--
|
||||
Show if:
|
||||
- one or more currencies.
|
||||
-->
|
||||
<div v-if="this.enabledCurrencies.length >= 1" class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||
<div class="col-sm-8 col-sm-offset-4 text-sm">
|
||||
{{ $t('form.foreign_amount') }}
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<select ref="currency_select" class="form-control" name="foreign_currency[]" @input="handleInput">
|
||||
<option
|
||||
v-for="currency in this.enabledCurrencies"
|
||||
:label="currency.attributes.name"
|
||||
:selected="parseInt(value.currency_id) === parseInt(currency.id)"
|
||||
:value="currency.id"
|
||||
<!--
|
||||
Show if:
|
||||
- one or more currencies.
|
||||
-->
|
||||
<div v-if="this.enabledCurrencies.length >= 1" class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||
<div class="col-sm-8 col-sm-offset-4 text-sm">
|
||||
{{ $t('form.foreign_amount') }}
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<select ref="currency_select" class="form-control" name="foreign_currency[]" @input="handleInput">
|
||||
<option
|
||||
v-for="currency in this.enabledCurrencies"
|
||||
:label="currency.attributes.name"
|
||||
:selected="parseInt(value.currency_id) === parseInt(currency.id)"
|
||||
:value="currency.id"
|
||||
|
||||
>
|
||||
{{ currency.attributes.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<input v-if="this.enabledCurrencies.length > 0" ref="amount" :placeholder="this.title" :title="this.title" :value="value.amount" autocomplete="off"
|
||||
class="form-control" name="foreign_amount[]"
|
||||
step="any" type="number" @input="handleInput">
|
||||
<span class="input-group-btn">
|
||||
>
|
||||
{{ currency.attributes.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<input v-if="this.enabledCurrencies.length > 0" ref="amount" :placeholder="this.title"
|
||||
:title="this.title" :value="value.amount" autocomplete="off"
|
||||
class="form-control" name="foreign_amount[]"
|
||||
step="any" type="number" @input="handleInput">
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
class="btn btn-default"
|
||||
tabIndex="-1"
|
||||
type="button"
|
||||
v-on:click="clearAmount"><i class="fa fa-trash-o"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
<ul v-for="error in this.error" class="list-unstyled">
|
||||
<li class="text-danger">{{ error }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul v-for="error in this.error" class="list-unstyled">
|
||||
<li class="text-danger">{{ error }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ForeignAmountSelect",
|
||||
name: "ForeignAmountSelect",
|
||||
|
||||
props: ['source', 'destination', 'transactionType', 'value', 'error', 'no_currency', 'title',],
|
||||
mounted() {
|
||||
this.liability = false;
|
||||
this.loadCurrencies();
|
||||
props: ['source', 'destination', 'transactionType', 'value', 'error', 'no_currency', 'title',],
|
||||
mounted() {
|
||||
this.liability = false;
|
||||
// console.log('I am mounted with a ' + this.transactionType + ' transaction type and currency id!');
|
||||
// console.log(this.value);
|
||||
this.loadCurrencies();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currencies: [],
|
||||
enabledCurrencies: [],
|
||||
exclude: null,
|
||||
// liability overrules the drop-down list if the source or dest is a liability
|
||||
liability: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
source: function () {
|
||||
// console.log('ForeignAmountSelect watch source');
|
||||
this.changeData();
|
||||
},
|
||||
destination: function () {
|
||||
// console.log('ForeignAmountSelect watch destination');
|
||||
this.changeData();
|
||||
},
|
||||
transactionType: function () {
|
||||
// console.log('ForeignAmountSelect watch transaction type (is now ' + this.transactionType + ')');
|
||||
this.changeData();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearAmount: function () {
|
||||
this.$refs.amount.value = '';
|
||||
this.$emit('input', this.$refs.amount.value);
|
||||
// some event?
|
||||
this.$emit('clear:amount')
|
||||
},
|
||||
hasError: function () {
|
||||
//console.log('ForeignAmountSelect hasError');
|
||||
return this.error.length > 0;
|
||||
},
|
||||
handleInput(e) {
|
||||
// console.log('ForeignAmountSelect handleInput');
|
||||
let obj = {
|
||||
amount: this.$refs.amount.value,
|
||||
currency_id: this.$refs.currency_select.value,
|
||||
};
|
||||
// console.log(obj);
|
||||
this.$emit('input', obj
|
||||
);
|
||||
},
|
||||
changeData: function () {
|
||||
// console.log('ForeignAmountSelect changeData');
|
||||
this.enabledCurrencies = [];
|
||||
let destType = this.destination.type ? this.destination.type.toLowerCase() : 'invalid';
|
||||
let srcType = this.source.type ? this.source.type.toLowerCase() : 'invalid';
|
||||
let tType = this.transactionType ? this.transactionType.toLowerCase() : 'invalid';
|
||||
let liabilities = ['loan', 'debt', 'mortgage'];
|
||||
let sourceIsLiability = liabilities.indexOf(srcType) !== -1;
|
||||
let destIsLiability = liabilities.indexOf(destType) !== -1;
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currencies: [],
|
||||
enabledCurrencies: [],
|
||||
exclude: null,
|
||||
// liability overrules the drop down list if the source or dest is a liability
|
||||
liability: false
|
||||
// console.log(srcType + ' (source) is a liability: ' + sourceIsLiability);
|
||||
// console.log(destType + ' (dest) is a liability: ' + destIsLiability);
|
||||
// console.log('tType: ' + tType);
|
||||
if (tType === 'transfer' || destIsLiability || sourceIsLiability) {
|
||||
// console.log('Source is liability OR dest is liability, OR transfer. Lock list on currency of destination.');
|
||||
// console.log('Length of currencies is ' + this.currencies.length);
|
||||
// console.log(this.currencies);
|
||||
this.liability = true;
|
||||
// lock dropdown list on currencyID of destination.
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
|
||||
if (
|
||||
parseInt(this.currencies[key].id) === parseInt(this.destination.currency_id)
|
||||
) {
|
||||
// console.log('Enable currency!!');
|
||||
// console.log(this.destination);
|
||||
// console.log(this.currencies[key]);
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log('Enabled currencies length is now ' + this.enabledCurrencies.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// if type is withdrawal, list all but skip the source account ID.
|
||||
if (tType === 'withdrawal' && this.source && false === sourceIsLiability) {
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.source.currency_id !== this.currencies[key].id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if type is deposit, list all but skip the source account ID.
|
||||
if (tType === 'deposit' && this.destination) {
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.destination.currency_id !== this.currencies[key].id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
},
|
||||
loadCurrencies: function () {
|
||||
// console.log('loadCurrencies');
|
||||
// reset list of currencies:
|
||||
this.currencies = [
|
||||
{
|
||||
id: 0,
|
||||
attributes: {
|
||||
name: this.no_currency,
|
||||
enabled: true
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
this.enabledCurrencies = [
|
||||
{
|
||||
attributes: {
|
||||
name: this.no_currency,
|
||||
enabled: true
|
||||
},
|
||||
id: 0,
|
||||
}
|
||||
];
|
||||
|
||||
this.getCurrencies(1);
|
||||
},
|
||||
getCurrencies: function (page) {
|
||||
let url = document.getElementsByTagName('base')[0].href + "api/v1/currencies?page=" + page;
|
||||
axios.get(url, {}).then((res) => {
|
||||
|
||||
for (const key in res.data.data) {
|
||||
if (res.data.data.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (res.data.data[key].attributes.enabled) {
|
||||
// console.log(res.data.data[key].attributes);
|
||||
this.currencies.push(res.data.data[key]);
|
||||
this.enabledCurrencies.push(res.data.data[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res.data.meta.pagination.current_page < res.data.meta.pagination.total_pages) {
|
||||
this.getCurrencies(res.data.meta.pagination.current_page + 1);
|
||||
return;
|
||||
}
|
||||
this.changeData();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
source: function () {
|
||||
//console.log('ForeignAmountSelect watch source');
|
||||
this.changeData();
|
||||
},
|
||||
destination: function () {
|
||||
//console.log('ForeignAmountSelect watch destination');
|
||||
this.changeData();
|
||||
},
|
||||
transactionType: function () {
|
||||
//console.log('ForeignAmountSelect watch transaction type (is now ' + this.transactionType + ')');
|
||||
this.changeData();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearAmount: function () {
|
||||
this.$refs.amount.value = '';
|
||||
this.$emit('input', this.$refs.amount.value);
|
||||
// some event?
|
||||
this.$emit('clear:amount')
|
||||
},
|
||||
hasError: function () {
|
||||
//console.log('ForeignAmountSelect hasError');
|
||||
return this.error.length > 0;
|
||||
},
|
||||
handleInput(e) {
|
||||
//console.log('ForeignAmountSelect handleInput');
|
||||
let obj = {
|
||||
amount: this.$refs.amount.value,
|
||||
currency_id: this.$refs.currency_select.value,
|
||||
};
|
||||
// console.log(obj);
|
||||
this.$emit('input', obj
|
||||
);
|
||||
},
|
||||
changeData: function () {
|
||||
// console.log('ForeignAmountSelect changeData');
|
||||
this.enabledCurrencies = [];
|
||||
let destType = this.destination.type ? this.destination.type.toLowerCase() : 'invalid';
|
||||
let srcType = this.source.type ? this.source.type.toLowerCase() : 'invalid';
|
||||
let tType = this.transactionType ? this.transactionType.toLowerCase() : 'invalid';
|
||||
let liabilities = ['loan', 'debt', 'mortgage'];
|
||||
let sourceIsLiability = liabilities.indexOf(srcType) !== -1;
|
||||
let destIsLiability = liabilities.indexOf(destType) !== -1;
|
||||
|
||||
// console.log(srcType + ' (source) is a liability: ' + sourceIsLiability);
|
||||
// console.log(destType + ' (dest) is a liability: ' + destIsLiability);
|
||||
|
||||
if (tType === 'transfer' || destIsLiability || sourceIsLiability) {
|
||||
// console.log('Source is liability OR dest is liability, OR transfer. Lock list on currency of destination.');
|
||||
// console.log('Length of currencies is ' + this.currencies.length);
|
||||
// console.log(this.currencies);
|
||||
this.liability = true;
|
||||
// lock dropdown list on currencyID of destination.
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
// console.log('this.currencies[key].id = ' + this.currencies[key].id);
|
||||
// console.log('this.destination.currency_id = ' + this.destination.currency_id);
|
||||
if (parseInt(this.currencies[key].id) === parseInt(this.destination.currency_id)) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log('Enabled currencies length is now ' + this.enabledCurrencies.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// if type is withdrawal, list all but skip the source account ID.
|
||||
if (tType === 'withdrawal' && this.source && false === sourceIsLiability) {
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.source.currency_id !== this.currencies[key].id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if type is deposit, list all but skip the source account ID.
|
||||
if (tType === 'deposit' && this.destination) {
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.destination.currency_id !== this.currencies[key].id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
},
|
||||
loadCurrencies: function () {
|
||||
// reset list of currencies:
|
||||
this.currencies = [
|
||||
{
|
||||
id: 0,
|
||||
attributes: {
|
||||
name: this.no_currency,
|
||||
enabled: true
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
this.enabledCurrencies = [
|
||||
{
|
||||
attributes: {
|
||||
name: this.no_currency,
|
||||
enabled: true
|
||||
},
|
||||
id: 0,
|
||||
}
|
||||
];
|
||||
|
||||
this.getCurrencies(1);
|
||||
},
|
||||
getCurrencies: function(page) {
|
||||
// console.log('loadCurrencies on page ' + page);
|
||||
let url = document.getElementsByTagName('base')[0].href + "api/v1/currencies?page=" + page;
|
||||
axios.get(url, {}).then((res) => {
|
||||
|
||||
for (const key in res.data.data) {
|
||||
if (res.data.data.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (res.data.data[key].attributes.enabled) {
|
||||
// console.log(res.data.data[key].attributes);
|
||||
this.currencies.push(res.data.data[key]);
|
||||
this.enabledCurrencies.push(res.data.data[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(res.data.meta.pagination.current_page < res.data.meta.pagination.total_pages) {
|
||||
this.getCurrencies(res.data.meta.pagination.current_page + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -18,8 +18,8 @@
|
||||
"is_reconciled": "Ist abgestimmt",
|
||||
"split": "Teilen",
|
||||
"single_split": "Teilen",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"not_enough_currencies": "Nicht gen\u00fcgend W\u00e4hrungen",
|
||||
"not_enough_currencies_enabled": "Wenn Sie nur eine W\u00e4hrung aktiviert haben, ist es nicht erforderlich, Wechselkurse hinzuzuf\u00fcgen.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Buchung #{ID} (\"{title}\")<\/a> wurde gespeichert.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> wurde gespeichert.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") wurde aktualisiert.",
|
||||
|
@@ -18,8 +18,8 @@
|
||||
"is_reconciled": "Est rapproch\u00e9",
|
||||
"split": "S\u00e9paration",
|
||||
"single_split": "S\u00e9paration unique",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"not_enough_currencies": "Pas assez de devises",
|
||||
"not_enough_currencies_enabled": "Si vous n'avez qu'une seule devise activ\u00e9e, il n'y a pas besoin d'ajouter des taux de change.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">L'op\u00e9ration n\u00b0{ID} (\"{title}\")<\/a> a \u00e9t\u00e9 enregistr\u00e9e.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Le Webhook #{ID} (\"{title}\")<\/a> a \u00e9t\u00e9 enregistr\u00e9.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Le webhook #{ID}<\/a> (\"{title}\") a \u00e9t\u00e9 mis \u00e0 jour.",
|
||||
|
@@ -18,8 +18,8 @@
|
||||
"is_reconciled": "Is reconciled",
|
||||
"split": "Feloszt\u00e1s",
|
||||
"single_split": "Feloszt\u00e1s",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"not_enough_currencies": "Nincs el\u00e9g p\u00e9nznem",
|
||||
"not_enough_currencies_enabled": "Amennyiben csak egyetlen p\u00e9nznem enged\u00e9lyezett, akkor nincs sz\u00fcks\u00e9g \u00e1rfolyam be\u00e1ll\u00edt\u00e1sokra.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID} (\"{title}\")<\/a> mentve.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> elt\u00e1rolva.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") friss\u00edtve.",
|
||||
|
@@ -18,8 +18,8 @@
|
||||
"is_reconciled": "\u0421\u0432\u0435\u0440\u0435\u043d\u043e",
|
||||
"split": "\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c",
|
||||
"single_split": "\u0420\u0430\u0437\u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"not_enough_currencies": "\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0435\u0434\u0438\u043d\u0438\u0446 \u0432\u0430\u043b\u044e\u0442",
|
||||
"not_enough_currencies_enabled": "\u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0432\u0430\u043b\u044e\u0442\u0430, \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u0443\u0440\u0441\u044b \u0432\u0430\u043b\u044e\u0442.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f #{ID} (\"{title}\")<\/a> \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0430.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">\u0412\u0435\u0431-\u0445\u0443\u043a #{ID} (\"{title}\")<\/a> \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">\u0412\u0435\u0431-\u0445\u0443\u043a #{ID} (\"{title}\")<\/a> \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d.",
|
||||
@@ -182,6 +182,6 @@
|
||||
},
|
||||
"config": {
|
||||
"html_language": "ru",
|
||||
"date_time_fns": "D MMMM yyyy, @ HH:mm:ss"
|
||||
"date_time_fns": "d MMMM yyyy, @ HH:mm:ss"
|
||||
}
|
||||
}
|
@@ -18,8 +18,8 @@
|
||||
"is_reconciled": "Je usklajena",
|
||||
"split": "Razdeli",
|
||||
"single_split": "Razdeli",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"not_enough_currencies": "Ni dovolj valut",
|
||||
"not_enough_currencies_enabled": "\u010ce imate omogo\u010deno samo eno valuto, menjalnih te\u010dajev ni treba dodajati.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transakcija \u0161t. #{ID} (\"{title}\")<\/a> je bila shranjena.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> je bil shranjen.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") je bil posodobljen.",
|
||||
|
@@ -6,7 +6,7 @@
|
||||
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
|
||||
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
|
||||
"table": "\u8868\u683c",
|
||||
"welcome_back": "What's playing?",
|
||||
"welcome_back": "\u6b61\u8fce\u56de\u4f86\u7e7c\u7e8c\u7406\u8ca1\uff01",
|
||||
"flash_error": "\u932f\u8aa4\uff01",
|
||||
"flash_warning": "\u8b66\u544a\uff01",
|
||||
"flash_success": "\u6210\u529f\uff01",
|
||||
|
@@ -69,9 +69,13 @@
|
||||
{% for key, balance in account.endBalances %}
|
||||
<span title="{{ key }}">
|
||||
{% if 'balance' == key %}
|
||||
{{ formatAmountBySymbol(balance, account.currency.symbol, account.currency.decimal_places) }}
|
||||
{% if not convertToNative %}
|
||||
{{ formatAmountBySymbol(balance, account.currency.symbol, account.currency.decimal_places) }}
|
||||
{% endif %}
|
||||
{% elseif 'native_balance' == key %}
|
||||
{{ formatAmountBySymbol(balance, defaultCurrency.symbol, defaultCurrency.decimal_places) }}
|
||||
{% if convertToNative %}
|
||||
{{ formatAmountBySymbol(balance, defaultCurrency.symbol, defaultCurrency.decimal_places) }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
({{ formatAmountByCode(balance, key) }})
|
||||
{% endif %}
|
||||
|
@@ -11,7 +11,7 @@ use FireflyIII\Support\Search\QueryParser\NodeGroup;
|
||||
use FireflyIII\Support\Search\QueryParser\Node;
|
||||
use Tests\integration\TestCase;
|
||||
|
||||
abstract class AbstractQueryParserInterfaceParseQueryTest extends TestCase
|
||||
abstract class AbstractQueryParserInterfaceParseQueryTester extends TestCase
|
||||
{
|
||||
abstract protected function createParser(): QueryParserInterface;
|
||||
|
@@ -16,7 +16,7 @@ use FireflyIII\Support\Search\QueryParser\QueryParserInterface;
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class QueryParserParseQueryTest extends AbstractQueryParserInterfaceParseQueryTest
|
||||
final class QueryParserParseQueryTest extends AbstractQueryParserInterfaceParseQueryTester
|
||||
{
|
||||
protected function createParser(): QueryParserInterface
|
||||
{
|
||||
|
Reference in New Issue
Block a user