Compare commits

...

23 Commits

Author SHA1 Message Date
github-actions
3bec106840 Auto commit for release 'v6.2.2' on 2025-02-02 2025-02-02 16:20:11 +01:00
James Cole
fb01c36be1 Update changelog and manifest [skip ci] 2025-02-02 16:14:32 +01:00
James Cole
26d851e69e Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-02-02 16:14:09 +01:00
James Cole
28c18c046b Fix #9744 2025-02-02 16:13:56 +01:00
github-actions
318cef7e3b Auto commit for release 'develop' on 2025-02-02 2025-02-02 16:06:22 +01:00
James Cole
e8dc8f25be Update changelog [skip ci] 2025-02-02 16:02:45 +01:00
James Cole
10ccc30240 Fix #9738 2025-02-02 16:02:17 +01:00
James Cole
5adc877d5e Merge pull request #9743 from mansehr/feature-nordic-currencies
Feature nordic currencies
2025-02-02 15:23:05 +01:00
SoftBrix
30923afb2b Added ISK 2025-02-02 14:48:01 +01:00
SoftBrix
4eb6813b43 Added NOK 2025-02-02 14:46:26 +01:00
James Cole
7521a31619 Expand changelog. 2025-02-02 06:48:57 +01:00
James Cole
fc05beb452 Fix #9727 2025-02-02 06:24:10 +01:00
James Cole
1103428a83 Smaller issue replies. 2025-02-02 05:41:54 +01:00
James Cole
d06d521bf0 Merge branch 'main' into develop 2025-02-02 05:39:41 +01:00
James Cole
8f64f1c0eb Expand explanation. 2025-02-02 05:39:33 +01:00
James Cole
d11c232171 Fix https://github.com/firefly-iii/firefly-iii/issues/9736 2025-02-02 05:38:47 +01:00
SoftBrix
93c73248de Added SEK 2025-02-02 00:03:31 +01:00
James Cole
5bed081ab9 Fix https://github.com/firefly-iii/firefly-iii/issues/9731 2025-02-01 21:14:28 +01:00
James Cole
c5188c503e Fix https://github.com/firefly-iii/firefly-iii/issues/9713 2025-02-01 21:06:06 +01:00
James Cole
98ffcac7b6 Fix https://github.com/firefly-iii/firefly-iii/issues/9729 2025-02-01 20:58:35 +01:00
James Cole
df1e81d611 Fix https://github.com/firefly-iii/firefly-iii/issues/9730 2025-02-01 20:52:41 +01:00
James Cole
9711170b08 Fix https://github.com/firefly-iii/firefly-iii/issues/9732 2025-02-01 20:43:20 +01:00
github-actions
e43264bdce Auto commit for release 'develop' on 2025-02-01 2025-02-01 19:12:18 +01:00
31 changed files with 185 additions and 71 deletions

View File

@@ -9,9 +9,9 @@ fixed:
This is an automatic reply. `Share and enjoy` This is an automatic reply. `Share and enjoy`
This issue has been marked as fixed. The bug, feature or enhancement will become a part of Firefly III or the data importer in due course. Thanks for reporting! This issue has been marked as fixed. Thanks for reporting! A new version will be released in due time. Unfortunately, [I cannot give an estimate](https://docs.firefly-iii.org/references/faq/firefly-iii/general/#when-will-you-release-version-the-next-version), but [the roadmap](https://roadmap.firefly-iii.org/) is available for your reading pleasure.
A new version will be released in due time. Unfortunately, [I cannot give an estimate](https://docs.firefly-iii.org/references/faq/firefly-iii/general/#when-will-you-release-version-the-next-version), but [the roadmap](https://roadmap.firefly-iii.org/) is available for your reading pleasure. There is no need to close the issue. It will be closed automatically.
Thank you for your contributions. Thank you for your contributions.
feature: feature:
@@ -23,7 +23,7 @@ feature:
This is an automatic reply. `Share and enjoy` This is an automatic reply. `Share and enjoy`
This issue has been marked as a feature request. The requested (new) feature will become a part of Firefly III or the data importer in due course. This issue has been marked as a feature request.
If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates. If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
@@ -54,7 +54,7 @@ enhancement:
This is an automatic reply. `Share and enjoy` This is an automatic reply. `Share and enjoy`
This issue has been marked as an enhancement. The requested enhancement to an existing feature will become a part of Firefly III or the data importer in due course. This issue has been marked as an enhancement.
If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates. If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.

View File

@@ -3,6 +3,9 @@
Over time, many people have contributed to Firefly III. Their efforts are not always visible, but always remembered and appreciated. Over time, many people have contributed to Firefly III. Their efforts are not always visible, but always remembered and appreciated.
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution. Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2025
- SoftBrix
## 2024 ## 2024
- Sobuno - Sobuno
- TasneemTantawy - TasneemTantawy

View File

@@ -83,6 +83,9 @@ class AccountController extends Controller
$return = []; $return = [];
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit')); $result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
// set date to end-of-day for account balance.
$date->endOfDay();
/** @var Account $account */ /** @var Account $account */
foreach ($result as $account) { foreach ($result as $account) {
$nameWithBalance = $account->name; $nameWithBalance = $account->name;

View File

@@ -32,6 +32,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ApiSupport; use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -80,6 +81,10 @@ class AccountController extends Controller
/** @var Carbon $end */ /** @var Carbon $end */
$end = $dates['end']; $end = $dates['end'];
// set dates to end of day + start of day:
$start->startOfDay();
$end->endOfDay();
// user's preferences // user's preferences
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
@@ -113,7 +118,7 @@ class AccountController extends Controller
]; ];
// TODO this code is also present in the V2 chart account controller so this method is due to be deprecated. // TODO this code is also present in the V2 chart account controller so this method is due to be deprecated.
$currentStart = clone $start; $currentStart = clone $start;
$range = app('steam')->finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative); $range = Steam::finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative);
$previous = array_values($range)[0][$field]; $previous = array_values($range)[0][$field];
while ($currentStart <= $end) { while ($currentStart <= $end) {
$format = $currentStart->format('Y-m-d'); $format = $currentStart->format('Y-m-d');

View File

@@ -57,11 +57,11 @@ class IndexController extends Controller
public function index(): JsonResponse public function index(): JsonResponse
{ {
$piggies = $this->repository->getAll(); $entries = $this->repository->getAll();
$pageSize = $this->parameters->get('limit'); $pageSize = $this->parameters->get('limit');
$count = $piggies->count(); $count = $entries->count();
$piggies = $piggies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $entries = $entries->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($piggies, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($entries, $count, $pageSize, $this->parameters->get('page'));
$transformer = new ExchangeRateTransformer(); $transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters); // give params to transformer $transformer->setParameters($this->parameters); // give params to transformer

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData; use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\CleansChartData; use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
@@ -118,7 +119,7 @@ class AccountController extends Controller
'native_entries' => [], 'native_entries' => [],
]; ];
$currentStart = clone $params['start']; $currentStart = clone $params['start'];
$range = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
$previous = array_values($range)[0]['balance']; $previous = array_values($range)[0]['balance'];
$previousNative = array_values($range)[0]['native_balance']; $previousNative = array_values($range)[0]['native_balance'];

View File

@@ -54,6 +54,9 @@ class MonthReportGenerator implements ReportGeneratorInterface
$dayBefore = clone $this->start; $dayBefore = clone $this->start;
$dayBefore->subDay(); $dayBefore->subDay();
// move to end of day
$dayBefore->endOfDay();
/** @var Account $account */ /** @var Account $account */
foreach ($this->accounts as $account) { foreach ($this->accounts as $account) {
// balance the day before: // balance the day before:

View File

@@ -52,6 +52,7 @@ class AccountObserver
$currency = $repository->getAccountCurrency($account); $currency = $repository->getAccountCurrency($account);
if (null !== $currency && $currency->id !== $userCurrency->id && '' !== (string) $account->virtual_balance && 0 !== bccomp($account->virtual_balance, '0')) { if (null !== $currency && $currency->id !== $userCurrency->id && '' !== (string) $account->virtual_balance && 0 !== bccomp($account->virtual_balance, '0')) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setUserGroup($account->user->userGroup);
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$account->native_virtual_balance = $converter->convert($currency, $userCurrency, today(), $account->virtual_balance); $account->native_virtual_balance = $converter->convert($currency, $userCurrency, today(), $account->virtual_balance);

View File

@@ -52,6 +52,7 @@ class AutoBudgetObserver
$autoBudget->native_amount = null; $autoBudget->native_amount = null;
if ($autoBudget->transactionCurrency->id !== $userCurrency->id) { if ($autoBudget->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setUserGroup($autoBudget->budget->user->userGroup);
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$autoBudget->native_amount = $converter->convert($autoBudget->transactionCurrency, $userCurrency, today(), $autoBudget->amount); $autoBudget->native_amount = $converter->convert($autoBudget->transactionCurrency, $userCurrency, today(), $autoBudget->amount);
} }

View File

@@ -64,6 +64,7 @@ class BillObserver
$bill->native_amount_max = null; $bill->native_amount_max = null;
if ($bill->transactionCurrency->id !== $userCurrency->id) { if ($bill->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setUserGroup($bill->user->userGroup);
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$bill->native_amount_min = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_min); $bill->native_amount_min = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_min);
$bill->native_amount_max = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_max); $bill->native_amount_max = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_max);

View File

@@ -54,6 +54,7 @@ class BudgetLimitObserver
$budgetLimit->native_amount = null; $budgetLimit->native_amount = null;
if ($budgetLimit->transactionCurrency->id !== $userCurrency->id) { if ($budgetLimit->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setUserGroup($budgetLimit->budget->user->userGroup);
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$budgetLimit->native_amount = $converter->convert($budgetLimit->transactionCurrency, $userCurrency, today(), $budgetLimit->amount); $budgetLimit->native_amount = $converter->convert($budgetLimit->transactionCurrency, $userCurrency, today(), $budgetLimit->amount);
} }

View File

@@ -52,6 +52,7 @@ class PiggyBankEventObserver
$event->native_amount = null; $event->native_amount = null;
if ($event->piggyBank->transactionCurrency->id !== $userCurrency->id) { if ($event->piggyBank->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setUserGroup($event->piggyBank->accounts()->first()->user->userGroup);
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);
$event->native_amount = $converter->convert($event->piggyBank->transactionCurrency, $userCurrency, today(), $event->amount); $event->native_amount = $converter->convert($event->piggyBank->transactionCurrency, $userCurrency, today(), $event->amount);
} }

View File

@@ -714,6 +714,9 @@ class GroupCollector implements GroupCollectorInterface
if (null === $transaction['amount']) { if (null === $transaction['amount']) {
throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId)); throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId));
} }
$nativeAmount = (string) ('' === $transaction['native_amount'] ? '0' : $transaction['native_amount']);
$nativeForeignAmount = (string) ('' === $transaction['native_foreign_amount'] ? '0' : $transaction['native_foreign_amount']);
$foreignAmount = (string) ('' === $transaction['foreign_amount'] ? '0' : $transaction['foreign_amount']);
// set default: // set default:
if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) {
@@ -724,9 +727,8 @@ class GroupCollector implements GroupCollectorInterface
$groups[$groudId]['sums'][$currencyId]['amount'] = '0'; $groups[$groudId]['sums'][$currencyId]['amount'] = '0';
$groups[$groudId]['sums'][$currencyId]['native_amount'] = '0'; $groups[$groudId]['sums'][$currencyId]['native_amount'] = '0';
} }
$transaction['native_amount'] = null === $transaction['native_amount'] ? '0' : $transaction['native_amount'];
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']);
$groups[$groudId]['sums'][$currencyId]['native_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['native_amount'], $transaction['native_amount']); $groups[$groudId]['sums'][$currencyId]['native_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['native_amount'], $nativeAmount);
if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) { if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) {
$currencyId = (int) $transaction['foreign_currency_id']; $currencyId = (int) $transaction['foreign_currency_id'];
@@ -738,11 +740,10 @@ class GroupCollector implements GroupCollectorInterface
$groups[$groudId]['sums'][$currencyId]['currency_symbol'] = $transaction['foreign_currency_symbol']; $groups[$groudId]['sums'][$currencyId]['currency_symbol'] = $transaction['foreign_currency_symbol'];
$groups[$groudId]['sums'][$currencyId]['currency_decimal_places'] = $transaction['foreign_currency_decimal_places']; $groups[$groudId]['sums'][$currencyId]['currency_decimal_places'] = $transaction['foreign_currency_decimal_places'];
$groups[$groudId]['sums'][$currencyId]['amount'] = '0'; $groups[$groudId]['sums'][$currencyId]['amount'] = '0';
$groups[$groudId]['sums'][$currencyId]['save_amount'] = '0'; $groups[$groudId]['sums'][$currencyId]['native_amount'] = '0';
} }
$transaction['native_foreign_amount'] = null === $transaction['native_foreign_amount'] ? '0' : $transaction['native_foreign_amount']; $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $foreignAmount);
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['foreign_amount']); $groups[$groudId]['sums'][$currencyId]['native_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $nativeForeignAmount);
$groups[$groudId]['sums'][$currencyId]['native_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['native_foreign_amount']);
} }
} }
} }

View File

@@ -108,11 +108,14 @@ class ReconcileController extends Controller
if ($end->lt($start)) { if ($end->lt($start)) {
[$start, $end] = [$end, $start]; [$start, $end] = [$end, $start];
} }
// move dates to end of day and start of day:
$start->startOfDay();
$end->endOfDay();
$startDate = clone $start; $startDate = clone $start;
$startDate->subDay(); $startDate->subDay();
$startBalance = Steam::finalAccountBalance($account, $startDate)['balance']; $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places);
$endBalance = Steam::finalAccountBalance($account, $end)['balance']; $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places);
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
$subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]);

View File

@@ -93,6 +93,11 @@ class ShowController extends Controller
if ($end->lt($start)) { if ($end->lt($start)) {
[$start, $end] = [$end, $start]; [$start, $end] = [$end, $start];
} }
// make sure dates are end of day and start of day:
$start->startOfDay();
$end->endOfDay();
$location = $this->repository->getLocation($account); $location = $this->repository->getLocation($account);
$attachments = $this->repository->getAttachments($account); $attachments = $this->repository->getAttachments($account);
$today = today(config('app.timezone')); $today = today(config('app.timezone'));
@@ -181,6 +186,8 @@ class ShowController extends Controller
$subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); $subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]);
$periods = new Collection(); $periods = new Collection();
$end->endOfDay();
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation(); $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation();

View File

@@ -35,7 +35,6 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Controllers\AugumentData; use FireflyIII\Support\Http\Controllers\AugumentData;
use FireflyIII\Support\Http\Controllers\ChartGeneration; use FireflyIII\Support\Http\Controllers\ChartGeneration;
@@ -416,7 +415,9 @@ class AccountController extends Controller
*/ */
public function period(Account $account, Carbon $start, Carbon $end): JsonResponse public function period(Account $account, Carbon $start, Carbon $end): JsonResponse
{ {
Log::debug(sprintf('Now in period("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d'))); $start->startOfDay();
$end->endOfDay();
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 = []; $chartData = [];
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty('chart.account.period'); $cache->addProperty('chart.account.period');
@@ -425,7 +426,7 @@ class AccountController extends Controller
$cache->addProperty($this->convertToNative); $cache->addProperty($this->convertToNative);
$cache->addProperty($account->id); $cache->addProperty($account->id);
if ($cache->has()) { if ($cache->has()) {
return response()->json($cache->get()); // return response()->json($cache->get());
} }
// collect and filter balances for the entire period. // collect and filter balances for the entire period.
@@ -442,11 +443,8 @@ class AccountController extends Controller
$format = (string) trans('config.month_and_day_js', [], $locale); $format = (string) trans('config.month_and_day_js', [], $locale);
$accountCurrency = $this->accountRepository->getAccountCurrency($account); $accountCurrency = $this->accountRepository->getAccountCurrency($account);
Log::debug('One');
$range = Steam::finalAccountBalanceInRange($account, $start, $end, $this->convertToNative); $range = Steam::finalAccountBalanceInRange($account, $start, $end, $this->convertToNative);
Log::debug('Two');
$range = Steam::filterAccountBalances($range, $account, $this->convertToNative, $accountCurrency); $range = Steam::filterAccountBalances($range, $account, $this->convertToNative, $accountCurrency);
Log::debug('Three');
// temp, get end balance. // temp, get end balance.
Log::debug('temp get end balance'); Log::debug('temp get end balance');
@@ -462,25 +460,32 @@ class AccountController extends Controller
Log::debug('Balances exist at:'); Log::debug('Balances exist at:');
foreach ($range as $key => $value) { foreach ($range as $key => $value) {
$newRange[] = ['date' => $key, 'info' => $value]; $newRange[] = ['date' => $key, 'info' => $value];
Log::debug(sprintf(' - %s', $key)); Log::debug(sprintf('%d - %s (%s)', count($newRange) - 1, $key, json_encode($value)));
} }
$carbon = Carbon::createFromFormat('Y-m-d', $newRange[0]['date']); $carbon = Carbon::createFromFormat('Y-m-d', $newRange[0]['date'])->endOfDay();
Log::debug(sprintf('Start of loop, $carbon is %s', $carbon->format('Y-m-d H:i:s')));
while ($end->gte($current)) { while ($end->gte($current)) {
$momentBalance = $previous; $momentBalance = $previous;
$theDate = $current->format('Y-m-d'); // $theDate = $current->format('Y-m-d');
while ($carbon->lte($current) && array_key_exists($expectedIndex, $newRange)) { Log::debug(sprintf('Now at %s, with momentBalance %s', $current->format('Y-m-d H:i:s'), json_encode($momentBalance)));
$momentBalance = $newRange[$expectedIndex]['info'];
Log::debug(sprintf('Expected index is %d!, date is %s, current is %s', $expectedIndex, $carbon->format('Y-m-d'), $current->format('Y-m-d')));
$carbon = Carbon::createFromFormat('Y-m-d', $newRange[$expectedIndex]['date']);
++$expectedIndex;
}
// loop over the array with balances, find one that is earlier or on the same day.
while ($carbon->lte($current) && array_key_exists($expectedIndex, $newRange)) {
Log::debug(sprintf('[a] Expected index is %d, $carbon is %s, current is %s', $expectedIndex, $carbon->format('Y-m-d H:i:s'), $current->format('Y-m-d H:i:s')));
// grab the balance from that particular $expectedIndex
$momentBalance = $newRange[$expectedIndex]['info'];
++$expectedIndex;
// make new carbon based on the next found date. this should stop the loop.
if (array_key_exists($expectedIndex, $newRange)) {
$carbon = Carbon::createFromFormat('Y-m-d', $newRange[$expectedIndex]['date'])->endOfDay();
}
}
Log::debug(sprintf('momentBalance is now %s', json_encode($momentBalance)));
$return = $this->updateChartKeys($return, $momentBalance); $return = $this->updateChartKeys($return, $momentBalance);
$previous = $momentBalance; $previous = $momentBalance;
Log::debug(sprintf('Now at %s', $theDate), $momentBalance);
// process each balance thing. // process each balance thing.
foreach ($momentBalance as $key => $amount) { foreach ($momentBalance as $key => $amount) {
$label = $current->isoFormat($format); $label = $current->isoFormat($format);
@@ -489,8 +494,6 @@ class AccountController extends Controller
$current = app('navigation')->addPeriod($current, $step, 0); $current = app('navigation')->addPeriod($current, $step, 0);
// here too, to fix #8041, the data is corrected to the end of the period. // here too, to fix #8041, the data is corrected to the end of the period.
$current = app('navigation')->endOfX($current, $step, null); $current = app('navigation')->endOfX($current, $step, null);
Log::debug(sprintf('Next moment is %s', $current->format('Y-m-d')));
} }
Log::debug('End of chart loop.'); Log::debug('End of chart loop.');
// second loop (yes) to create nice array with info! Yay! // second loop (yes) to create nice array with info! Yay!

View File

@@ -189,9 +189,10 @@ class ReconcileController extends Controller
if ($end->lt($start)) { if ($end->lt($start)) {
[$end, $start] = [$start, $end]; [$end, $start] = [$start, $end];
} }
$start->startOfDay();
$end->endOfDay();
$startDate = clone $start; $startDate = clone $start;
$startDate->subDay(); $startDate->subDay();
$end->endOfDay();
$currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency;
$startBalance = Steam::finalAccountBalance($account, $startDate)['balance']; $startBalance = Steam::finalAccountBalance($account, $startDate)['balance'];

View File

@@ -83,6 +83,8 @@ class ReportController extends Controller
return view('error')->with('message', (string) trans('firefly.end_after_start_date')); return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
} }
$this->repository->cleanupBudgets(); $this->repository->cleanupBudgets();
$start->startOfDay();
$end->endOfDay();
app('view')->share( app('view')->share(
'subTitle', 'subTitle',
@@ -114,6 +116,8 @@ class ReportController extends Controller
return view('error')->with('message', (string) trans('firefly.end_after_start_date')); return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
} }
$this->repository->cleanupBudgets(); $this->repository->cleanupBudgets();
$start->startOfDay();
$end->endOfDay();
app('view')->share( app('view')->share(
'subTitle', 'subTitle',
@@ -146,6 +150,8 @@ class ReportController extends Controller
return view('error')->with('message', (string) trans('firefly.end_after_start_date')); return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
} }
$this->repository->cleanupBudgets(); $this->repository->cleanupBudgets();
$start->startOfDay();
$end->endOfDay();
app('view')->share( app('view')->share(
'subTitle', 'subTitle',
@@ -179,6 +185,8 @@ class ReportController extends Controller
} }
$this->repository->cleanupBudgets(); $this->repository->cleanupBudgets();
$start->startOfDay();
$end->endOfDay();
app('view')->share( app('view')->share(
'subTitle', 'subTitle',
@@ -211,6 +219,8 @@ class ReportController extends Controller
} }
$this->repository->cleanupBudgets(); $this->repository->cleanupBudgets();
$start->startOfDay();
$end->endOfDay();
app('view')->share( app('view')->share(
'subTitle', 'subTitle',
@@ -367,6 +377,8 @@ class ReportController extends Controller
return view('error')->with('message', (string) trans('firefly.end_after_start_date')); return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
} }
$this->repository->cleanupBudgets(); $this->repository->cleanupBudgets();
$start->startOfDay();
$end->endOfDay();
app('view')->share( app('view')->share(
'subTitle', 'subTitle',

View File

@@ -57,7 +57,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
*/ */
public function getCompleteSet(): Collection public function getCompleteSet(): Collection
{ {
return TransactionCurrency::orderBy('code', 'ASC')->get(); return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get();
} }
/** /**

View File

@@ -108,6 +108,6 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface
#[\Override] #[\Override]
public function getAll(): Collection public function getAll(): Collection
{ {
return $this->userGroup->currencyExchangeRates()->get(); return $this->userGroup->currencyExchangeRates()->orderBy('date', 'ASC')->get();
} }
} }

View File

@@ -410,11 +410,11 @@ class Steam
$defaultCurrency = app('amount')->getNativeCurrency(); $defaultCurrency = app('amount')->getNativeCurrency();
if ($convertToNative) { if ($convertToNative) {
if ($defaultCurrency->id === $currency?->id) { if ($defaultCurrency->id === $currency?->id) {
Log::debug(sprintf('Unset "native_balance" and "%s" for account #%d', $defaultCurrency->code, $account->id)); // Log::debug(sprintf('Unset "native_balance" and "%s" for account #%d', $defaultCurrency->code, $account->id));
unset($set['native_balance'], $set[$defaultCurrency->code]); unset($set['native_balance'], $set[$defaultCurrency->code]);
} }
if (null !== $currency && $defaultCurrency->id !== $currency->id) { if (null !== $currency && $defaultCurrency->id !== $currency->id) {
Log::debug(sprintf('Unset balance for account #%d', $account->id)); // Log::debug(sprintf('Unset balance for account #%d', $account->id));
unset($set['balance']); unset($set['balance']);
} }
@@ -426,13 +426,13 @@ class Steam
if (!$convertToNative) { if (!$convertToNative) {
if (null === $currency) { if (null === $currency) {
Log::debug(sprintf('Unset native_balance and make defaultCurrency balance the balance for account #%d', $account->id)); // Log::debug(sprintf('Unset native_balance and make defaultCurrency balance the balance for account #%d', $account->id));
$set['balance'] = $set[$defaultCurrency->code] ?? '0'; $set['balance'] = $set[$defaultCurrency->code] ?? '0';
unset($set['native_balance'], $set[$defaultCurrency->code]); unset($set['native_balance'], $set[$defaultCurrency->code]);
} }
if (null !== $currency) { if (null !== $currency) {
Log::debug(sprintf('Unset native_balance + defaultCurrency + currencyCode balance for account #%d', $account->id)); // Log::debug(sprintf('Unset native_balance + defaultCurrency + currencyCode balance for account #%d', $account->id));
unset($set['native_balance'], $set[$defaultCurrency->code], $set[$currency->code]); unset($set['native_balance'], $set[$defaultCurrency->code], $set[$currency->code]);
} }
} }

View File

@@ -132,7 +132,7 @@ class PiggyBankTransformer extends AbstractTransformer
$return = []; $return = [];
foreach ($piggyBank->accounts()->get() as $account) { foreach ($piggyBank->accounts()->get() as $account) {
$return[] = [ $return[] = [
'id' => $account->id, 'id' => (string) $account->id,
'name' => $account->name, 'name' => $account->name,
'current_amount' => (string) $account->pivot->current_amount, 'current_amount' => (string) $account->pivot->current_amount,
'native_current_amount' => (string) $account->pivot->native_current_amount, 'native_current_amount' => (string) $account->pivot->native_current_amount,

View File

@@ -3,6 +3,27 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## 6.2.2 - 2025-02-02
> ⚠️ _This release comes with many changes, small and large. I expect you will run into issue, and I appreciate your feedback and your patience as I fix them. I've tested many things, but I'm 100% sure I've missed things. Please open [an issue here](https://github.com/firefly-iii/firefly-iii/issues/new?template=bug.yml) if you run into problems._
### Fixed
- #9713
- #9727
- #9729
- #9730
- #9731
- #9732
- #9736
- #9738
- #9744
### Added
- #9743
## 6.2.1 - 2025-02-01 ## 6.2.1 - 2025-02-01
> ⚠️ _This release comes with many changes, small and large. I expect you will run into issue, and I appreciate your feedback and your patience as I fix them. I've tested many things, but I'm 100% sure I've missed things. Please open [an issue here](https://github.com/firefly-iii/firefly-iii/issues/new?template=bug.yml) if you run into problems._ > ⚠️ _This release comes with many changes, small and large. I expect you will run into issue, and I appreciate your feedback and your patience as I fix them. I've tested many things, but I'm 100% sure I've missed things. Please open [an issue here](https://github.com/firefly-iii/firefly-iii/issues/new?template=bug.yml) if you run into problems._

View File

@@ -81,7 +81,7 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false), 'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => '6.2.1', 'version' => '6.2.2',
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 25, 'db_version' => 25,

View File

@@ -42,6 +42,9 @@ class TransactionCurrencySeeder extends Seeder
$currencies[] = ['code' => 'PLN', 'name' => 'Polish złoty', 'symbol' => 'zł', 'decimal_places' => 2]; $currencies[] = ['code' => 'PLN', 'name' => 'Polish złoty', 'symbol' => 'zł', 'decimal_places' => 2];
$currencies[] = ['code' => 'TRY', 'name' => 'Turkish lira', 'symbol' => '₺', 'decimal_places' => 2]; $currencies[] = ['code' => 'TRY', 'name' => 'Turkish lira', 'symbol' => '₺', 'decimal_places' => 2];
$currencies[] = ['code' => 'DKK', 'name' => 'Dansk krone', 'symbol' => 'kr.', 'decimal_places' => 2]; $currencies[] = ['code' => 'DKK', 'name' => 'Dansk krone', 'symbol' => 'kr.', 'decimal_places' => 2];
$currencies[] = ['code' => 'ISK', 'name' => 'Íslensk króna', 'symbol' => 'kr.', 'decimal_places' => 2];
$currencies[] = ['code' => 'NOK', 'name' => 'Norsk krone', 'symbol' => 'kr.', 'decimal_places' => 2];
$currencies[] = ['code' => 'SEK', 'name' => 'Svensk krona', 'symbol' => 'kr.', 'decimal_places' => 2];
$currencies[] = ['code' => 'RON', 'name' => 'Romanian leu', 'symbol' => 'lei', 'decimal_places' => 2]; $currencies[] = ['code' => 'RON', 'name' => 'Romanian leu', 'symbol' => 'lei', 'decimal_places' => 2];
// american currencies // american currencies

6
package-lock.json generated
View File

@@ -7159,9 +7159,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@@ -57,6 +57,7 @@ export default {
data() { data() {
return { return {
currencies: [], currencies: [],
page: 1,
}; };
}, },
mounted() { mounted() {
@@ -65,6 +66,7 @@ export default {
methods: { methods: {
getCurrencies: function () { getCurrencies: function () {
this.currencies = []; this.currencies = [];
// start with page one, loop for the rest.
this.downloadCurrencies(1); this.downloadCurrencies(1);
}, },
downloadCurrencies: function (page) { downloadCurrencies: function (page) {

View File

@@ -42,6 +42,27 @@
<h3 class="box-title">{{ $t('firefly.header_exchange_rates_table') }}</h3> <h3 class="box-title">{{ $t('firefly.header_exchange_rates_table') }}</h3>
</div> </div>
<div class="box-body no-padding"> <div class="box-body no-padding">
<nav v-if="totalPages > 1">
<ul class="pagination">
<li v-if="1 === this.page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
<li class="page-item" v-if="1 !== this.page">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page-1)" rel="prev" :aria-label="$t('pagination.next')">&lsaquo;</a>
</li>
<li v-for="item in this.totalPages" :class="item === page ? 'page-item active' : 'page-item'" aria-current="page">
<span v-if="item === page" class="page-link" v-text="item"></span>
<a v-if="item !== page" class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + item" v-text="item"></a>
</li>
<li v-if="totalPages !== page" class="page-item">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page+1)" rel="next" :aria-label="$t('pagination.next')">&rsaquo;</a>
</li>
<li v-if="totalPages === page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
</ul>
</nav>
<table class="table table-responsive table-hover"> <table class="table table-responsive table-hover">
<thead> <thead>
<tr> <tr>
@@ -98,6 +119,28 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<nav v-if="totalPages > 1">
<ul class="pagination">
<li v-if="1 === this.page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
<li class="page-item" v-if="1 !== this.page">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page-1)" rel="prev" :aria-label="$t('pagination.next')">&lsaquo;</a>
</li>
<li v-for="item in this.totalPages" :class="item === page ? 'page-item active' : 'page-item'" aria-current="page">
<span v-if="item === page" class="page-link" v-text="item"></span>
<a v-if="item !== page" class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + item" v-text="item"></a>
</li>
<li v-if="totalPages !== page" class="page-item">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page+1)" rel="next" :aria-label="$t('pagination.next')">&rsaquo;</a>
</li>
<li v-if="totalPages === page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
</ul>
</nav>
</div> </div>
</div> </div>
</div> </div>
@@ -167,6 +210,8 @@ export default {
loading: true, loading: true,
posting: false, posting: false,
updating: false, updating: false,
page: 1,
totalPages: 1,
}; };
}, },
mounted() { mounted() {
@@ -175,8 +220,16 @@ export default {
let parts = window.location.href.split('/'); let parts = window.location.href.split('/');
this.from_code = parts[parts.length - 2].substring(0, 3); this.from_code = parts[parts.length - 2].substring(0, 3);
this.to_code = parts[parts.length - 1].substring(0, 3); this.to_code = parts[parts.length - 1].substring(0, 3);
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
this.page = parseInt(params.page ?? 1);
this.downloadCurrencies(); this.downloadCurrencies();
this.downloadRates(1); this.rates = [];
this.downloadRates(this.page);
}, },
methods: { methods: {
submitRate: function(e) { submitRate: function(e) {
@@ -203,16 +256,11 @@ export default {
return ('' === this.rates[index].rate && '' === this.rates[index].inverse) || this.updating; return ('' === this.rates[index].rate && '' === this.rates[index].inverse) || this.updating;
}, },
updateRate: function (index) { updateRate: function (index) {
// console.log('Update!');
// console.log(this.rates[index].key);
let parts = this.spliceKey(this.rates[index].key); let parts = this.spliceKey(this.rates[index].key);
if (0 === parts.length) { if (0 === parts.length) {
return; return;
} }
if ('' !== this.rates[index].rate) { if ('' !== this.rates[index].rate) {
// update rate
// console.log('Rate is ' + this.rates[index].rate);
// console.log('ID is ' + this.rates[index].rate_id);
this.updating = true; this.updating = true;
axios.put("./api/v1/exchange-rates/" + this.rates[index].rate_id, {rate: this.rates[index].rate}) axios.put("./api/v1/exchange-rates/" + this.rates[index].rate_id, {rate: this.rates[index].rate})
.then(() => { .then(() => {
@@ -220,9 +268,6 @@ export default {
}); });
} }
if ('' !== this.rates[index].inverse) { if ('' !== this.rates[index].inverse) {
// update inverse
// console.log('Inverse is ' + this.rates[index].inverse);
// console.log('Inverse ID is ' + this.rates[index].inverse_id);
this.updating = true; this.updating = true;
axios.put("./api/v1/exchange-rates/" + this.rates[index].inverse_id, {rate: this.rates[index].inverse}) axios.put("./api/v1/exchange-rates/" + this.rates[index].inverse_id, {rate: this.rates[index].inverse})
.then(() => { .then(() => {
@@ -281,7 +326,6 @@ export default {
}, },
downloadRates: function (page) { downloadRates: function (page) {
this.tempRates = {}; this.tempRates = {};
this.rates = [];
this.loading = true; this.loading = true;
axios.get("./api/v1/exchange-rates/rates/" + this.from_code + '/' + this.to_code + '?page=' + page).then((response) => { axios.get("./api/v1/exchange-rates/rates/" + this.from_code + '/' + this.to_code + '?page=' + page).then((response) => {
for (let i in response.data.data) { for (let i in response.data.data) {
@@ -334,13 +378,10 @@ export default {
} }
} }
if (parseInt(response.data.meta.pagination.current_page) < parseInt(response.data.meta.pagination.total_pages)) { this.totalPages = parseInt(response.data.meta.pagination.total_pages);
this.downloadRates(page + 1); this.loading = false;
} this.rates = Object.values(this.tempRates);
if (parseInt(response.data.meta.pagination.current_page) === parseInt(response.data.meta.pagination.total_pages)) { console.log('Do not download more pages. Now on page ' + this.page + ' of ' + this.totalPages);
this.loading = false;
this.rates = Object.values(this.tempRates);
}
}); });
} }
}, },

View File

@@ -138,7 +138,7 @@
"visit_webhook_url": "Webhook-URL besuchen", "visit_webhook_url": "Webhook-URL besuchen",
"reset_webhook_secret": "Webhook Secret zur\u00fccksetzen", "reset_webhook_secret": "Webhook Secret zur\u00fccksetzen",
"header_exchange_rates": "Wechselkurse", "header_exchange_rates": "Wechselkurse",
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.", "exchange_rates_intro": "Firefly III unterst\u00fctzt das Herunterladen und Verwenden von Wechselkursen. Lesen Sie mehr dar\u00fcber in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\"> der Dokumentation<\/a>.",
"exchange_rates_from_to": "Zwischen {from} und {to} (und umgekehrt)", "exchange_rates_from_to": "Zwischen {from} und {to} (und umgekehrt)",
"exchange_rates_intro_rates": "Firefly III verwendet die folgenden Wechselkurse. Der Kehrwert wird automatisch berechnet, wenn er nicht angegeben wurde. Wenn f\u00fcr das Datum der Transaktion kein Wechselkurs vorhanden ist, sucht Firefly III in der Vergangenheit nach einem Kurs. Wenn keine vorhanden sind, wird der Kurs \u201e1\u201c verwendet.", "exchange_rates_intro_rates": "Firefly III verwendet die folgenden Wechselkurse. Der Kehrwert wird automatisch berechnet, wenn er nicht angegeben wurde. Wenn f\u00fcr das Datum der Transaktion kein Wechselkurs vorhanden ist, sucht Firefly III in der Vergangenheit nach einem Kurs. Wenn keine vorhanden sind, wird der Kurs \u201e1\u201c verwendet.",
"header_exchange_rates_rates": "Wechselkurse", "header_exchange_rates_rates": "Wechselkurse",

View File

@@ -138,7 +138,7 @@
"visit_webhook_url": "Visiter l'URL du webhook", "visit_webhook_url": "Visiter l'URL du webhook",
"reset_webhook_secret": "R\u00e9initialiser le secret du webhook", "reset_webhook_secret": "R\u00e9initialiser le secret du webhook",
"header_exchange_rates": "Taux de change", "header_exchange_rates": "Taux de change",
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.", "exchange_rates_intro": "Firefly III prend en charge le chargement et l'utilisation des taux de change. En savoir plus \u00e0 ce sujet dans <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">la documentation<\/a>.",
"exchange_rates_from_to": "Entre {from} et {to} (et l'inverse)", "exchange_rates_from_to": "Entre {from} et {to} (et l'inverse)",
"exchange_rates_intro_rates": "Firefly III utilise les taux de change suivants. L'inverse est calcul\u00e9 automatiquement lorsqu'il n'est pas fourni. Si aucun taux de change n'existe pour la date de la transaction, Firefly III reviendra dans le temps pour en trouver un. Si aucun n'est pr\u00e9sent, le taux \"1\" sera utilis\u00e9.", "exchange_rates_intro_rates": "Firefly III utilise les taux de change suivants. L'inverse est calcul\u00e9 automatiquement lorsqu'il n'est pas fourni. Si aucun taux de change n'existe pour la date de la transaction, Firefly III reviendra dans le temps pour en trouver un. Si aucun n'est pr\u00e9sent, le taux \"1\" sera utilis\u00e9.",
"header_exchange_rates_rates": "Taux de change", "header_exchange_rates_rates": "Taux de change",

View File

@@ -36,8 +36,8 @@
<h3 class="box-title">{{ 'optionalFields'|_ }}</h3> <h3 class="box-title">{{ 'optionalFields'|_ }}</h3>
</div> </div>
<div class="box-body"> <div class="box-body">
{{ ExpandedForm.date('startdate') }} {{ ExpandedForm.date('start_date') }}
{{ ExpandedForm.date('targetdate') }} {{ ExpandedForm.date('target_date') }}
{{ ExpandedForm.textarea('notes', null, {helpText: trans('firefly.field_supports_markdown')}) }} {{ ExpandedForm.textarea('notes', null, {helpText: trans('firefly.field_supports_markdown')}) }}
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }} {{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
{{ ExpandedForm.objectGroup() }} {{ ExpandedForm.objectGroup() }}