Compare commits

..

54 Commits

Author SHA1 Message Date
github-actions
0a6b34b4f2 Auto commit for release 'v6.2.3' on 2025-02-05 2025-02-05 07:25:30 +01:00
github-actions
1e06b4dd0b Merge branch 'develop' 2025-02-05 06:23:14 +00:00
James Cole
5701f95e0b Expand changelog 2025-02-05 07:22:00 +01:00
James Cole
60d3572d37 Expand changelog 2025-02-05 07:21:31 +01:00
github-actions
ffa6e6a571 Auto commit for release 'develop' on 2025-02-05 2025-02-05 06:50:00 +01:00
James Cole
d6453cd735 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-02-05 06:46:35 +01:00
James Cole
fd79f9df44 Expand changelog, fix migration. 2025-02-05 06:46:27 +01:00
github-actions
4587340293 Auto commit for release 'develop' on 2025-02-05 2025-02-05 06:41:08 +01:00
James Cole
90bfdc7573 Fix #9754 2025-02-05 06:36:51 +01:00
James Cole
eca12f661f Fix #9327 2025-02-05 06:31:15 +01:00
James Cole
f85878b843 Final tweaks in account balance logic. 2025-02-05 06:29:07 +01:00
James Cole
6499b5eaab Rename variable for consistency. 2025-02-05 06:03:57 +01:00
James Cole
7e4fece63d add some checks and balances to migrations. 2025-02-05 05:58:53 +01:00
James Cole
512eddf8be Fix #9736 2025-02-05 05:51:22 +01:00
github-actions
f0fa93a811 Auto commit for release 'develop' on 2025-02-04 2025-02-04 21:38:20 +01:00
James Cole
3c8de21709 Fix balance and native balance lists. 2025-02-04 21:34:46 +01:00
James Cole
81173e8340 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	app/Support/Steam.php
2025-02-04 21:28:43 +01:00
James Cole
35a8fa5f02 Fix balance in range. 2025-02-04 21:27:24 +01:00
James Cole
443036936d Update changelog. 2025-02-04 21:26:53 +01:00
James Cole
ac88007593 Replace steam call. 2025-02-04 21:26:40 +01:00
github-actions
2297589dca Auto commit for release 'develop' on 2025-02-04 2025-02-04 19:48:38 +01:00
James Cole
6ada5fa560 Fix #9751 2025-02-04 19:43:53 +01:00
Sander Dorigo
8f6eefb5e7 Fix #9745 2025-02-04 08:45:08 +01:00
Sander Dorigo
b36a50381b Fix #9747 2025-02-04 08:42:54 +01:00
Sander Dorigo
51f84b3060 Fix #9762 2025-02-04 08:37:02 +01:00
Sander Dorigo
72132a19b0 Fix #9736 2025-02-04 08:30:27 +01:00
Sander Dorigo
065d165211 Fix #9713 2025-02-04 08:28:43 +01:00
James Cole
cabedf39b2 Merge pull request #9750 from firefly-iii/dependabot/github_actions/aws-actions/closed-issue-message-2
Bump aws-actions/closed-issue-message from 1 to 2
2025-02-03 08:03:16 +01:00
dependabot[bot]
5d3806fcd4 Bump aws-actions/closed-issue-message from 1 to 2
Bumps [aws-actions/closed-issue-message](https://github.com/aws-actions/closed-issue-message) from 1 to 2.
- [Release notes](https://github.com/aws-actions/closed-issue-message/releases)
- [Commits](https://github.com/aws-actions/closed-issue-message/compare/v1...v2)

---
updated-dependencies:
- dependency-name: aws-actions/closed-issue-message
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-03 03:34:11 +00:00
github-actions
01695b3342 Auto commit for release 'develop' on 2025-02-03 2025-02-03 04:08:56 +01:00
James Cole
71fb5fe077 Fix changelog. 2025-02-02 16:24:10 +01:00
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
45 changed files with 527 additions and 372 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

@@ -8,7 +8,7 @@ jobs:
command_and_close: command_and_close:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: aws-actions/closed-issue-message@v1 - uses: aws-actions/closed-issue-message@v2
with: with:
message: | message: |
Hi there! This is an automatic reply. `Share and enjoy` Hi there! This is an automatic reply. `Share and enjoy`

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

@@ -26,6 +26,7 @@ namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
@@ -52,6 +53,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);
@@ -72,12 +74,15 @@ class AccountObserver
// app('log')->debug('Observe "deleting" of an account.'); // app('log')->debug('Observe "deleting" of an account.');
$account->accountMeta()->delete(); $account->accountMeta()->delete();
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($account->user);
/** @var PiggyBank $piggy */ /** @var PiggyBank $piggy */
foreach ($account->piggyBanks()->get() as $piggy) { foreach ($account->piggyBanks()->get() as $piggy) {
$piggy->accounts()->detach($account); $piggy->accounts()->detach($account);
} }
foreach ($account->attachments()->get() as $attachment) { foreach ($account->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
foreach ($account->transactions()->get() as $transaction) { foreach ($account->transactions()->get() as $transaction) {
$transaction->delete(); $transaction->delete();

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

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -41,9 +42,12 @@ class BillObserver
public function deleting(Bill $bill): void public function deleting(Bill $bill): void
{ {
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($bill->user);
// app('log')->debug('Observe "deleting" of a bill.'); // app('log')->debug('Observe "deleting" of a bill.');
foreach ($bill->attachments()->get() as $attachment) { foreach ($bill->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$bill->notes()->delete(); $bill->notes()->delete();
} }
@@ -64,6 +68,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

@@ -25,6 +25,7 @@ namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
/** /**
* Class BudgetObserver * Class BudgetObserver
@@ -34,8 +35,12 @@ class BudgetObserver
public function deleting(Budget $budget): void public function deleting(Budget $budget): void
{ {
app('log')->debug('Observe "deleting" of a budget.'); app('log')->debug('Observe "deleting" of a budget.');
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($budget->user);
foreach ($budget->attachments()->get() as $attachment) { foreach ($budget->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$budgetLimits = $budget->budgetlimits()->get(); $budgetLimits = $budget->budgetlimits()->get();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
/** /**
* Class CategoryObserver * Class CategoryObserver
@@ -33,8 +34,12 @@ class CategoryObserver
public function deleting(Category $category): void public function deleting(Category $category): void
{ {
app('log')->debug('Observe "deleting" of a category.'); app('log')->debug('Observe "deleting" of a category.');
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($category->user);
foreach ($category->attachments()->get() as $attachment) { foreach ($category->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$category->notes()->delete(); $category->notes()->delete();
} }

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

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -46,8 +47,11 @@ class PiggyBankObserver
{ {
app('log')->debug('Observe "deleting" of a piggy bank.'); app('log')->debug('Observe "deleting" of a piggy bank.');
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($piggyBank->accounts()->first()->user);
foreach ($piggyBank->attachments()->get() as $attachment) { foreach ($piggyBank->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$piggyBank->piggyBankEvents()->delete(); $piggyBank->piggyBankEvents()->delete();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
/** /**
* Class RecurrenceObserver * Class RecurrenceObserver
@@ -33,8 +34,12 @@ class RecurrenceObserver
public function deleting(Recurrence $recurrence): void public function deleting(Recurrence $recurrence): void
{ {
app('log')->debug('Observe "deleting" of a recurrence.'); app('log')->debug('Observe "deleting" of a recurrence.');
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($recurrence->user);
foreach ($recurrence->attachments()->get() as $attachment) { foreach ($recurrence->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$recurrence->recurrenceRepetitions()->delete(); $recurrence->recurrenceRepetitions()->delete();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
/** /**
* Class TagObserver * Class TagObserver
@@ -34,8 +35,11 @@ class TagObserver
{ {
app('log')->debug('Observe "deleting" of a tag.'); app('log')->debug('Observe "deleting" of a tag.');
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($tag->user);
foreach ($tag->attachments()->get() as $attachment) { foreach ($tag->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$tag->locations()->delete(); $tag->locations()->delete();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
/** /**
* Class TransactionJournalObserver * Class TransactionJournalObserver
@@ -34,6 +35,10 @@ class TransactionJournalObserver
{ {
app('log')->debug('Observe "deleting" of a transaction journal.'); app('log')->debug('Observe "deleting" of a transaction journal.');
$repository = app(AttachmentRepositoryInterface::class);
$repository->setUser($transactionJournal->user);
// to make sure the listener doesn't get back to use and loop // to make sure the listener doesn't get back to use and loop
TransactionJournal::withoutEvents(static function () use ($transactionJournal): void { TransactionJournal::withoutEvents(static function () use ($transactionJournal): void {
foreach ($transactionJournal->transactions()->get() as $transaction) { foreach ($transactionJournal->transactions()->get() as $transaction) {
@@ -41,7 +46,7 @@ class TransactionJournalObserver
} }
}); });
foreach ($transactionJournal->attachments()->get() as $attachment) { foreach ($transactionJournal->attachments()->get() as $attachment) {
$attachment->delete(); $repository->destroy($attachment);
} }
$transactionJournal->locations()->delete(); $transactionJournal->locations()->delete();
$transactionJournal->sourceJournalLinks()->delete(); $transactionJournal->sourceJournalLinks()->delete();

View File

@@ -100,7 +100,7 @@ class GroupCollector implements GroupCollectorInterface
'category_id', 'category_id',
'budget_id', 'budget_id',
]; ];
$this->stringFields = ['amount', 'foreign_amount']; $this->stringFields = ['amount', 'foreign_amount', 'native_amount', 'native_foreign_amount'];
$this->total = 0; $this->total = 0;
$this->fields = [ $this->fields = [
// group // group
@@ -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()->endOfDay();
$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

@@ -109,8 +109,8 @@ class AccountController extends Controller
$accountNames = $this->extractNames($accounts); $accountNames = $this->extractNames($accounts);
// grab all balances // grab all balances
$startBalances = app('steam')->finalAccountsBalance($accounts, $start); $startBalances = Steam::finalAccountsBalance($accounts, $start);
$endBalances = app('steam')->finalAccountsBalance($accounts, $end); $endBalances = Steam::finalAccountsBalance($accounts, $end);
// loop the accounts, then check for balance and currency info. // loop the accounts, then check for balance and currency info.
foreach ($accounts as $account) { foreach ($accounts as $account) {
@@ -416,7 +416,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');
@@ -431,7 +433,7 @@ class AccountController extends Controller
// collect and filter balances for the entire period. // collect and filter balances for the entire period.
$step = $this->calculateStep($start, $end); $step = $this->calculateStep($start, $end);
Log::debug(sprintf('Step is %s', $step)); Log::debug(sprintf('Step is %s', $step));
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
$return = []; $return = [];
// fix for issue https://github.com/firefly-iii/firefly-iii/issues/8041 // fix for issue https://github.com/firefly-iii/firefly-iii/issues/8041
@@ -442,11 +444,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 +461,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 +495,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!
@@ -567,8 +571,8 @@ class AccountController extends Controller
$accountNames = $this->extractNames($accounts); $accountNames = $this->extractNames($accounts);
// grab all balances // grab all balances
$startBalances = app('steam')->finalAccountsBalance($accounts, $start); $startBalances = Steam::finalAccountsBalance($accounts, $start);
$endBalances = app('steam')->finalAccountsBalance($accounts, $end); $endBalances = Steam::finalAccountsBalance($accounts, $end);
// loop the accounts, then check for balance and currency info. // loop the accounts, then check for balance and currency info.

View File

@@ -189,13 +189,14 @@ 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::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);
// get the transactions // get the transactions
$selectionStart = clone $start; $selectionStart = clone $start;

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

@@ -28,10 +28,11 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Amount;
/** /**
* Class Steam. * Class Steam.
@@ -75,98 +76,79 @@ class Steam
$balances = []; $balances = [];
$formatted = $start->format('Y-m-d'); $formatted = $start->format('Y-m-d');
$startBalance = $this->finalAccountBalance($account, $start); $startBalance = $this->finalAccountBalance($account, $start);
$defaultCurrency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup); $nativeCurrency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup);
$accountCurrency = $this->getAccountCurrency($account); $accountCurrency = $this->getAccountCurrency($account);
$hasCurrency = null !== $accountCurrency; $hasCurrency = null !== $accountCurrency;
$currency = $accountCurrency ?? $defaultCurrency; $currency = $accountCurrency ?? $nativeCurrency;
Log::debug(sprintf('Currency is %s', $currency->code)); Log::debug(sprintf('Currency is %s', $currency->code));
// set start balances:
$startBalance[$currency->code] ??= '0';
if ($hasCurrency) {
$startBalance[$accountCurrency->code] ??= '0';
}
if (!$hasCurrency) { if (!$hasCurrency) {
Log::debug(sprintf('Also set start balance in %s', $defaultCurrency->code)); Log::debug(sprintf('Also set start balance in %s', $nativeCurrency->code));
$startBalance[$defaultCurrency->code] ??= '0'; $startBalance[$nativeCurrency->code] ??= '0';
} }
$currencies = [ $currencies = [
$currency->id => $currency, $currency->id => $currency,
$defaultCurrency->id => $defaultCurrency, $nativeCurrency->id => $nativeCurrency,
]; ];
$startBalance[$currency->code] ??= '0';
$balances[$formatted] = $startBalance; $balances[$formatted] = $startBalance;
Log::debug('Final start balance: ', $startBalance); Log::debug('Final start balance: ', $startBalance);
// sums up the balance changes per day.
// sums up the balance changes per day, for foreign, native and normal amounts.
$set = $account->transactions() $set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->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', '>=', $start->format('Y-m-d H:i:s'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
->groupBy('transaction_journals.date') ->groupBy('transaction_journals.date')
->groupBy('transactions.transaction_currency_id') ->groupBy('transactions.transaction_currency_id')
->groupBy('transactions.foreign_currency_id')
->orderBy('transaction_journals.date', 'ASC') ->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at') ->whereNull('transaction_journals.deleted_at')
->get( ->get(
[ // @phpstan-ignore-line [ // @phpstan-ignore-line
'transaction_journals.date', 'transaction_journals.date',
'transactions.transaction_currency_id', 'transactions.transaction_currency_id',
DB::raw('SUM(transactions.amount) AS modified'), DB::raw('SUM(transactions.amount) AS sum_of_day'),
'transactions.foreign_currency_id',
DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
DB::raw('SUM(transactions.native_amount) AS modified_native'),
] ]
) )
; ;
$currentBalance = $startBalance; $currentBalance = $startBalance;
$converter = new ExchangeRateConverter();
/** @var Transaction $entry */ /** @var Transaction $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
// normal, native and foreign amount // get date object
$carbon = new Carbon($entry->date, $entry->date_tz); $carbon = new Carbon($entry->date, $entry->date_tz);
$modified = (string) (null === $entry->modified ? '0' : $entry->modified); // make sure sum is a string:
$foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign); $sumOfDay = (string) (null === $entry->sum_of_day ? '0' : $entry->sum_of_day);
$nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native);
// find currency of this entry. // find currency of this entry, does not have to exist.
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id); $currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
// make sure this $entry has its own $entryCurrency
/** @var TransactionCurrency $entryCurrency */ /** @var TransactionCurrency $entryCurrency */
$entryCurrency = $currencies[$entry->transaction_currency_id]; $entryCurrency = $currencies[$entry->transaction_currency_id];
Log::debug(sprintf('Processing transaction(s) on date %s', $carbon->format('Y-m-d H:i:s'))); Log::debug(sprintf('Processing transaction(s) on date %s', $carbon->format('Y-m-d H:i:s')));
$currentBalance[$entryCurrency->code] ??= '0';
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, $currentBalance[$entryCurrency->code]);
// if convert to native, if NOT convert to native. // if not convert to native, add the amount to "balance", do nothing else.
if ($convertToNative) {
Log::debug(sprintf('Amount is %s %s, foreign amount is %s, native amount is %s', $entryCurrency->code, $this->bcround($modified, 2), $this->bcround($foreignModified, 2), $this->bcround($nativeModified, 2)));
// if the currency is the default currency add to native balance + currency balance
if ($entry->transaction_currency_id === $defaultCurrency->id) {
Log::debug('Add amount to native.');
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $modified);
}
// add to native balance.
if ($entry->foreign_currency_id !== $defaultCurrency->id) {
// this check is not necessary, because if the foreign currency is the same as the default currency, the native amount is zero.
// so adding this would mean nothing.
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeModified);
}
if ($entry->foreign_currency_id === $defaultCurrency->id) {
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $foreignModified);
}
// add to balance if is the same.
if ($entry->transaction_currency_id === $accountCurrency?->id) {
$currentBalance['balance'] = bcadd($currentBalance['balance'], $modified);
}
// add currency balance
$currentBalance[$entryCurrency->code] = bcadd($currentBalance[$entryCurrency->code] ?? '0', $modified);
}
if (!$convertToNative) { if (!$convertToNative) {
Log::debug(sprintf('Amount is %s %s, foreign amount is %s, native amount is %s', $entryCurrency->code, $modified, $foreignModified, $nativeModified)); $currentBalance['balance'] = bcadd($currentBalance['balance'], $sumOfDay);
// add to balance, as expected.
$currentBalance['balance'] = bcadd($currentBalance['balance'] ?? '0', $modified);
// add to GBP, as expected.
$currentBalance[$entryCurrency->code] = bcadd($currentBalance[$entryCurrency->code] ?? '0', $modified);
} }
// if convert to native add the converted amount to "native_balance".
if ($convertToNative) {
$nativeSumOfDay = $converter->convert($entryCurrency, $nativeCurrency, $carbon, $sumOfDay);
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeSumOfDay);
}
// add final $currentBalance array to the big one.
$balances[$carbon->format('Y-m-d')] = $currentBalance; $balances[$carbon->format('Y-m-d')] = $currentBalance;
Log::debug('Updated entry', $currentBalance); Log::debug('Updated entry', $currentBalance);
} }
@@ -275,24 +257,14 @@ class Steam
/** /**
* Returns the balance of an account at exact moment given. Array with at least one value. * Returns the balance of an account at exact moment given. Array with at least one value.
* Always returns:
* "balance": balance in the account's currency OR user's native currency if the account has no currency
* "EUR": balance in EUR (or whatever currencies the account has balance in)
* *
* "balance" the balance in whatever currency the account has, so the sum of all transaction that happen to have * If the user has $convertToNative:
* THAT currency. * "balance": balance in the account's currency OR user's native currency if the account has no currency
* "native_balance" the balance according to the "native_amount" + "native_foreign_amount" fields. * --> "native_balance": balance in the user's native balance, with all amounts converted to native.
* "ABC" the balance in this particular currency code (may repeat for each found currency). * "EUR": balance in EUR (or whatever currencies the account has balance in)
*
* Het maakt niet uit of de native currency wel of niet gelijk is aan de account currency.
* Optelsom zou hetzelfde moeten zijn. Als het EUR is en de rekening ook is native_amount 0.
* Zo niet is amount 0 en native_amount het bedrag.
*
* Eerst een som van alle transacties in de native currency. Alle EUR bij elkaar opgeteld.
* Om te weten wat er nog meer op de rekening gebeurt, pak alles waar currency niet EUR is, en de foreign ook niet,
* en tel native_amount erbij op.
* Daarna pak je alle transacties waar currency niet EUR is, en de foreign wel, en tel foreign_amount erbij op.
*
* Wil je niks weten van native currencies, pak je:
*
* Eerst een som van alle transacties gegroepeerd op currency. Einde.
*/ */
public function finalAccountBalance(Account $account, Carbon $date): array public function finalAccountBalance(Account $account, Carbon $date): array
{ {
@@ -310,48 +282,11 @@ class Steam
$accountCurrency = $this->getAccountCurrency($account); $accountCurrency = $this->getAccountCurrency($account);
$hasCurrency = null !== $accountCurrency; $hasCurrency = null !== $accountCurrency;
$currency = $hasCurrency ? $accountCurrency : $native; $currency = $hasCurrency ? $accountCurrency : $native;
$return = []; $return = [
'native_balance' => '0',
// first, the "balance", as described earlier. 'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
if ($convertToNative) { ];
// normal balance // balance(s) in all currencies.
$return['balance'] = (string) $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->where('transactions.transaction_currency_id', $native->id)
->sum('transactions.amount')
;
// plus virtual balance, if the account has a virtual_balance in the native currency
if ($native->id === $accountCurrency?->id) {
$return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']);
}
// Log::debug(sprintf('balance is (%s only) %s (with virtual balance)', $native->code, $this->bcround($return['balance'], 2)));
// native balance
$return['native_balance'] = (string) $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->whereNot('transactions.transaction_currency_id', $native->id)
->sum('transactions.native_amount')
;
// plus native virtual balance.
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['native_balance']);
// Log::debug(sprintf('native_balance is (all transactions to %s) %s (with virtual balance)', $native->code, $this->bcround($return['native_balance'])));
// plus foreign transactions in THIS currency.
$sum = (string) $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->whereNot('transactions.transaction_currency_id', $native->id)
->where('transactions.foreign_currency_id', $native->id)
->sum('transactions.foreign_amount')
;
$return['native_balance'] = bcadd($return['native_balance'], $sum);
// Log::debug(sprintf('Foreign amount transactions add (%s only) %s, total native_balance is now %s', $native->code, $this->bcround($sum), $this->bcround($return['native_balance'])));
}
// balance(s) in other (all) currencies.
$array = $account->transactions() $array = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id') ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
@@ -360,31 +295,38 @@ class Steam
; ;
$others = $this->groupAndSumTransactions($array, 'code', 'amount'); $others = $this->groupAndSumTransactions($array, 'code', 'amount');
// Log::debug('All balances are (joined)', $others); // Log::debug('All balances are (joined)', $others);
// if the account has no own currency preference, drop balance in favor of native balance // if there is no request to convert, take this as "balance" and "native_balance".
if ($hasCurrency && !$convertToNative) {
$return['balance'] = $others[$currency->code] ?? '0'; $return['balance'] = $others[$currency->code] ?? '0';
$return['native_balance'] = $others[$currency->code] ?? '0'; if (!$convertToNative) {
// Log::debug(sprintf('Set balance + native_balance to %s', $return['balance'])); unset($return['native_balance']);
// Log::debug(sprintf('Set balance to %s, unset native_balance', $return['balance']));
}
// if there is a request to convert, convert to "native_balance" and use "balance" for whichever amount is in the native currency.
if ($convertToNative) {
$return['native_balance'] = $this->convertAllBalances($others, $native, $date); // todo sum all and convert.
// Log::debug(sprintf('Set native_balance to %s', $return['native_balance']));
} }
// if the currency is the same as the native currency, set the native_balance to the balance for consistency. // either way, the balance is always combined with the virtual balance:
// if($currency->id === $native->id) { $virtualBalance = (string) ('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance);
// $return['native_balance'] = $return['balance'];
// }
if (!$hasCurrency && array_key_exists('balance', $return)) { if ($convertToNative) {
// Log::debug('Account has no currency preference, dropping balance in favor of native balance.'); // the native balance is combined with a converted virtual_balance:
$sum = bcadd($return['balance'], $return['native_balance']); $converter = new ExchangeRateConverter();
// Log::debug(sprintf('%s + %s = %s', $return['balance'], $return['native_balance'], $sum)); $nativeVirtualBalance = $converter->convert($currency, $native, $date, $virtualBalance);
$return['native_balance'] = $sum; $return['native_balance'] = bcadd($nativeVirtualBalance, $return['native_balance']);
unset($return['balance']); // Log::debug(sprintf('Native virtual balance makes the native total %s', $return['native_balance']));
}
if (!$convertToNative) {
// if not, also increase the balance + native balance for consistency.
$return['balance'] = bcadd($return['balance'], $virtualBalance);
// Log::debug(sprintf('Virtual balance makes the (native) total %s', $return['balance']));
} }
$final = array_merge($return, $others); $final = array_merge($return, $others);
// Log::debug('Return is', $final); Log::debug('Final balance is', $final);
$cache->store($final); $cache->store($final);
return array_merge($return, $others); return $final;
// Log::debug('Return is', $final);
} }
public function filterAccountBalances(array $total, Account $account, bool $convertToNative, ?TransactionCurrency $currency = null): array public function filterAccountBalances(array $total, Account $account, bool $convertToNative, ?TransactionCurrency $currency = null): array
@@ -410,17 +352,18 @@ 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]);
} }
// todo rethink this logic.
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']);
} }
if (null === $currency) { if (null === $currency) {
Log::debug(sprintf('TEMP DO NOT Drop defaultCurrency balance for account #%d', $account->id)); Log::debug(sprintf('Unset balance for account #%d', $account->id));
// unset($set[$this->defaultCurrency->code]); unset($set['balance']);
} }
} }
@@ -428,16 +371,15 @@ class Steam
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[$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 [%s] + [%s] balance for account #%d', $defaultCurrency->code, $currency->code, $account->id));
unset($set['native_balance'], $set[$defaultCurrency->code], $set[$currency->code]); unset($set[$defaultCurrency->code], $set[$currency->code]);
} }
} }
// put specific value first in array. // put specific value first in array.
if (array_key_exists('native_balance', $set)) { if (array_key_exists('native_balance', $set)) {
$set = ['native_balance' => $set['native_balance']] + $set; $set = ['native_balance' => $set['native_balance']] + $set;
@@ -687,4 +629,21 @@ class Steam
return $amount; return $amount;
} }
private function convertAllBalances(array $others, TransactionCurrency $native, Carbon $date): string
{
$total = '0';
$converter = new ExchangeRateConverter();
foreach ($others as $key => $amount) {
$currency = TransactionCurrency::where('code', $key)->first();
if (null === $currency) {
continue;
}
$current = $converter->convert($currency, $native, $date, $amount);
Log::debug(sprintf('Convert %s %s to %s %s', $currency->code, $amount, $native->code, $current));
$total = bcadd($current, $total);
}
return $total;
}
} }

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,44 @@
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.3 - 2025-02-05
> ⚠️ _Most pressing issues are fixed. Please open [an issue here](https://github.com/firefly-iii/firefly-iii/issues/new?template=bug.yml) if you run into problems._
### Fixed
- [Issue 9327](https://github.com/firefly-iii/firefly-iii/issues/9327) (Add Link to Search-Page to the help file) reported by @nottheend
- [Issue 9713](https://github.com/firefly-iii/firefly-iii/issues/9713) (Many decimal points in amounts) reported by @memo-567
- [Issue 9736](https://github.com/firefly-iii/firefly-iii/issues/9736) (Wrong `finalAccountBalance` result) reported by @gthbusrr
- [Discussion 9737](https://github.com/orgs/firefly-iii/discussions/9737) (API returns 0 as current balance) started by @eps90
- [Issue 9745](https://github.com/firefly-iii/firefly-iii/issues/9745) (Type mismatch in period overview) reported by @electrofloat
- [Issue 9747](https://github.com/firefly-iii/firefly-iii/issues/9747) (Data entry issues with exchange rates) reported by @Azmodeszer
- [Issue 9751](https://github.com/firefly-iii/firefly-iii/issues/9751) (Net worth changes since 6.2 update) reported by @ahmaddxb
- [Issue 9754](https://github.com/firefly-iii/firefly-iii/issues/9754) (Deleting account - Attachments remain) reported by @memo-567
- [Issue 9762](https://github.com/firefly-iii/firefly-iii/issues/9762) (Piggy bank show: start/target date not displayed) reported by @Simeam
- Various other balance related fixes.
## 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
- [Issue 9713](https://github.com/firefly-iii/firefly-iii/issues/9713) (Many decimal points in amounts) reported by @memo-567
- [Discussion 9727](https://github.com/orgs/firefly-iii/discussions/9727) (Odd behavior from graphs) started by @jbrandwi
- [Issue 9729](https://github.com/firefly-iii/firefly-iii/issues/9729) (Type mismatch in transaction collector) reported by @electrofloat
- [Issue 9730](https://github.com/firefly-iii/firefly-iii/issues/9730) (API: `PiggyBankAccountRead.id` should return string, returns int) reported by @dreautall
- [Issue 9731](https://github.com/firefly-iii/firefly-iii/issues/9731) ($userGroup must not be accessed before initialization) reported by @Azmodeszer
- [Issue 9732](https://github.com/firefly-iii/firefly-iii/issues/9732) (Editing dates of a piggy bank does not save) reported by @Simeam
- [Issue 9736](https://github.com/firefly-iii/firefly-iii/issues/9736) (Wrong `finalAccountBalance` result) reported by @gthbusrr
- [Issue 9738](https://github.com/firefly-iii/firefly-iii/issues/9738) (Missing pagination controls on exchange rate page) reported by @dicksonleong
- [Discussion 9744](https://github.com/orgs/firefly-iii/discussions/9744) (Downloading exchange rates results in 404 error) started by @electrofloat
### Added
- [PR 9743](https://github.com/firefly-iii/firefly-iii/pull/9743) (Feature nordic currencies) reported by @mansehr
## 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._

12
composer.lock generated
View File

@@ -1571,16 +1571,16 @@
}, },
{ {
"name": "guzzlehttp/uri-template", "name": "guzzlehttp/uri-template",
"version": "v1.0.3", "version": "v1.0.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/uri-template.git", "url": "https://github.com/guzzle/uri-template.git",
"reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" "reference": "30e286560c137526eccd4ce21b2de477ab0676d2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2",
"reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", "reference": "30e286560c137526eccd4ce21b2de477ab0676d2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1637,7 +1637,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/uri-template/issues", "issues": "https://github.com/guzzle/uri-template/issues",
"source": "https://github.com/guzzle/uri-template/tree/v1.0.3" "source": "https://github.com/guzzle/uri-template/tree/v1.0.4"
}, },
"funding": [ "funding": [
{ {
@@ -1653,7 +1653,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-12-03T19:50:20+00:00" "time": "2025-02-03T10:55:03+00:00"
}, },
{ {
"name": "jc5/google2fa-laravel", "name": "jc5/google2fa-laravel",

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.3',
'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

@@ -50,33 +50,60 @@ return new class () extends Migration {
}); });
Schema::table('piggy_banks', static function (Blueprint $table): void { Schema::table('piggy_banks', static function (Blueprint $table): void {
// 3. add currency // 3. add currency
if (!Schema::hasColumn('piggy_banks', 'transaction_currency_id')) {
$table->integer('transaction_currency_id', false, true)->after('account_id')->nullable(); $table->integer('transaction_currency_id', false, true)->after('account_id')->nullable();
}
if (!self::hasForeign('piggy_banks', 'unique_currency')) {
$table->foreign('transaction_currency_id', 'unique_currency')->references('id')->on('transaction_currencies')->onDelete('cascade'); $table->foreign('transaction_currency_id', 'unique_currency')->references('id')->on('transaction_currencies')->onDelete('cascade');
}
}); });
Schema::table('piggy_banks', static function (Blueprint $table): void { Schema::table('piggy_banks', static function (Blueprint $table): void {
// 4. rename columns // 4. rename columns
if (Schema::hasColumn('piggy_banks', 'targetamount') && !Schema::hasColumn('piggy_banks', 'target_amount')) {
$table->renameColumn('targetamount', 'target_amount'); $table->renameColumn('targetamount', 'target_amount');
}
if (Schema::hasColumn('piggy_banks', 'startdate') && !Schema::hasColumn('piggy_banks', 'start_date')) {
$table->renameColumn('startdate', 'start_date'); $table->renameColumn('startdate', 'start_date');
}
if (Schema::hasColumn('piggy_banks', 'targetdate') && !Schema::hasColumn('piggy_banks', 'target_date')) {
$table->renameColumn('targetdate', 'target_date'); $table->renameColumn('targetdate', 'target_date');
}
if (Schema::hasColumn('piggy_banks', 'targetdate') && !Schema::hasColumn('startdate_tz', 'start_date_tz')) {
$table->renameColumn('startdate_tz', 'start_date_tz'); $table->renameColumn('startdate_tz', 'start_date_tz');
}
if (Schema::hasColumn('piggy_banks', 'targetdate_tz') && !Schema::hasColumn('target_date_tz', 'start_date_tz')) {
$table->renameColumn('targetdate_tz', 'target_date_tz'); $table->renameColumn('targetdate_tz', 'target_date_tz');
}
}); });
Schema::table('piggy_banks', static function (Blueprint $table): void { Schema::table('piggy_banks', static function (Blueprint $table): void {
// 5. add new index // 5. add new index
if (!self::hasForeign('piggy_banks', 'piggy_banks_account_id_foreign')) {
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('set null'); $table->foreign('account_id')->references('id')->on('accounts')->onDelete('set null');
}
}); });
// rename some fields in piggy bank reps. // rename some fields in piggy bank reps.
Schema::table('piggy_bank_repetitions', static function (Blueprint $table): void { Schema::table('piggy_bank_repetitions', static function (Blueprint $table): void {
// 6. rename columns // 6. rename columns
if (Schema::hasColumn('piggy_bank_repetitions', 'currentamount') && !Schema::hasColumn('piggy_bank_repetitions', 'current_amount')) {
$table->renameColumn('currentamount', 'current_amount'); $table->renameColumn('currentamount', 'current_amount');
}
if (Schema::hasColumn('piggy_bank_repetitions', 'startdate') && !Schema::hasColumn('piggy_bank_repetitions', 'start_date')) {
$table->renameColumn('startdate', 'start_date'); $table->renameColumn('startdate', 'start_date');
}
if (Schema::hasColumn('piggy_bank_repetitions', 'targetdate') && !Schema::hasColumn('piggy_bank_repetitions', 'target_date')) {
$table->renameColumn('targetdate', 'target_date'); $table->renameColumn('targetdate', 'target_date');
}
if (Schema::hasColumn('piggy_bank_repetitions', 'startdate_tz') && !Schema::hasColumn('piggy_bank_repetitions', 'start_date_tz')) {
$table->renameColumn('startdate_tz', 'start_date_tz'); $table->renameColumn('startdate_tz', 'start_date_tz');
}
if (Schema::hasColumn('piggy_bank_repetitions', 'targetdate_tz') && !Schema::hasColumn('piggy_bank_repetitions', 'target_date_tz')) {
$table->renameColumn('targetdate_tz', 'target_date_tz'); $table->renameColumn('targetdate_tz', 'target_date_tz');
}
}); });
// create table account_piggy_bank // create table account_piggy_bank
if (!Schema::hasTable('account_piggy_bank')) {
Schema::create('account_piggy_bank', static function (Blueprint $table): void { Schema::create('account_piggy_bank', static function (Blueprint $table): void {
$table->id(); $table->id();
$table->integer('account_id', false, true); $table->integer('account_id', false, true);
@@ -86,6 +113,7 @@ return new class () extends Migration {
$table->foreign('piggy_bank_id')->references('id')->on('piggy_banks')->onDelete('cascade'); $table->foreign('piggy_bank_id')->references('id')->on('piggy_banks')->onDelete('cascade');
$table->unique(['account_id', 'piggy_bank_id'], 'unique_piggy_save'); $table->unique(['account_id', 'piggy_bank_id'], 'unique_piggy_save');
}); });
}
} }

View File

@@ -41,8 +41,6 @@ return new class () extends Migration {
'piggy_banks' => ['native_target_amount'], // works 'piggy_banks' => ['native_target_amount'], // works
'transactions' => ['native_amount', 'native_foreign_amount'], // works 'transactions' => ['native_amount', 'native_foreign_amount'], // works
// TODO button to recalculate all native amounts on selected pages?
]; ];
/** /**
@@ -52,9 +50,11 @@ return new class () extends Migration {
{ {
foreach ($this->tables as $table => $fields) { foreach ($this->tables as $table => $fields) {
foreach ($fields as $field) { foreach ($fields as $field) {
Schema::table($table, static function (Blueprint $table) use ($field): void { Schema::table($table, static function (Blueprint $tableObject) use ($table, $field): void {
// add amount column // add amount column
$table->decimal($field, 32, 12)->nullable(); if (!Schema::hasColumn($table, $field)) {
$tableObject->decimal($field, 32, 12)->nullable();
}
}); });
} }
} }

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

200
package-lock.json generated
View File

@@ -2591,9 +2591,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz",
"integrity": "sha512-Eeao7ewDq79jVEsrtWIj5RNqB8p2knlm9fhR6uJ2gqP7UfbLrTrxevudVrEPDM7Wkpn/HpRC2QfazH7MXLz3vQ==", "integrity": "sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2605,9 +2605,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.2.tgz",
"integrity": "sha512-yVh0Kf1f0Fq4tWNf6mWcbQBCLDpDrDEl88lzPgKhrgTcDrTtlmun92ywEF9dCjmYO3EFiSuJeeo9cYRxl2FswA==", "integrity": "sha512-K5GfWe+vtQ3kyEbihrimM38UgX57UqHp+oME7X/EX9Im6suwZfa7Hsr8AtzbJvukTpwMGs+4s29YMSO3rwWtsw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2619,9 +2619,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.2.tgz",
"integrity": "sha512-gCs0ErAZ9s0Osejpc3qahTsqIPUDjSKIyxK/0BGKvL+Tn0n3Kwvj8BrCv7Y5sR1Ypz1K2qz9Ny0VvkVyoXBVUQ==", "integrity": "sha512-PSN58XG/V/tzqDb9kDGutUruycgylMlUE59f40ny6QIRNsTEIZsrNQTJKUN2keMMSmlzgunMFqyaGLmly39sug==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2633,9 +2633,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.2.tgz",
"integrity": "sha512-aIB5Anc8hngk15t3GUkiO4pv42ykXHfmpXGS+CzM9CTyiWyT8HIS5ygRAy7KcFb/wiw4Br+vh1byqcHRTfq2tQ==", "integrity": "sha512-gQhK788rQJm9pzmXyfBB84VHViDERhAhzGafw+E5mUpnGKuxZGkMVDa3wgDFKT6ukLC5V7QTifzsUKdNVxp5qQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2647,9 +2647,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.2.tgz",
"integrity": "sha512-kpdsUdMlVJMRMaOf/tIvxk8TQdzHhY47imwmASOuMajg/GXpw8GKNd8LNwIHE5Yd1onehNpcUB9jHY6wgw9nHQ==", "integrity": "sha512-eiaHgQwGPpxLC3+zTAcdKl4VsBl3r0AiJOd1Um/ArEzAjN/dbPK1nROHrVkdnoE6p7Svvn04w3f/jEZSTVHunA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2661,9 +2661,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.2.tgz",
"integrity": "sha512-D0RDyHygOBCQiqookcPevrvgEarN0CttBecG4chOeIYCNtlKHmf5oi5kAVpXV7qs0Xh/WO2RnxeicZPtT50V0g==", "integrity": "sha512-lhdiwQ+jf8pewYOTG4bag0Qd68Jn1v2gO1i0mTuiD+Qkt5vNfHVK/jrT7uVvycV8ZchlzXp5HDVmhpzjC6mh0g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2675,9 +2675,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.2.tgz",
"integrity": "sha512-mCIw8j5LPDXmCOW8mfMZwT6F/Kza03EnSr4wGYEswrEfjTfVsFOxvgYfuRMxTuUF/XmRb9WSMD5GhCWDe2iNrg==", "integrity": "sha512-lfqTpWjSvbgQP1vqGTXdv+/kxIznKXZlI109WkIFPbud41bjigjNmOAAKoazmRGx+k9e3rtIdbq2pQZPV1pMig==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2689,9 +2689,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.2.tgz",
"integrity": "sha512-AwwldAu4aCJPob7zmjuDUMvvuatgs8B/QiVB0KwkUarAcPB3W+ToOT+18TQwY4z09Al7G0BvCcmLRop5zBLTag==", "integrity": "sha512-RGjqULqIurqqv+NJTyuPgdZhka8ImMLB32YwUle2BPTDqDoXNgwFjdjQC59FbSk08z0IqlRJjrJ0AvDQ5W5lpw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2703,9 +2703,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.2.tgz",
"integrity": "sha512-e7kDUGVP+xw05pV65ZKb0zulRploU3gTu6qH1qL58PrULDGxULIS0OSDQJLH7WiFnpd3ZKUU4VM3u/Z7Zw+e7Q==", "integrity": "sha512-ZvkPiheyXtXlFqHpsdgscx+tZ7hoR59vOettvArinEspq5fxSDSgfF+L5wqqJ9R4t+n53nyn0sKxeXlik7AY9Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2717,9 +2717,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.2.tgz",
"integrity": "sha512-SXYJw3zpwHgaBqTXeAZ31qfW/v50wq4HhNVvKFhRr5MnptRX2Af4KebLWR1wpxGJtLgfS2hEPuALRIY3LPAAcA==", "integrity": "sha512-UlFk+E46TZEoxD9ufLKDBzfSG7Ki03fo6hsNRRRHF+KuvNZ5vd1RRVQm8YZlGsjcJG8R252XFK0xNPay+4WV7w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2731,9 +2731,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-loongarch64-gnu": { "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.2.tgz",
"integrity": "sha512-e5XiCinINCI4RdyU3sFyBH4zzz7LiQRvHqDtRe9Dt8o/8hTBaYpdPimayF00eY2qy5j4PaaWK0azRgUench6WQ==", "integrity": "sha512-hJhfsD9ykx59jZuuoQgYT1GEcNNi3RCoEmbo5OGfG8RlHOiVS7iVNev9rhLKh7UBYq409f4uEw0cclTXx8nh8Q==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@@ -2745,9 +2745,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.2.tgz",
"integrity": "sha512-3SWN3e0bAsm9ToprLFBSro8nJe6YN+5xmB11N4FfNf92wvLye/+Rh5JGQtKOpwLKt6e61R1RBc9g+luLJsc23A==", "integrity": "sha512-g/O5IpgtrQqPegvqopvmdCF9vneLE7eqYfdPWW8yjPS8f63DNam3U4ARL1PNNB64XHZDHKpvO2Giftf43puB8Q==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -2759,9 +2759,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.2.tgz",
"integrity": "sha512-B1Oqt3GLh7qmhvfnc2WQla4NuHlcxAD5LyueUi5WtMc76ZWY+6qDtQYqnxARx9r+7mDGfamD+8kTJO0pKUJeJA==", "integrity": "sha512-bSQijDC96M6PuooOuXHpvXUYiIwsnDmqGU8+br2U7iPoykNi9JtMUpN7K6xml29e0evK0/g0D1qbAUzWZFHY5Q==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -2773,9 +2773,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.2.tgz",
"integrity": "sha512-UfUCo0h/uj48Jq2lnhX0AOhZPSTAq3Eostas+XZ+GGk22pI+Op1Y6cxQ1JkUuKYu2iU+mXj1QjPrZm9nNWV9rg==", "integrity": "sha512-49TtdeVAsdRuiUHXPrFVucaP4SivazetGUVH8CIxVsNsaPHV4PFkpLmH9LeqU/R4Nbgky9lzX5Xe1NrzLyraVA==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -2787,9 +2787,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.2.tgz",
"integrity": "sha512-chZLTUIPbgcpm+Z7ALmomXW8Zh+wE2icrG+K6nt/HenPLmtwCajhQC5flNSk1Xy5EDMt/QAOz2MhzfOfJOLSiA==", "integrity": "sha512-j+jFdfOycLIQ7FWKka9Zd3qvsIyugg5LeZuHF6kFlXo6MSOc6R1w37YUVy8VpAKd81LMWGi5g9J25P09M0SSIw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2801,9 +2801,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.2.tgz",
"integrity": "sha512-jo0UolK70O28BifvEsFD/8r25shFezl0aUk2t0VJzREWHkq19e+pcLu4kX5HiVXNz5qqkD+aAq04Ct8rkxgbyQ==", "integrity": "sha512-aDPHyM/D2SpXfSNCVWCxyHmOqN9qb7SWkY1+vaXqMNMXslZYnwh9V/UCudl6psyG0v6Ukj7pXanIpfZwCOEMUg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2815,9 +2815,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.2.tgz",
"integrity": "sha512-Vmg0NhAap2S54JojJchiu5An54qa6t/oKT7LmDaWggpIcaiL8WcWHEN6OQrfTdL6mQ2GFyH7j2T5/3YPEDOOGA==", "integrity": "sha512-LQRkCyUBnAo7r8dbEdtNU08EKLCJMgAk2oP5H3R7BnUlKLqgR3dUjrLBVirmc1RK6U6qhtDw29Dimeer8d5hzQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2829,9 +2829,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.2.tgz",
"integrity": "sha512-CV2aqhDDOsABKHKhNcs1SZFryffQf8vK2XrxP6lxC99ELZAdvsDgPklIBfd65R8R+qvOm1SmLaZ/Fdq961+m7A==", "integrity": "sha512-wt8OhpQUi6JuPFkm1wbVi1BByeag87LDFzeKSXzIdGcX4bMLqORTtKxLoCbV57BHYNSUSOKlSL4BYYUghainYA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -2843,9 +2843,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.2.tgz",
"integrity": "sha512-g2ASy1QwHP88y5KWvblUolJz9rN+i4ZOsYzkEwcNfaNooxNUXG+ON6F5xFo0NIItpHqxcdAyls05VXpBnludGw==", "integrity": "sha512-rUrqINax0TvrPBXrFKg0YbQx18NpPN3NNrgmaao9xRNbTwek7lOXObhx8tQy8gelmQ/gLaGy1WptpU2eKJZImg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3133,9 +3133,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.13.0", "version": "22.13.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
"integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4448,9 +4448,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001696", "version": "1.0.30001697",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001697.tgz",
"integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", "integrity": "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -5663,9 +5663,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.90", "version": "1.5.92",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.92.tgz",
"integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", "integrity": "sha512-BeHgmNobs05N1HMmMZ7YIuHfYBGlq/UmvlsTgg+fsbFs9xVMj+xJHFg19GN04+9Q+r8Xnh9LXqaYIyEWElnNgQ==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -5720,9 +5720,9 @@
} }
}, },
"node_modules/enhanced-resolve": { "node_modules/enhanced-resolve": {
"version": "5.18.0", "version": "5.18.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
"integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -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": {
@@ -8387,9 +8387,9 @@
} }
}, },
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.13.3", "version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -9987,9 +9987,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.34.0", "version": "4.34.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.2.tgz",
"integrity": "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg==", "integrity": "sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -10003,25 +10003,25 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.34.0", "@rollup/rollup-android-arm-eabi": "4.34.2",
"@rollup/rollup-android-arm64": "4.34.0", "@rollup/rollup-android-arm64": "4.34.2",
"@rollup/rollup-darwin-arm64": "4.34.0", "@rollup/rollup-darwin-arm64": "4.34.2",
"@rollup/rollup-darwin-x64": "4.34.0", "@rollup/rollup-darwin-x64": "4.34.2",
"@rollup/rollup-freebsd-arm64": "4.34.0", "@rollup/rollup-freebsd-arm64": "4.34.2",
"@rollup/rollup-freebsd-x64": "4.34.0", "@rollup/rollup-freebsd-x64": "4.34.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.34.0", "@rollup/rollup-linux-arm-gnueabihf": "4.34.2",
"@rollup/rollup-linux-arm-musleabihf": "4.34.0", "@rollup/rollup-linux-arm-musleabihf": "4.34.2",
"@rollup/rollup-linux-arm64-gnu": "4.34.0", "@rollup/rollup-linux-arm64-gnu": "4.34.2",
"@rollup/rollup-linux-arm64-musl": "4.34.0", "@rollup/rollup-linux-arm64-musl": "4.34.2",
"@rollup/rollup-linux-loongarch64-gnu": "4.34.0", "@rollup/rollup-linux-loongarch64-gnu": "4.34.2",
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.2",
"@rollup/rollup-linux-riscv64-gnu": "4.34.0", "@rollup/rollup-linux-riscv64-gnu": "4.34.2",
"@rollup/rollup-linux-s390x-gnu": "4.34.0", "@rollup/rollup-linux-s390x-gnu": "4.34.2",
"@rollup/rollup-linux-x64-gnu": "4.34.0", "@rollup/rollup-linux-x64-gnu": "4.34.2",
"@rollup/rollup-linux-x64-musl": "4.34.0", "@rollup/rollup-linux-x64-musl": "4.34.2",
"@rollup/rollup-win32-arm64-msvc": "4.34.0", "@rollup/rollup-win32-arm64-msvc": "4.34.2",
"@rollup/rollup-win32-ia32-msvc": "4.34.0", "@rollup/rollup-win32-ia32-msvc": "4.34.2",
"@rollup/rollup-win32-x64-msvc": "4.34.0", "@rollup/rollup-win32-x64-msvc": "4.34.2",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -10168,9 +10168,9 @@
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "7.7.0", "version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {

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>
@@ -76,10 +97,10 @@
> >
</td> </td>
<td> <td>
<input type="number" class="form-control" min="0" v-model="rate.rate"> <input type="number" class="form-control" min="0" step="any" v-model="rate.rate">
</td> </td>
<td> <td>
<input type="number" class="form-control" min="0" v-model="rate.inverse"> <input type="number" class="form-control" min="0" step="any" v-model="rate.inverse">
</td> </td>
<td> <td>
<div class="btn-group"> <div class="btn-group">
@@ -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);
}
if (parseInt(response.data.meta.pagination.current_page) === parseInt(response.data.meta.pagination.total_pages)) {
this.loading = false; this.loading = false;
this.rates = Object.values(this.tempRates); this.rates = Object.values(this.tempRates);
} console.log('Do not download more pages. Now on page ' + this.page + ' of ' + this.totalPages);
}); });
} }
}, },

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

@@ -28,7 +28,7 @@
"apply_rules_checkbox": "Zastosuj regu\u0142y", "apply_rules_checkbox": "Zastosuj regu\u0142y",
"fire_webhooks_checkbox": "Uruchom webhooki", "fire_webhooks_checkbox": "Uruchom webhooki",
"no_budget_pointer": "Wygl\u0105da na to, \u017ce nie masz jeszcze bud\u017cet\u00f3w. Powiniene\u015b utworzy\u0107 kilka na stronie <a href=\"budgets\">bud\u017cet\u00f3w<\/a>. Bud\u017cety mog\u0105 Ci pom\u00f3c \u015bledzi\u0107 wydatki.", "no_budget_pointer": "Wygl\u0105da na to, \u017ce nie masz jeszcze bud\u017cet\u00f3w. Powiniene\u015b utworzy\u0107 kilka na stronie <a href=\"budgets\">bud\u017cet\u00f3w<\/a>. Bud\u017cety mog\u0105 Ci pom\u00f3c \u015bledzi\u0107 wydatki.",
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.", "no_bill_pointer": "Wygl\u0105da na to, \u017ce nie masz jeszcze subskrypcji. Powiniene\u015b utworzy\u0107 j\u0105 na stronie <a href=\"subscriptions\">subskrypcji<\/a>. Subskrypcje mog\u0105 pom\u00f3c Ci \u015bledzi\u0107 wydatki.",
"source_account": "Konto \u017ar\u00f3d\u0142owe", "source_account": "Konto \u017ar\u00f3d\u0142owe",
"hidden_fields_preferences": "Mo\u017cesz w\u0142\u0105czy\u0107 wi\u0119cej opcji transakcji w swoich <a href=\"preferences\">ustawieniach<\/a>.", "hidden_fields_preferences": "Mo\u017cesz w\u0142\u0105czy\u0107 wi\u0119cej opcji transakcji w swoich <a href=\"preferences\">ustawieniach<\/a>.",
"destination_account": "Konto docelowe", "destination_account": "Konto docelowe",
@@ -151,7 +151,7 @@
"url": "URL", "url": "URL",
"active": "Aktywny", "active": "Aktywny",
"interest_date": "Data odsetek", "interest_date": "Data odsetek",
"administration_currency": "Native currency", "administration_currency": "Waluta natywna",
"title": "Tytu\u0142", "title": "Tytu\u0142",
"date": "Data", "date": "Data",
"book_date": "Data ksi\u0119gowania", "book_date": "Data ksi\u0119gowania",
@@ -166,12 +166,12 @@
"webhook_delivery": "Dor\u0119czenie", "webhook_delivery": "Dor\u0119czenie",
"from_currency_to_currency": "{from} &rarr; {to}", "from_currency_to_currency": "{from} &rarr; {to}",
"to_currency_from_currency": "{to} &rarr; {from}", "to_currency_from_currency": "{to} &rarr; {from}",
"rate": "Rate" "rate": "Kurs"
}, },
"list": { "list": {
"title": "Tytu\u0142", "title": "Tytu\u0142",
"active": "Jest aktywny?", "active": "Jest aktywny?",
"native_currency": "Native currency", "native_currency": "Waluta natywna",
"trigger": "Wyzwalacz", "trigger": "Wyzwalacz",
"response": "Odpowied\u017a", "response": "Odpowied\u017a",
"delivery": "Dor\u0119czenie", "delivery": "Dor\u0119czenie",

View File

@@ -138,7 +138,7 @@
"visit_webhook_url": "Obi\u0161\u010dite URL webhooka", "visit_webhook_url": "Obi\u0161\u010dite URL webhooka",
"reset_webhook_secret": "Ponastavi skrivno kodo webhooka", "reset_webhook_secret": "Ponastavi skrivno kodo webhooka",
"header_exchange_rates": "Menjalni te\u010daji", "header_exchange_rates": "Menjalni te\u010daji",
"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 podpira prenos in uporabo menjalnih te\u010dajev. Preberite ve\u010d o tem v <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">dokumentaciji<\/a>.",
"exchange_rates_from_to": "Med {from} in {to} (in obratno)", "exchange_rates_from_to": "Med {from} in {to} (in obratno)",
"exchange_rates_intro_rates": "Firefly III uporablja naslednje menjalne te\u010daje. Obratna vrednost se samodejno izra\u010duna, \u010de ni na voljo. \u010ce na dan transakcije ni menjalnega te\u010daja, se bo Firefly III vrnil v preteklost, da bi ga na\u0161el. \u010ce jih ni, se uporabi te\u010daj \"1\".", "exchange_rates_intro_rates": "Firefly III uporablja naslednje menjalne te\u010daje. Obratna vrednost se samodejno izra\u010duna, \u010de ni na voljo. \u010ce na dan transakcije ni menjalnega te\u010daja, se bo Firefly III vrnil v preteklost, da bi ga na\u0161el. \u010ce jih ni, se uporabi te\u010daj \"1\".",
"header_exchange_rates_rates": "Menjalni te\u010daji", "header_exchange_rates_rates": "Menjalni te\u010daji",

View File

@@ -733,7 +733,7 @@ return [
// END // END
'general_search_error' => 'An error occurred while searching. Please check the log files for more information.', 'general_search_error' => 'An error occurred while searching. Please check the log files for more information.',
'search_box' => 'Search', 'search_box' => 'Search',
'search_box_intro' => 'Welcome to the search function of Firefly III. Enter your search query in the box. Make sure you check out the help file because the search is pretty advanced.', 'search_box_intro' => 'Welcome to the search function of Firefly III. Enter your search query in the box. <a href="https://docs.firefly-iii.org/how-to/firefly-iii/features/search/">Make sure you check out the help file</a> because the search is pretty advanced.',
'search_error' => 'Error while searching', 'search_error' => 'Error while searching',
'search_searching' => 'Searching ...', 'search_searching' => 'Searching ...',
'search_results' => 'Search results', 'search_results' => 'Search results',

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() }}

View File

@@ -71,8 +71,8 @@
<tr> <tr>
<td>{{ 'start_date'|_ }}</td> <td>{{ 'start_date'|_ }}</td>
<td> <td>
{% if piggyBank.startdate %} {% if piggyBank.start_date %}
{{ piggyBank.startdate.isoFormat(monthAndDayFormat) }} {{ piggyBank.start_date.isoFormat(monthAndDayFormat) }}
{% else %} {% else %}
<em>{{ 'no_start_date'|_ }}</em> <em>{{ 'no_start_date'|_ }}</em>
{% endif %} {% endif %}
@@ -81,14 +81,14 @@
<tr> <tr>
<td>{{ 'target_date'|_ }}</td> <td>{{ 'target_date'|_ }}</td>
<td> <td>
{% if piggyBank.targetdate %} {% if piggyBank.target_date %}
{{ piggyBank.targetdate.isoFormat(monthAndDayFormat) }} {{ piggyBank.target_date.isoFormat(monthAndDayFormat) }}
{% else %} {% else %}
<em>{{ 'no_target_date'|_ }}</em> <em>{{ 'no_target_date'|_ }}</em>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% if piggyBank.targetdate and piggy.save_per_month %} {% if piggyBank.target_date and piggy.save_per_month %}
<tr> <tr>
<td>{{ 'suggested_amount'|_ }}</td> <td>{{ 'suggested_amount'|_ }}</td>
<td> <td>