mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-31 15:41:21 +00:00
Compare commits
7 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f909f1d9ff | ||
|
|
55018ca046 | ||
|
|
19c746a865 | ||
|
|
503d2aa786 | ||
|
|
70d83ab501 | ||
|
|
edab602bb7 | ||
|
|
f9bcc4b1fa |
@@ -104,15 +104,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,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -335,7 +335,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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -88,6 +88,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)));
|
||||
|
||||
@@ -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
|
||||
@@ -82,6 +82,7 @@ class Steam
|
||||
$currency = $accountCurrency ?? $nativeCurrency;
|
||||
Log::debug(sprintf('Currency is %s', $currency->code));
|
||||
|
||||
|
||||
// set start balances:
|
||||
$startBalance[$currency->code] ??= '0';
|
||||
if ($hasCurrency) {
|
||||
@@ -100,10 +101,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')
|
||||
|
||||
@@ -13,6 +13,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
|
||||
|
||||
@@ -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-09',
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 25,
|
||||
|
||||
|
||||
142
package-lock.json
generated
142
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",
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": "\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.",
|
||||
|
||||
@@ -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