🤖 Auto commit for release 'develop' on 2025-08-15

This commit is contained in:
JC5
2025-08-15 13:37:27 +02:00
parent 4885dbc78e
commit f2dc0d234b
20 changed files with 293 additions and 269 deletions

View File

@@ -345,16 +345,16 @@
}, },
{ {
"name": "fidry/cpu-core-counter", "name": "fidry/cpu-core-counter",
"version": "1.2.0", "version": "1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/theofidry/cpu-core-counter.git", "url": "https://github.com/theofidry/cpu-core-counter.git",
"reference": "8520451a140d3f46ac33042715115e290cf5785f" "reference": "db9508f7b1474469d9d3c53b86f817e344732678"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678",
"reference": "8520451a140d3f46ac33042715115e290cf5785f", "reference": "db9508f7b1474469d9d3c53b86f817e344732678",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -364,10 +364,10 @@
"fidry/makefile": "^0.2.0", "fidry/makefile": "^0.2.0",
"fidry/php-cs-fixer-config": "^1.1.2", "fidry/php-cs-fixer-config": "^1.1.2",
"phpstan/extension-installer": "^1.2.0", "phpstan/extension-installer": "^1.2.0",
"phpstan/phpstan": "^1.9.2", "phpstan/phpstan": "^2.0",
"phpstan/phpstan-deprecation-rules": "^1.0.0", "phpstan/phpstan-deprecation-rules": "^2.0.0",
"phpstan/phpstan-phpunit": "^1.2.2", "phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^1.4.4", "phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^8.5.31 || ^9.5.26", "phpunit/phpunit": "^8.5.31 || ^9.5.26",
"webmozarts/strict-phpunit": "^7.5" "webmozarts/strict-phpunit": "^7.5"
}, },
@@ -394,7 +394,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/theofidry/cpu-core-counter/issues", "issues": "https://github.com/theofidry/cpu-core-counter/issues",
"source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0"
}, },
"funding": [ "funding": [
{ {
@@ -402,20 +402,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-08-06T10:04:20+00:00" "time": "2025-08-14T07:29:31+00:00"
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.85.1", "version": "v3.86.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "2fb6d7f6c3398dca5786a1635b27405d73a417ba" "reference": "4a952bd19dc97879b0620f495552ef09b55f7d36"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2fb6d7f6c3398dca5786a1635b27405d73a417ba", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4a952bd19dc97879b0620f495552ef09b55f7d36",
"reference": "2fb6d7f6c3398dca5786a1635b27405d73a417ba", "reference": "4a952bd19dc97879b0620f495552ef09b55f7d36",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -499,7 +499,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.85.1" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.86.0"
}, },
"funding": [ "funding": [
{ {
@@ -507,7 +507,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-07-29T22:22:50+00:00" "time": "2025-08-13T22:36:21+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",

View File

@@ -65,7 +65,7 @@ class AccountController extends Controller
$this->chartData = new ChartData(); $this->chartData = new ChartData();
$this->repository = app(AccountRepositoryInterface::class); $this->repository = app(AccountRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request); $userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup); $this->repository->setUserGroup($userGroup);
return $next($request); return $next($request);
@@ -107,12 +107,12 @@ class AccountController extends Controller
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToPrimary); $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToPrimary);
$previous = array_values($range)[0]['balance']; $previous = array_values($range)[0]['balance'];
$pcPrevious = null; $pcPrevious = null;
if (!$currency instanceof TransactionCurrency) { if (!$currency instanceof TransactionCurrency) {
$currency = $this->default; $currency = $this->default;
} }
$currentSet = [ $currentSet = [
'label' => $account->name, 'label' => $account->name,
// the currency that belongs to the account. // the currency that belongs to the account.
@@ -153,7 +153,7 @@ class AccountController extends Controller
// do the same for the primary currency balance, if relevant: // do the same for the primary currency balance, if relevant:
$pcBalance = null; $pcBalance = null;
if ($this->convertToPrimary) { if ($this->convertToPrimary) {
$pcBalance = array_key_exists($format, $range) ? $range[$format]['pc_balance'] : $pcPrevious; $pcBalance = array_key_exists($format, $range) ? $range[$format]['pc_balance'] : $pcPrevious;
$pcPrevious = $pcBalance; $pcPrevious = $pcBalance;
@@ -170,7 +170,7 @@ class AccountController extends Controller
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
/** @var Preference $frontpage */ /** @var Preference $frontpage */
$frontpage = Preferences::get('frontpageAccounts', $defaultSet); $frontpage = Preferences::get('frontpageAccounts', $defaultSet);
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) { if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontpage->data = $defaultSet; $frontpage->data = $defaultSet;

View File

@@ -12,7 +12,6 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\AccountBalanceGrouped; use FireflyIII\Support\Http\Api\AccountBalanceGrouped;
use FireflyIII\Support\Http\Api\CleansChartData; use FireflyIII\Support\Http\Api\CleansChartData;
@@ -26,7 +25,7 @@ class BalanceController extends Controller
{ {
use CleansChartData; use CleansChartData;
use CollectsAccountsFromFilter; use CollectsAccountsFromFilter;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
private array $chartData; private array $chartData;
private GroupCollectorInterface $collector; private GroupCollectorInterface $collector;
@@ -89,7 +88,7 @@ class BalanceController extends Controller
foreach ($data as $entry) { foreach ($data as $entry) {
$this->chartData[] = $entry; $this->chartData[] = $entry;
} }
$this->chartData= $this->clean($this->chartData); $this->chartData = $this->clean($this->chartData);
return response()->json($this->chartData); return response()->json($this->chartData);
} }

View File

@@ -50,7 +50,7 @@ class BudgetController extends Controller
use CleansChartData; use CleansChartData;
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
protected OperationsRepositoryInterface $opsRepository; protected OperationsRepositoryInterface $opsRepository;
private BudgetLimitRepositoryInterface $blRepository; private BudgetLimitRepositoryInterface $blRepository;
@@ -83,13 +83,13 @@ class BudgetController extends Controller
*/ */
public function overview(DateRequest $request): JsonResponse public function overview(DateRequest $request): JsonResponse
{ {
$params = $request->getAll(); $params = $request->getAll();
/** @var Carbon $start */ /** @var Carbon $start */
$start = $params['start']; $start = $params['start'];
/** @var Carbon $end */ /** @var Carbon $end */
$end = $params['end']; $end = $params['end'];
// code from FrontpageChartGenerator, but not in separate class // code from FrontpageChartGenerator, but not in separate class
$budgets = $this->repository->getActiveBudgets(); $budgets = $this->repository->getActiveBudgets();
@@ -115,19 +115,19 @@ class BudgetController extends Controller
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget])); $spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
$expenses = $this->processExpenses($budget->id, $spent, $start, $end); $expenses = $this->processExpenses($budget->id, $spent, $start, $end);
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$currencies = [$this->primaryCurrency->id => $this->primaryCurrency,]; $currencies = [$this->primaryCurrency->id => $this->primaryCurrency];
/** /**
* @var int $currencyId * @var int $currencyId
* @var array $row * @var array $row
*/ */
foreach ($expenses as $currencyId => $row) { foreach ($expenses as $currencyId => $row) {
// budgeted, left and overspent are now 0. // budgeted, left and overspent are now 0.
$limit = $this->filterLimit($currencyId, $limits); $limit = $this->filterLimit($currencyId, $limits);
// primary currency entries // primary currency entries
$row['pc_budgeted'] = '0'; $row['pc_budgeted'] = '0';
$row['pc_spent'] = '0'; $row['pc_spent'] = '0';
$row['pc_left'] = '0'; $row['pc_left'] = '0';
$row['pc_overspent'] = '0'; $row['pc_overspent'] = '0';
@@ -142,18 +142,18 @@ class BudgetController extends Controller
// convert data if necessary. // convert data if necessary.
if (true === $this->convertToPrimary && $currencyId !== $this->primaryCurrency->id) { if (true === $this->convertToPrimary && $currencyId !== $this->primaryCurrency->id) {
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId); $currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$row['pc_budgeted'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['budgeted']); $row['pc_budgeted'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['budgeted']);
$row['pc_spent'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['spent']); $row['pc_spent'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['spent']);
$row['pc_left'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['left']); $row['pc_left'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['left']);
$row['pc_overspent'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['overspent']); $row['pc_overspent'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['overspent']);
} }
if (true === $this->convertToPrimary && $currencyId === $this->primaryCurrency->id) { if (true === $this->convertToPrimary && $currencyId === $this->primaryCurrency->id) {
$row['pc_budgeted'] = $row['budgeted']; $row['pc_budgeted'] = $row['budgeted'];
$row['pc_spent'] = $row['spent']; $row['pc_spent'] = $row['spent'];
$row['pc_left'] = $row['left']; $row['pc_left'] = $row['left'];
$row['pc_overspent'] = $row['overspent']; $row['pc_overspent'] = $row['overspent'];
} }
$rows[] = $row; $rows[] = $row;
} }
@@ -164,14 +164,14 @@ class BudgetController extends Controller
// } // }
// is always an array // is always an array
$return = []; $return = [];
foreach ($rows as $row) { foreach ($rows as $row) {
$current = [ $current = [
'label' => $budget->name, 'label' => $budget->name,
'currency_id' => (string)$row['currency_id'], 'currency_id' => (string)$row['currency_id'],
'currency_name' => $row['currency_name'], 'currency_name' => $row['currency_name'],
'currency_code' => $row['currency_code'], 'currency_code' => $row['currency_code'],
'currency_decimal_places' => $row['currency_decimal_places'], 'currency_decimal_places' => $row['currency_decimal_places'],
'primary_currency_id' => (string)$this->primaryCurrency->id, 'primary_currency_id' => (string)$this->primaryCurrency->id,
'primary_currency_name' => $this->primaryCurrency->name, 'primary_currency_name' => $this->primaryCurrency->name,
@@ -179,19 +179,19 @@ class BudgetController extends Controller
'primary_currency_symbol' => $this->primaryCurrency->symbol, 'primary_currency_symbol' => $this->primaryCurrency->symbol,
'primary_currency_decimal_places' => $this->primaryCurrency->decimal_places, 'primary_currency_decimal_places' => $this->primaryCurrency->decimal_places,
'period' => null, 'period' => null,
'date' => $row['start'], 'date' => $row['start'],
'start_date' => $row['start'], 'start_date' => $row['start'],
'end_date' => $row['end'], 'end_date' => $row['end'],
'yAxisID' => 0, 'yAxisID' => 0,
'type' => 'bar', 'type' => 'bar',
'entries' => [ 'entries' => [
'budgeted' => $row['budgeted'], 'budgeted' => $row['budgeted'],
'spent' => $row['spent'], 'spent' => $row['spent'],
'left' => $row['left'], 'left' => $row['left'],
'overspent' => $row['overspent'], 'overspent' => $row['overspent'],
], ],
'pc_entries' => [ 'pc_entries' => [
'budgeted' => $row['pc_budgeted'], 'budgeted' => $row['pc_budgeted'],
'spent' => '0', 'spent' => '0',
'left' => '0', 'left' => '0',
@@ -231,7 +231,7 @@ class BudgetController extends Controller
* This array contains the expenses in this budget. Grouped per currency. * This array contains the expenses in this budget. Grouped per currency.
* The grouping is on the main currency only. * The grouping is on the main currency only.
* *
* @var int $currencyId * @var int $currencyId
* @var array $block * @var array $block
*/ */
foreach ($spent as $currencyId => $block) { foreach ($spent as $currencyId => $block) {
@@ -249,7 +249,7 @@ class BudgetController extends Controller
'left' => '0', 'left' => '0',
'overspent' => '0', 'overspent' => '0',
]; ];
$currentBudgetArray = $block['budgets'][$budgetId]; $currentBudgetArray = $block['budgets'][$budgetId];
// var_dump($return); // var_dump($return);
/** @var array $journal */ /** @var array $journal */
@@ -290,7 +290,7 @@ class BudgetController extends Controller
private function processLimit(Budget $budget, BudgetLimit $limit): array private function processLimit(Budget $budget, BudgetLimit $limit): array
{ {
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$end = clone $limit->end_date; $end = clone $limit->end_date;
$end->endOfDay(); $end->endOfDay();
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget])); $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
$limitCurrencyId = $limit->transaction_currency_id; $limitCurrencyId = $limit->transaction_currency_id;
@@ -298,8 +298,8 @@ class BudgetController extends Controller
/** @var array $entry */ /** @var array $entry */
// only spent the entry where the entry's currency matches the budget limit's currency // only spent the entry where the entry's currency matches the budget limit's currency
// so $filtered will only have 1 or 0 entries // so $filtered will only have 1 or 0 entries
$filtered = array_filter($spent, fn($entry) => $entry['currency_id'] === $limitCurrencyId); $filtered = array_filter($spent, fn ($entry) => $entry['currency_id'] === $limitCurrencyId);
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end); $result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
if (1 === count($result)) { if (1 === count($result)) {
$compare = bccomp($limit->amount, (string)app('steam')->positive($result[$limitCurrencyId]['spent'])); $compare = bccomp($limit->amount, (string)app('steam')->positive($result[$limitCurrencyId]['spent']));
$result[$limitCurrencyId]['budgeted'] = $limit->amount; $result[$limitCurrencyId]['budgeted'] = $limit->amount;

View File

@@ -81,7 +81,7 @@ class CategoryController extends Controller
public function overview(DateRequest $request): JsonResponse public function overview(DateRequest $request): JsonResponse
{ {
/** @var Carbon $start */ /** @var Carbon $start */
$start = $this->parameters->get('start'); $start = $this->parameters->get('start');
/** @var Carbon $end */ /** @var Carbon $end */
$end = $this->parameters->get('end'); $end = $this->parameters->get('end');
@@ -92,25 +92,25 @@ class CategoryController extends Controller
// get journals for entire period: // get journals for entire period:
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->withAccountInformation(); $collector->setRange($start, $end)->withAccountInformation();
$collector->setXorAccounts($accounts)->withCategoryInformation(); $collector->setXorAccounts($accounts)->withCategoryInformation();
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]); $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]);
$journals = $collector->getExtractedJournals(); $journals = $collector->getExtractedJournals();
/** @var array $journal */ /** @var array $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
// find journal: // find journal:
$journalCurrencyId = (int)$journal['currency_id']; $journalCurrencyId = (int)$journal['currency_id'];
$currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId); $currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId);
$currencies[$journalCurrencyId] = $currency; $currencies[$journalCurrencyId] = $currency;
$currencyId = (int)$currency->id; $currencyId = (int)$currency->id;
$currencyName = (string)$currency->name; $currencyName = (string)$currency->name;
$currencyCode = (string)$currency->code; $currencyCode = (string)$currency->code;
$currencySymbol = (string)$currency->symbol; $currencySymbol = (string)$currency->symbol;
$currencyDecimalPlaces = (int)$currency->decimal_places; $currencyDecimalPlaces = (int)$currency->decimal_places;
$amount = Steam::positive($journal['amount']); $amount = Steam::positive($journal['amount']);
$pcAmount = null; $pcAmount = null;
// overrule if necessary: // overrule if necessary:
if ($this->convertToPrimary && $journalCurrencyId === $this->primaryCurrency->id) { if ($this->convertToPrimary && $journalCurrencyId === $this->primaryCurrency->id) {
@@ -127,8 +127,8 @@ class CategoryController extends Controller
} }
$categoryName = $journal['category_name'] ?? (string)trans('firefly.no_category'); $categoryName = $journal['category_name'] ?? (string)trans('firefly.no_category');
$key = sprintf('%s-%s', $categoryName, $currencyCode); $key = sprintf('%s-%s', $categoryName, $currencyCode);
// create arrays // create arrays
$return[$key] ??= [ $return[$key] ??= [
'label' => $categoryName, 'label' => $categoryName,
@@ -148,10 +148,10 @@ class CategoryController extends Controller
'yAxisID' => 0, 'yAxisID' => 0,
'type' => 'bar', 'type' => 'bar',
'entries' => [ 'entries' => [
'spent' => '0' 'spent' => '0',
], ],
'pc_entries' => [ 'pc_entries' => [
'spent' => '0' 'spent' => '0',
], ],
]; ];
@@ -161,10 +161,10 @@ class CategoryController extends Controller
$return[$key]['pc_entries']['spent'] = bcadd($return[$key]['pc_entries']['spent'], (string)$pcAmount); $return[$key]['pc_entries']['spent'] = bcadd($return[$key]['pc_entries']['spent'], (string)$pcAmount);
} }
} }
$return = array_values($return); $return = array_values($return);
// order by amount // order by amount
usort($return, static fn(array $a, array $b) => (float)$a['entries']['spent'] < (float)$b['entries']['spent'] ? 1 : -1); usort($return, static fn (array $a, array $b) => (float)$a['entries']['spent'] < (float)$b['entries']['spent'] ? 1 : -1);
return response()->json($this->clean($return)); return response()->json($this->clean($return));
} }

View File

@@ -28,13 +28,11 @@ use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\DestroyRequest; use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\DestroyRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\ValidationException;
use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class DestroyController extends Controller class DestroyController extends Controller
{ {
@@ -70,10 +68,11 @@ class DestroyController extends Controller
return response()->json([], 204); return response()->json([], 204);
} }
public function destroySingleByDate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse public function destroySingleByDate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse
{ {
$exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date); $exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date);
if(null !== $exchangeRate) { if (null !== $exchangeRate) {
$this->repository->deleteRate($exchangeRate); $this->repository->deleteRate($exchangeRate);
} }

View File

@@ -91,17 +91,17 @@ class ShowController extends Controller
public function showSingleByDate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse public function showSingleByDate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse
{ {
$transformer = new ExchangeRateTransformer(); $transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date); $exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date);
if(null === $exchangeRate) { if (null === $exchangeRate) {
throw new NotFoundHttpException(); throw new NotFoundHttpException();
} }
return response() return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer)) ->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
->header('Content-Type', self::CONTENT_TYPE) ->header('Content-Type', self::CONTENT_TYPE)
; ;
} }
} }

View File

@@ -43,7 +43,7 @@ class StoreController extends Controller
{ {
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates'; public const string RESOURCE_KEY = 'exchange-rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER]; protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository; private ExchangeRateRepositoryInterface $repository;
@@ -63,8 +63,8 @@ class StoreController extends Controller
public function storeByCurrencies(StoreByCurrenciesRequest $request, TransactionCurrency $from, TransactionCurrency $to): JsonResponse public function storeByCurrencies(StoreByCurrenciesRequest $request, TransactionCurrency $from, TransactionCurrency $to): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$collection = new Collection(); $collection = new Collection();
foreach ($data as $date => $rate) { foreach ($data as $date => $rate) {
$date = Carbon::createFromFormat('Y-m-d', $date); $date = Carbon::createFromFormat('Y-m-d', $date);
@@ -73,9 +73,10 @@ class StoreController extends Controller
// update existing rate. // update existing rate.
$existing = $this->repository->updateExchangeRate($existing, $rate); $existing = $this->repository->updateExchangeRate($existing, $rate);
$collection->push($existing); $collection->push($existing);
continue; continue;
} }
$new = $this->repository->storeExchangeRate($from, $to, $rate, $date); $new = $this->repository->storeExchangeRate($from, $to, $rate, $date);
$collection->push($new); $collection->push($new);
} }
@@ -86,17 +87,18 @@ class StoreController extends Controller
return response() return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer)) ->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE); ->header('Content-Type', self::CONTENT_TYPE)
;
} }
public function storeByDate(StoreByDateRequest $request, Carbon $date): JsonResponse public function storeByDate(StoreByDateRequest $request, Carbon $date): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$from = $request->getFromCurrency(); $from = $request->getFromCurrency();
$collection = new Collection(); $collection = new Collection();
foreach ($data['rates'] as $key => $rate) { foreach ($data['rates'] as $key => $rate) {
$to = TransactionCurrency::where('code', $key)->first(); $to = TransactionCurrency::where('code', $key)->first();
if (null === $to) { if (null === $to) {
continue; // should not happen. continue; // should not happen.
} }
@@ -105,9 +107,10 @@ class StoreController extends Controller
// update existing rate. // update existing rate.
$existing = $this->repository->updateExchangeRate($existing, $rate); $existing = $this->repository->updateExchangeRate($existing, $rate);
$collection->push($existing); $collection->push($existing);
continue; continue;
} }
$new = $this->repository->storeExchangeRate($from, $to, $rate, $date); $new = $this->repository->storeExchangeRate($from, $to, $rate, $date);
$collection->push($new); $collection->push($new);
} }
@@ -118,18 +121,19 @@ class StoreController extends Controller
return response() return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer)) ->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE); ->header('Content-Type', self::CONTENT_TYPE)
;
} }
public function store(StoreRequest $request): JsonResponse public function store(StoreRequest $request): JsonResponse
{ {
$date = $request->getDate(); $date = $request->getDate();
$rate = $request->getRate(); $rate = $request->getRate();
$from = $request->getFromCurrency(); $from = $request->getFromCurrency();
$to = $request->getToCurrency(); $to = $request->getToCurrency();
// already has rate? // already has rate?
$object = $this->repository->getSpecificRateOnDate($from, $to, $date); $object = $this->repository->getSpecificRateOnDate($from, $to, $date);
if ($object instanceof CurrencyExchangeRate) { if ($object instanceof CurrencyExchangeRate) {
// just update it, no matter. // just update it, no matter.
$rate = $this->repository->updateExchangeRate($object, $rate, $date); $rate = $this->repository->updateExchangeRate($object, $rate, $date);
@@ -144,6 +148,7 @@ class StoreController extends Controller
return response() return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $rate, $transformer)) ->api($this->jsonApiObject(self::RESOURCE_KEY, $rate, $transformer))
->header('Content-Type', self::CONTENT_TYPE); ->header('Content-Type', self::CONTENT_TYPE)
;
} }
} }

View File

@@ -40,7 +40,7 @@ class UpdateController extends Controller
{ {
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates'; public const string RESOURCE_KEY = 'exchange-rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER]; protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository; private ExchangeRateRepositoryInterface $repository;
@@ -67,7 +67,8 @@ class UpdateController extends Controller
return response() return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer)) ->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
->header('Content-Type', self::CONTENT_TYPE); ->header('Content-Type', self::CONTENT_TYPE)
;
} }
public function updateByDate(UpdateRequest $request, TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse public function updateByDate(UpdateRequest $request, TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse
@@ -80,11 +81,12 @@ class UpdateController extends Controller
$rate = $request->getRate(); $rate = $request->getRate();
$exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date); $exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
$transformer = new ExchangeRateTransformer(); $transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
return response() return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer)) ->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
->header('Content-Type', self::CONTENT_TYPE); ->header('Content-Type', self::CONTENT_TYPE)
;
} }
} }

View File

@@ -60,14 +60,17 @@ class StoreByCurrenciesRequest extends FormRequest
try { try {
$date = Carbon::createFromFormat('Y-m-d', $date); $date = Carbon::createFromFormat('Y-m-d', $date);
} catch (InvalidFormatException $e) { } catch (InvalidFormatException $e) {
$validator->errors()->add('date', trans('validation.date',['attribute' => 'date'])); $validator->errors()->add('date', trans('validation.date', ['attribute' => 'date']));
return; return;
} }
if (!is_numeric($rate)) { if (!is_numeric($rate)) {
$validator->errors()->add('rate', trans('validation.number',['attribute' => 'rate'])); $validator->errors()->add('rate', trans('validation.number', ['attribute' => 'rate']));
return; return;
} }
} }
}); }
);
} }
} }

View File

@@ -38,7 +38,7 @@ class StoreByDateRequest extends FormRequest
public function getAll(): array public function getAll(): array
{ {
return [ return [
'from' => $this->get('from'), 'from' => $this->get('from'),
'rates' => $this->get('rates', []), 'rates' => $this->get('rates', []),
]; ];
} }
@@ -62,7 +62,7 @@ class StoreByDateRequest extends FormRequest
public function withValidator(Validator $validator): void public function withValidator(Validator $validator): void
{ {
$from = $this->getFromCurrency(); $from = $this->getFromCurrency();
$validator->after( $validator->after(
static function (Validator $validator) use ($from): void { static function (Validator $validator) use ($from): void {
@@ -70,11 +70,13 @@ class StoreByDateRequest extends FormRequest
$rates = $data['rates'] ?? []; $rates = $data['rates'] ?? [];
if (0 === count($rates)) { if (0 === count($rates)) {
$validator->errors()->add('rates', 'No rates given.'); $validator->errors()->add('rates', 'No rates given.');
return; return;
} }
foreach ($rates as $key => $entry) { foreach ($rates as $key => $entry) {
if ($key === $from->code) { if ($key === $from->code) {
$validator->errors()->add(sprintf('rates.%s', $key), trans('validation.convert_to_itself', ['code' => $key])); $validator->errors()->add(sprintf('rates.%s', $key), trans('validation.convert_to_itself', ['code' => $key]));
continue; continue;
} }
$to = TransactionCurrency::where('code', $key)->first(); $to = TransactionCurrency::where('code', $key)->first();
@@ -82,6 +84,7 @@ class StoreByDateRequest extends FormRequest
$validator->errors()->add(sprintf('rates.%s', $key), trans('validation.invalid_currency_code', ['code' => $key])); $validator->errors()->add(sprintf('rates.%s', $key), trans('validation.invalid_currency_code', ['code' => $key]));
} }
} }
}); }
);
} }
} }

View File

@@ -55,17 +55,20 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface, UserGro
// orderBy('date', 'DESC')->toRawSql(); // orderBy('date', 'DESC')->toRawSql();
return return
$this->userGroup->currencyExchangeRates() $this->userGroup->currencyExchangeRates()
->where(function (Builder $q1) use ($from, $to): void { ->where(function (Builder $q1) use ($from, $to): void {
$q1->where(function (Builder $q) use ($from, $to): void { $q1->where(function (Builder $q) use ($from, $to): void {
$q->where('from_currency_id', $from->id) $q->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id); ->where('to_currency_id', $to->id)
})->orWhere(function (Builder $q) use ($from, $to): void { ;
$q->where('from_currency_id', $to->id) })->orWhere(function (Builder $q) use ($from, $to): void {
->where('to_currency_id', $from->id); $q->where('from_currency_id', $to->id)
}); ->where('to_currency_id', $from->id)
}) ;
->orderBy('date', 'DESC') });
->get(['currency_exchange_rates.*']); })
->orderBy('date', 'DESC')
->get(['currency_exchange_rates.*'])
;
} }
@@ -75,10 +78,11 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface, UserGro
/** @var null|CurrencyExchangeRate */ /** @var null|CurrencyExchangeRate */
return return
$this->userGroup->currencyExchangeRates() $this->userGroup->currencyExchangeRates()
->where('from_currency_id', $from->id) ->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id) ->where('to_currency_id', $to->id)
->where('date', $date->format('Y-m-d')) ->where('date', $date->format('Y-m-d'))
->first(); ->first()
;
} }
#[Override] #[Override]
@@ -112,8 +116,8 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface, UserGro
public function deleteRates(TransactionCurrency $from, TransactionCurrency $to): void public function deleteRates(TransactionCurrency $from, TransactionCurrency $to): void
{ {
$this->userGroup->currencyExchangeRates() $this->userGroup->currencyExchangeRates()
->where('from_currency_id', $from->id) ->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id) ->where('to_currency_id', $to->id)
->delete(); ->delete();
} }
} }

View File

@@ -46,6 +46,7 @@ use Illuminate\Support\Collection;
interface ExchangeRateRepositoryInterface interface ExchangeRateRepositoryInterface
{ {
public function deleteRate(CurrencyExchangeRate $rate): void; public function deleteRate(CurrencyExchangeRate $rate): void;
public function deleteRates(TransactionCurrency $from, TransactionCurrency $to): void; public function deleteRates(TransactionCurrency $from, TransactionCurrency $to): void;
public function getAll(): Collection; public function getAll(): Collection;

View File

@@ -66,7 +66,7 @@ class AccountBalanceGrouped
/** @var array $currency */ /** @var array $currency */
foreach ($this->data as $currency) { foreach ($this->data as $currency) {
// income and expense array prepped: // income and expense array prepped:
$income = [ $income = [
'label' => 'earned', 'label' => 'earned',
'currency_id' => (string)$currency['currency_id'], 'currency_id' => (string)$currency['currency_id'],
'currency_symbol' => $currency['currency_symbol'], 'currency_symbol' => $currency['currency_symbol'],
@@ -85,7 +85,7 @@ class AccountBalanceGrouped
'entries' => [], 'entries' => [],
'pc_entries' => [], 'pc_entries' => [],
]; ];
$expense = [ $expense = [
'label' => 'spent', 'label' => 'spent',
'currency_id' => (string)$currency['currency_id'], 'currency_id' => (string)$currency['currency_id'],
'currency_symbol' => $currency['currency_symbol'], 'currency_symbol' => $currency['currency_symbol'],
@@ -107,22 +107,22 @@ class AccountBalanceGrouped
// loop all possible periods between $start and $end, and add them to the correct dataset. // loop all possible periods between $start and $end, and add them to the correct dataset.
$currentStart = clone $this->start; $currentStart = clone $this->start;
while ($currentStart <= $this->end) { while ($currentStart <= $this->end) {
$key = $currentStart->format($this->carbonFormat); $key = $currentStart->format($this->carbonFormat);
$label = $currentStart->toAtomString(); $label = $currentStart->toAtomString();
// normal entries // normal entries
$income['entries'][$label] = Steam::bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']); $income['entries'][$label] = Steam::bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
$expense['entries'][$label] = Steam::bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']); $expense['entries'][$label] = Steam::bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
// converted entries // converted entries
$income['pc_entries'][$label] = Steam::bcround($currency[$key]['pc_earned'] ?? '0', $currency['primary_currency_decimal_places']); $income['pc_entries'][$label] = Steam::bcround($currency[$key]['pc_earned'] ?? '0', $currency['primary_currency_decimal_places']);
$expense['pc_entries'][$label] = Steam::bcround($currency[$key]['pc_spent'] ?? '0', $currency['primary_currency_decimal_places']); $expense['pc_entries'][$label] = Steam::bcround($currency[$key]['pc_spent'] ?? '0', $currency['primary_currency_decimal_places']);
// next loop // next loop
$currentStart = Navigation::addPeriod($currentStart, $this->preferredRange, 0); $currentStart = Navigation::addPeriod($currentStart, $this->preferredRange, 0);
} }
$chartData[] = $income; $chartData[] = $income;
$chartData[] = $expense; $chartData[] = $expense;
} }
return $chartData; return $chartData;
@@ -148,9 +148,9 @@ class AccountBalanceGrouped
private function processJournal(array $journal): void private function processJournal(array $journal): void
{ {
// format the date according to the period // format the date according to the period
$period = $journal['date']->format($this->carbonFormat); $period = $journal['date']->format($this->carbonFormat);
$currencyId = (int)$journal['currency_id']; $currencyId = (int)$journal['currency_id'];
$currency = $this->findCurrency($currencyId); $currency = $this->findCurrency($currencyId);
// set the array with monetary info, if it does not exist. // set the array with monetary info, if it does not exist.
$this->createDefaultDataEntry($journal); $this->createDefaultDataEntry($journal);
@@ -158,12 +158,12 @@ class AccountBalanceGrouped
$this->createDefaultPeriodEntry($journal); $this->createDefaultPeriodEntry($journal);
// is this journal's amount in- our outgoing? // is this journal's amount in- our outgoing?
$key = $this->getDataKey($journal); $key = $this->getDataKey($journal);
$amount = 'spent' === $key ? Steam::negative($journal['amount']) : Steam::positive($journal['amount']); $amount = 'spent' === $key ? Steam::negative($journal['amount']) : Steam::positive($journal['amount']);
// get conversion rate // get conversion rate
$rate = $this->getRate($currency, $journal['date']); $rate = $this->getRate($currency, $journal['date']);
$amountConverted = bcmul((string)$amount, $rate); $amountConverted = bcmul((string)$amount, $rate);
// perhaps transaction already has the foreign amount in the primary currency. // perhaps transaction already has the foreign amount in the primary currency.
if ((int)$journal['foreign_currency_id'] === $this->primary->id) { if ((int)$journal['foreign_currency_id'] === $this->primary->id) {
@@ -172,7 +172,7 @@ class AccountBalanceGrouped
} }
// add normal entry // add normal entry
$this->data[$currencyId][$period][$key] = bcadd((string)$this->data[$currencyId][$period][$key], (string)$amount); $this->data[$currencyId][$period][$key] = bcadd((string)$this->data[$currencyId][$period][$key], (string)$amount);
// add converted entry // add converted entry
$convertedKey = sprintf('pc_%s', $key); $convertedKey = sprintf('pc_%s', $key);
@@ -191,7 +191,7 @@ class AccountBalanceGrouped
private function createDefaultDataEntry(array $journal): void private function createDefaultDataEntry(array $journal): void
{ {
$currencyId = (int)$journal['currency_id']; $currencyId = (int)$journal['currency_id'];
$this->data[$currencyId] ??= [ $this->data[$currencyId] ??= [
'currency_id' => (string)$currencyId, 'currency_id' => (string)$currencyId,
'currency_symbol' => $journal['currency_symbol'], 'currency_symbol' => $journal['currency_symbol'],
@@ -208,8 +208,8 @@ class AccountBalanceGrouped
private function createDefaultPeriodEntry(array $journal): void private function createDefaultPeriodEntry(array $journal): void
{ {
$currencyId = (int)$journal['currency_id']; $currencyId = (int)$journal['currency_id'];
$period = $journal['date']->format($this->carbonFormat); $period = $journal['date']->format($this->carbonFormat);
$this->data[$currencyId][$period] ??= [ $this->data[$currencyId][$period] ??= [
'period' => $period, 'period' => $period,
'spent' => '0', 'spent' => '0',

View File

@@ -47,14 +47,15 @@ trait CleansChartData
* @var array $array * @var array $array
*/ */
foreach ($data as $index => $array) { foreach ($data as $index => $array) {
$array = $this->cleanSingleArray($index, $array); $array = $this->cleanSingleArray($index, $array);
$return[] = $array; $return[] = $array;
} }
return $return; return $return;
} }
private function cleanSingleArray(mixed $index, array $array): array { private function cleanSingleArray(mixed $index, array $array): array
{
if (array_key_exists('currency_id', $array)) { if (array_key_exists('currency_id', $array)) {
$array['currency_id'] = (string)$array['currency_id']; $array['currency_id'] = (string)$array['currency_id'];
} }
@@ -62,14 +63,15 @@ trait CleansChartData
$array['primary_currency_id'] = (string)$array['primary_currency_id']; $array['primary_currency_id'] = (string)$array['primary_currency_id'];
} }
$required = [ $required = [
'start_date', 'end_date', 'period', 'yAxisID','type','entries','pc_entries', 'start_date', 'end_date', 'period', 'yAxisID', 'type', 'entries', 'pc_entries',
'currency_id', 'primary_currency_id' 'currency_id', 'primary_currency_id',
]; ];
foreach ($required as $field) { foreach ($required as $field) {
if (!array_key_exists($field, $array)) { if (!array_key_exists($field, $array)) {
throw new FireflyException(sprintf('Data-set "%s" is missing the "%s"-variable.', $index, $field)); throw new FireflyException(sprintf('Data-set "%s" is missing the "%s"-variable.', $index, $field));
} }
} }
return $array; return $array;
} }
} }

38
composer.lock generated
View File

@@ -1878,16 +1878,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v12.23.1", "version": "v12.24.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "2a0e9331a0db904236143fe915c281ff4be274a3" "reference": "6dcf2c46da23d159f35d6246234953a74b740d83"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/2a0e9331a0db904236143fe915c281ff4be274a3", "url": "https://api.github.com/repos/laravel/framework/zipball/6dcf2c46da23d159f35d6246234953a74b740d83",
"reference": "2a0e9331a0db904236143fe915c281ff4be274a3", "reference": "6dcf2c46da23d159f35d6246234953a74b740d83",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1997,7 +1997,7 @@
"league/flysystem-read-only": "^3.25.1", "league/flysystem-read-only": "^3.25.1",
"league/flysystem-sftp-v3": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1",
"mockery/mockery": "^1.6.10", "mockery/mockery": "^1.6.10",
"orchestra/testbench-core": "^10.0.0", "orchestra/testbench-core": "^10.6.0",
"pda/pheanstalk": "^5.0.6|^7.0.0", "pda/pheanstalk": "^5.0.6|^7.0.0",
"php-http/discovery": "^1.15", "php-http/discovery": "^1.15",
"phpstan/phpstan": "^2.0", "phpstan/phpstan": "^2.0",
@@ -2091,7 +2091,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2025-08-12T17:35:05+00:00" "time": "2025-08-13T20:30:36+00:00"
}, },
{ {
"name": "laravel/passport", "name": "laravel/passport",
@@ -10987,16 +10987,16 @@
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v5.6.0", "version": "v5.6.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56" "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/221b0d0fdf1369c71047ad1d18bb5880017bbc56", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56", "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11015,7 +11015,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "5.0-dev" "dev-master": "5.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -11039,9 +11039,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nikic/PHP-Parser/issues", "issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.0" "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
}, },
"time": "2025-07-27T20:03:57+00:00" "time": "2025-08-13T20:13:15+00:00"
}, },
{ {
"name": "phar-io/manifest", "name": "phar-io/manifest",
@@ -11876,16 +11876,16 @@
}, },
{ {
"name": "rector/rector", "name": "rector/rector",
"version": "2.1.2", "version": "2.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/rectorphp/rector.git", "url": "https://github.com/rectorphp/rector.git",
"reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff" "reference": "dd430c869fddf4965049c8fd6f5ee49f155cfddf"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/40a71441dd73fa150a66102f5ca1364c44fc8fff", "url": "https://api.github.com/repos/rectorphp/rector/zipball/dd430c869fddf4965049c8fd6f5ee49f155cfddf",
"reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff", "reference": "dd430c869fddf4965049c8fd6f5ee49f155cfddf",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11924,7 +11924,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/rectorphp/rector/issues", "issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.1.2" "source": "https://github.com/rectorphp/rector/tree/2.1.3"
}, },
"funding": [ "funding": [
{ {
@@ -11932,7 +11932,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-07-17T19:30:06+00:00" "time": "2025-08-13T11:43:04+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",

View File

@@ -78,8 +78,8 @@ 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' => 'develop/2025-08-13', 'version' => 'develop/2025-08-15',
'build_time' => 1755064254, 'build_time' => 1755257739,
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 26, 'db_version' => 26,

188
package-lock.json generated
View File

@@ -53,22 +53,22 @@
} }
}, },
"node_modules/@babel/core": { "node_modules/@babel/core": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
"integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.0", "@babel/generator": "^7.28.3",
"@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.27.3", "@babel/helper-module-transforms": "^7.28.3",
"@babel/helpers": "^7.27.6", "@babel/helpers": "^7.28.3",
"@babel/parser": "^7.28.0", "@babel/parser": "^7.28.3",
"@babel/template": "^7.27.2", "@babel/template": "^7.27.2",
"@babel/traverse": "^7.28.0", "@babel/traverse": "^7.28.3",
"@babel/types": "^7.28.0", "@babel/types": "^7.28.2",
"convert-source-map": "^2.0.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"gensync": "^1.0.0-beta.2", "gensync": "^1.0.0-beta.2",
@@ -94,14 +94,14 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
"integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.28.0", "@babel/parser": "^7.28.3",
"@babel/types": "^7.28.0", "@babel/types": "^7.28.2",
"@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28", "@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2" "jsesc": "^3.0.2"
@@ -151,18 +151,18 @@
} }
}, },
"node_modules/@babel/helper-create-class-features-plugin": { "node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.27.1", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz",
"integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-annotate-as-pure": "^7.27.3",
"@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-member-expression-to-functions": "^7.27.1",
"@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1",
"@babel/helper-replace-supers": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1",
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
"@babel/traverse": "^7.27.1", "@babel/traverse": "^7.28.3",
"semver": "^6.3.1" "semver": "^6.3.1"
}, },
"engines": { "engines": {
@@ -266,15 +266,15 @@
} }
}, },
"node_modules/@babel/helper-module-transforms": { "node_modules/@babel/helper-module-transforms": {
"version": "7.27.3", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
"integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-module-imports": "^7.27.1", "@babel/helper-module-imports": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1",
"@babel/traverse": "^7.27.3" "@babel/traverse": "^7.28.3"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -387,24 +387,24 @@
} }
}, },
"node_modules/@babel/helper-wrap-function": { "node_modules/@babel/helper-wrap-function": {
"version": "7.27.1", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz",
"integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/template": "^7.27.1", "@babel/template": "^7.27.2",
"@babel/traverse": "^7.27.1", "@babel/traverse": "^7.28.3",
"@babel/types": "^7.27.1" "@babel/types": "^7.28.2"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.28.2", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz",
"integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -416,13 +416,13 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.28.0" "@babel/types": "^7.28.2"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -499,14 +499,14 @@
} }
}, },
"node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
"version": "7.27.1", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz",
"integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1",
"@babel/traverse": "^7.27.1" "@babel/traverse": "^7.28.3"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -726,13 +726,13 @@
} }
}, },
"node_modules/@babel/plugin-transform-class-static-block": { "node_modules/@babel/plugin-transform-class-static-block": {
"version": "7.27.1", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz",
"integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-create-class-features-plugin": "^7.28.3",
"@babel/helper-plugin-utils": "^7.27.1" "@babel/helper-plugin-utils": "^7.27.1"
}, },
"engines": { "engines": {
@@ -743,9 +743,9 @@
} }
}, },
"node_modules/@babel/plugin-transform-classes": { "node_modules/@babel/plugin-transform-classes": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.3.tgz",
"integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", "integrity": "sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -754,7 +754,7 @@
"@babel/helper-globals": "^7.28.0", "@babel/helper-globals": "^7.28.0",
"@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-replace-supers": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1",
"@babel/traverse": "^7.28.0" "@babel/traverse": "^7.28.3"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1284,9 +1284,9 @@
} }
}, },
"node_modules/@babel/plugin-transform-regenerator": { "node_modules/@babel/plugin-transform-regenerator": {
"version": "7.28.1", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.1.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.3.tgz",
"integrity": "sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg==", "integrity": "sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1333,9 +1333,9 @@
} }
}, },
"node_modules/@babel/plugin-transform-runtime": { "node_modules/@babel/plugin-transform-runtime": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz",
"integrity": "sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==", "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1512,9 +1512,9 @@
} }
}, },
"node_modules/@babel/preset-env": { "node_modules/@babel/preset-env": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz",
"integrity": "sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==", "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1526,7 +1526,7 @@
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3",
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
"@babel/plugin-syntax-import-assertions": "^7.27.1", "@babel/plugin-syntax-import-assertions": "^7.27.1",
"@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-import-attributes": "^7.27.1",
@@ -1537,8 +1537,8 @@
"@babel/plugin-transform-block-scoped-functions": "^7.27.1", "@babel/plugin-transform-block-scoped-functions": "^7.27.1",
"@babel/plugin-transform-block-scoping": "^7.28.0", "@babel/plugin-transform-block-scoping": "^7.28.0",
"@babel/plugin-transform-class-properties": "^7.27.1", "@babel/plugin-transform-class-properties": "^7.27.1",
"@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-class-static-block": "^7.28.3",
"@babel/plugin-transform-classes": "^7.28.0", "@babel/plugin-transform-classes": "^7.28.3",
"@babel/plugin-transform-computed-properties": "^7.27.1", "@babel/plugin-transform-computed-properties": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.28.0", "@babel/plugin-transform-destructuring": "^7.28.0",
"@babel/plugin-transform-dotall-regex": "^7.27.1", "@babel/plugin-transform-dotall-regex": "^7.27.1",
@@ -1570,7 +1570,7 @@
"@babel/plugin-transform-private-methods": "^7.27.1", "@babel/plugin-transform-private-methods": "^7.27.1",
"@babel/plugin-transform-private-property-in-object": "^7.27.1", "@babel/plugin-transform-private-property-in-object": "^7.27.1",
"@babel/plugin-transform-property-literals": "^7.27.1", "@babel/plugin-transform-property-literals": "^7.27.1",
"@babel/plugin-transform-regenerator": "^7.28.0", "@babel/plugin-transform-regenerator": "^7.28.3",
"@babel/plugin-transform-regexp-modifiers": "^7.27.1", "@babel/plugin-transform-regexp-modifiers": "^7.27.1",
"@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-reserved-words": "^7.27.1",
"@babel/plugin-transform-shorthand-properties": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1",
@@ -1622,9 +1622,9 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.28.2", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz",
"integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1646,18 +1646,18 @@
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.28.0", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
"integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.0", "@babel/generator": "^7.28.3",
"@babel/helper-globals": "^7.28.0", "@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.0", "@babel/parser": "^7.28.3",
"@babel/template": "^7.27.2", "@babel/template": "^7.27.2",
"@babel/types": "^7.28.0", "@babel/types": "^7.28.2",
"debug": "^4.3.1" "debug": "^4.3.1"
}, },
"engines": { "engines": {
@@ -3148,9 +3148,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.2.1", "version": "24.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
"integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4486,9 +4486,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001734", "version": "1.0.30001735",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz",
"integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==", "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -5700,9 +5700,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.200", "version": "1.5.202",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.202.tgz",
"integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==", "integrity": "sha512-NxbYjRmiHcHXV1Ws3fWUW+SLb62isauajk45LUJ/HgIOkUA7jLZu/X2Iif+X9FBNK8QkF9Zb4Q2mcwXCcY30mg==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -7052,9 +7052,9 @@
} }
}, },
"node_modules/i18next": { "node_modules/i18next": {
"version": "25.3.4", "version": "25.3.6",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.3.4.tgz", "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.3.6.tgz",
"integrity": "sha512-AHklEYFLiRRxW1Cb6zE9lfnEtYvsydRC8nRS3RSKGX3zCqZ8nLZwMaUsrb80YuccPNv2RNokDL8LkTNnp+6mDw==", "integrity": "sha512-dThZ0CTCM3sUG/qS0ZtQYZQcUI6DtBN8yBHK+SKEqihPcEYmjVWh/YJ4luic73Iq6Uxhp6q7LJJntRK5+1t7jQ==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -11170,11 +11170,14 @@
} }
}, },
"node_modules/tinyglobby/node_modules/fdir": { "node_modules/tinyglobby/node_modules/fdir": {
"version": "6.4.6", "version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": { "peerDependencies": {
"picomatch": "^3 || ^4" "picomatch": "^3 || ^4"
}, },
@@ -11617,11 +11620,14 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/vite/node_modules/fdir": { "node_modules/vite/node_modules/fdir": {
"version": "6.4.6", "version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": { "peerDependencies": {
"picomatch": "^3 || ^4" "picomatch": "^3 || ^4"
}, },
@@ -11844,9 +11850,9 @@
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.101.1", "version": "5.101.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.2.tgz",
"integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==", "integrity": "sha512-4JLXU0tD6OZNVqlwzm3HGEhAHufSiyv+skb7q0d2367VDMzrU1Q/ZeepvkcHH0rZie6uqEtTQQe0OEOOluH3Mg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

0
public/v1/js/.gitkeep Executable file → Normal file
View File

View File

@@ -102,7 +102,7 @@
"profile_oauth_client_secret_title": "Secret du client", "profile_oauth_client_secret_title": "Secret du client",
"profile_oauth_client_secret_expl": "Voici votre nouveau secret de client. C'est la seule fois qu'il sera affich\u00e9, donc ne le perdez pas ! Vous pouvez maintenant utiliser ce secret pour faire des requ\u00eates d'API.", "profile_oauth_client_secret_expl": "Voici votre nouveau secret de client. C'est la seule fois qu'il sera affich\u00e9, donc ne le perdez pas ! Vous pouvez maintenant utiliser ce secret pour faire des requ\u00eates d'API.",
"profile_oauth_confidential": "Confidentiel", "profile_oauth_confidential": "Confidentiel",
"profile_oauth_confidential_help": "Require the client to authenticate with a secret. Confidential clients can hold credentials in a secure way without exposing them to unauthorized parties. Public applications, such as native desktop or JavaScript SPA applications, are unable to hold secrets securely.", "profile_oauth_confidential_help": "Exiger que le client s'authentifie avec un secret. Les clients confidentiels peuvent d\u00e9tenir des informations d'identification de mani\u00e8re s\u00e9curis\u00e9e sans les exposer \u00e0 des tiers non autoris\u00e9s. Les applications publiques, telles que les applications de bureau natif ou les SPA JavaScript, ne peuvent pas tenir des secrets en toute s\u00e9curit\u00e9.",
"multi_account_warning_unknown": "Selon le type d'op\u00e9ration que vous cr\u00e9ez, le(s) compte(s) source et\/ou de destination des s\u00e9parations suivantes peuvent \u00eatre remplac\u00e9s par celui de la premi\u00e8re s\u00e9paration de l'op\u00e9ration.", "multi_account_warning_unknown": "Selon le type d'op\u00e9ration que vous cr\u00e9ez, le(s) compte(s) source et\/ou de destination des s\u00e9parations suivantes peuvent \u00eatre remplac\u00e9s par celui de la premi\u00e8re s\u00e9paration de l'op\u00e9ration.",
"multi_account_warning_withdrawal": "Gardez en t\u00eate que le compte source des s\u00e9parations suivantes peut \u00eatre remplac\u00e9 par celui de la premi\u00e8re s\u00e9paration de la d\u00e9pense.", "multi_account_warning_withdrawal": "Gardez en t\u00eate que le compte source des s\u00e9parations suivantes peut \u00eatre remplac\u00e9 par celui de la premi\u00e8re s\u00e9paration de la d\u00e9pense.",
"multi_account_warning_deposit": "Gardez en t\u00eate que le compte de destination des s\u00e9parations suivantes peut \u00eatre remplac\u00e9 par celui de la premi\u00e8re s\u00e9paration du d\u00e9p\u00f4t.", "multi_account_warning_deposit": "Gardez en t\u00eate que le compte de destination des s\u00e9parations suivantes peut \u00eatre remplac\u00e9 par celui de la premi\u00e8re s\u00e9paration du d\u00e9p\u00f4t.",