mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-05-04 13:16:31 +00:00
Compare commits
31 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b9bbc9d6a | ||
|
|
f24f535d39 | ||
|
|
4ac7fec5f6 | ||
|
|
b6759c3fa0 | ||
|
|
4a83b1e3e5 | ||
|
|
4b701dfc4c | ||
|
|
b2997d0a5a | ||
|
|
fd8722e401 | ||
|
|
e46153330a | ||
|
|
525f0c752a | ||
|
|
13e4160e85 | ||
|
|
7806d63f91 | ||
|
|
8c620b6536 | ||
|
|
e47ce30579 | ||
|
|
7e6eadc047 | ||
|
|
dae4f6f351 | ||
|
|
8c8af51bc4 | ||
|
|
a5e1cba39c | ||
|
|
96d56ad723 | ||
|
|
e4b1c3045e | ||
|
|
e974594fe3 | ||
|
|
c93a2dc23a | ||
|
|
639efee78a | ||
|
|
eb4971fec6 | ||
|
|
0c63a3380d | ||
|
|
edd30b2d42 | ||
|
|
a4f6c2b748 | ||
|
|
5fc90e0f76 | ||
|
|
e8ab7d8a93 | ||
|
|
e73d04bc0f | ||
|
|
c0eca4298a |
36
.ci/php-cs-fixer/composer.lock
generated
36
.ci/php-cs-fixer/composer.lock
generated
@@ -1334,16 +1334,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7"
|
||||
"reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/5b66d385dc58f69652e56f78a4184615e3f2b7f7",
|
||||
"reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/7113778e2e91f4709cb3194a75dfa9c0d028d94d",
|
||||
"reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1400,7 +1400,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/console/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1420,7 +1420,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-29T15:02:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -1491,16 +1491,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6"
|
||||
"reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f662acc6ab22a3d6d716dcb44c381c6002940df6",
|
||||
"reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0c3c1a17604c4dbbec4b93fe162c538482096e1f",
|
||||
"reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1552,7 +1552,7 @@
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1572,7 +1572,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-18T13:51:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
@@ -1652,16 +1652,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "66b769ae743ce2d13e435528fbef4af03d623e5a"
|
||||
"reference": "d1ec4543d5c6c2dac78503c2fae5ea0b3608ce40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/66b769ae743ce2d13e435528fbef4af03d623e5a",
|
||||
"reference": "66b769ae743ce2d13e435528fbef4af03d623e5a",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d1ec4543d5c6c2dac78503c2fae5ea0b3608ce40",
|
||||
"reference": "d1ec4543d5c6c2dac78503c2fae5ea0b3608ce40",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1698,7 +1698,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1718,7 +1718,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-18T13:51:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/fr.yml
vendored
8
.github/ISSUE_TEMPLATE/fr.yml
vendored
@@ -12,6 +12,14 @@ body:
|
||||
required: true
|
||||
- label: I've used [the search](https://github.com/firefly-iii/firefly-iii/issues?q=is%3Aissue) and this has not been requested before.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Use of AI
|
||||
description: AI agents like Claude and CoPilot are not reliable tools. Do not use them.
|
||||
options:
|
||||
- label: I'm a real person and wrote this bug without assistance from AI.
|
||||
required: true
|
||||
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
2
.github/security.md
vendored
2
.github/security.md
vendored
@@ -5,7 +5,7 @@ disclosure and response policy to ensure that critical issues are responsibly ha
|
||||
|
||||
## Supported versions
|
||||
|
||||
Only the latest Firefly III release is maintained. Applicable fixes, including security fixes, will not backported to
|
||||
Only the latest Firefly III release is maintained. Applicable fixes, including security fixes, will not be backported to
|
||||
older release branches. Please refer to [releases.md](https://github.com/firefly-iii/firefly-iii/blob/main/releases.md) for details.
|
||||
|
||||
## Reporting a vulnerability - private disclosure process
|
||||
|
||||
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
@@ -99,11 +99,6 @@ jobs:
|
||||
env:
|
||||
FIREFLY_III_ROOT: /github/workspace
|
||||
GH_TOKEN: ''
|
||||
- name: Setup Mago
|
||||
uses: nhedger/setup-mago@v1
|
||||
with:
|
||||
version: "latest"
|
||||
working-directory: "."
|
||||
- name: Run CI
|
||||
run: |
|
||||
cp .env.example .env
|
||||
@@ -113,17 +108,19 @@ jobs:
|
||||
|
||||
# format code.
|
||||
echo "Will now run Mago Format"
|
||||
mago format
|
||||
./vendor/bin/mago format
|
||||
sudo chown -R runner:docker resources/lang
|
||||
echo "Will now run PHPCS"
|
||||
.ci/phpcs.sh
|
||||
|
||||
# lint and check
|
||||
echo "Will now run Mago Lint"
|
||||
mago lint
|
||||
./vendor/bin/mago lint
|
||||
echo "Will now run PHPstan"
|
||||
.ci/phpstan.sh
|
||||
rm .env
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Crowdin action
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
|
||||
@@ -179,9 +179,9 @@ final class CategoryController extends Controller
|
||||
|
||||
// order by amount
|
||||
usort($return, static fn (array $a, array $b): int => ((float) $a['entries']['spent'] + (float) $a['entries']['earned'])
|
||||
< ((float) $b['entries']['spent'] + (float) $b['entries']['earned'])
|
||||
? 1
|
||||
: -1);
|
||||
< ((float) $b['entries']['spent'] + (float) $b['entries']['earned'])
|
||||
? 1
|
||||
: -1);
|
||||
|
||||
return response()->json($this->clean($return));
|
||||
}
|
||||
|
||||
@@ -158,10 +158,7 @@ final class TagController extends Controller
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd(
|
||||
(string) $response[$foreignKey]['difference'],
|
||||
Steam::positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,10 +155,7 @@ final class TagController extends Controller
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd(
|
||||
(string) $response[$foreignKey]['difference'],
|
||||
Steam::positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +59,9 @@ final class DestroyController extends Controller
|
||||
|
||||
public function destroy(DestroyRequest $request, TransactionCurrency $from, TransactionCurrency $to): JsonResponse
|
||||
{
|
||||
$first = Carbon::create(1970, 1, 1);
|
||||
$this->repository->deleteRates($from, $to);
|
||||
event(new DestroyedCurrencyExchangeRate($from, $to, $this->validateUserGroup($request)));
|
||||
event(new DestroyedCurrencyExchangeRate($from, $to, $this->validateUserGroup($request), $first));
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@@ -74,7 +75,7 @@ final class DestroyController extends Controller
|
||||
if (!$exchangeRate instanceof CurrencyExchangeRate) {
|
||||
throw new FireflyException('Bla');
|
||||
}
|
||||
event(new DestroyedCurrencyExchangeRate($from, $to, $this->validateUserGroup($request)));
|
||||
event(new DestroyedCurrencyExchangeRate($from, $to, $this->validateUserGroup($request), $date));
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@@ -85,7 +86,7 @@ final class DestroyController extends Controller
|
||||
$to = $exchangeRate->toCurrency;
|
||||
$this->repository->deleteRate($exchangeRate);
|
||||
|
||||
event(new DestroyedCurrencyExchangeRate($from, $to, $this->validateUserGroup($request)));
|
||||
event(new DestroyedCurrencyExchangeRate($from, $to, $this->validateUserGroup($request), $exchangeRate->date));
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,9 @@ final class StoreController extends Controller
|
||||
$transactionGroup = $this->groupRepository->store($data);
|
||||
} catch (DuplicateTransactionException $e) {
|
||||
Log::warning('Caught a duplicate transaction. Return error message.');
|
||||
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], [
|
||||
'transactions.0.description' => new IsDuplicateTransaction(),
|
||||
]);
|
||||
|
||||
throw new ValidationException($validator);
|
||||
} catch (FireflyException $e) {
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\CurrencyExchangeRate;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
@@ -37,7 +38,8 @@ class DestroyedCurrencyExchangeRate extends Event
|
||||
public function __construct(
|
||||
public TransactionCurrency $from,
|
||||
public TransactionCurrency $to,
|
||||
public UserGroup $userGroup
|
||||
public UserGroup $userGroup,
|
||||
public Carbon $date
|
||||
) {
|
||||
Log::debug(sprintf('DestroyedCurrencyExchangeRate(%s, %s) Event', $from->code, $to->code));
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class PiggyBankObserver
|
||||
}
|
||||
|
||||
$params = new ConversionParameters();
|
||||
$params->user = $piggyBank->accounts()->first()?->user;
|
||||
$params->user = $piggyBank->accounts()->first()->user;
|
||||
$params->model = $piggyBank;
|
||||
$params->originalCurrency = $piggyBank->transactionCurrency;
|
||||
$params->amountField = 'target_amount';
|
||||
|
||||
@@ -40,8 +40,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
/**
|
||||
* ReportHelper constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
public function __construct(/** @var BudgetRepositoryInterface The budget repository */
|
||||
protected BudgetRepositoryInterface $budgetRepository
|
||||
) {}
|
||||
|
||||
|
||||
@@ -255,10 +255,7 @@ final class IndexController extends Controller
|
||||
if (count($bill['paid_dates']) < count($bill['pay_dates'])) {
|
||||
$count = count($bill['pay_dates']) - count($bill['paid_dates']);
|
||||
if ($count > 0) {
|
||||
$avg = bcdiv(
|
||||
bcadd((string) $bill['amount_min'], (string) $bill['amount_max']),
|
||||
'2'
|
||||
);
|
||||
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
|
||||
$avg = bcmul($avg, (string) $count);
|
||||
$sums[$groupOrder][$currencyId]['total_left_to_pay'] = bcadd($sums[$groupOrder][$currencyId]['total_left_to_pay'], $avg);
|
||||
Log::debug(
|
||||
|
||||
@@ -198,13 +198,7 @@ final class BudgetLimitController extends Controller
|
||||
if ($request->expectsJson()) {
|
||||
$array = $limit->toArray();
|
||||
// add some extra metadata:
|
||||
$spentArr = $this->opsRepository->sumExpenses(
|
||||
$limit->start_date,
|
||||
$limit->end_date,
|
||||
null,
|
||||
new Collection()->push($budget),
|
||||
$currency
|
||||
);
|
||||
$spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
|
||||
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
|
||||
$array['left_formatted'] = Amount::formatAnything($limit->transactionCurrency, bcadd($array['spent'], (string) $array['amount']));
|
||||
$array['amount_formatted'] = Amount::formatAnything($limit->transactionCurrency, $limit['amount']);
|
||||
|
||||
@@ -245,7 +245,13 @@ final class IndexController extends Controller
|
||||
$inPast = $limitPeriod->startsBefore(now()) && $limitPeriod->endsBefore(now());
|
||||
$currency = $limit->transactionCurrency ?? $primaryCurrency;
|
||||
$amount = Steam::bcround($limit->amount, $currency->decimal_places);
|
||||
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
|
||||
$spent = $this->opsRepository->sumExpenses(
|
||||
$limit->start_date,
|
||||
$limit->end_date,
|
||||
null,
|
||||
new Collection()->push($budget),
|
||||
$currency
|
||||
);
|
||||
$spentAmount = $spent[$currency->id]['sum'] ?? '0';
|
||||
$array['budgeted'][] = [
|
||||
'id' => $limit->id,
|
||||
@@ -283,10 +289,7 @@ final class IndexController extends Controller
|
||||
|
||||
if (array_key_exists($currency->id, $spentArr) && array_key_exists('sum', $spentArr[$currency->id])) {
|
||||
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
|
||||
$array['spent'][$currency->id]['spent_outside'] = bcmul(
|
||||
bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']),
|
||||
'-1'
|
||||
);
|
||||
$array['spent'][$currency->id]['spent_outside'] = bcmul(bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']), '-1');
|
||||
$array['spent'][$currency->id]['currency_id'] = $currency->id;
|
||||
$array['spent'][$currency->id]['currency_symbol'] = $currency->symbol;
|
||||
$array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places;
|
||||
|
||||
@@ -589,7 +589,6 @@ final class AccountController extends Controller
|
||||
Log::debug('End of chart loop.');
|
||||
// second loop (yes) to create nice array with info! Yay!
|
||||
$chartData = [];
|
||||
|
||||
foreach ($return as $key => $info) {
|
||||
if ('balance' !== $key && 'pc_balance' !== $key) {
|
||||
// assume it's a currency:
|
||||
@@ -608,6 +607,11 @@ final class AccountController extends Controller
|
||||
$info['currency_code'] = $this->primaryCurrency->code;
|
||||
$info['label'] = sprintf('%s (%s) (%s)', $account->name, (string) trans('firefly.sum'), $this->primaryCurrency->symbol);
|
||||
}
|
||||
// do not add pc_balance to the array if the account is in the primary currency anyway,
|
||||
// and it has no currency balances.
|
||||
if (2 === count(array_keys($return)) && 'pc_balance' === $key && $accountCurrency->id === $this->primaryCurrency->id) {
|
||||
continue;
|
||||
}
|
||||
$chartData[] = $info;
|
||||
}
|
||||
|
||||
|
||||
@@ -539,13 +539,7 @@ final class BudgetController extends Controller
|
||||
}
|
||||
|
||||
// get spent amount in this period for this currency.
|
||||
$sum = $this->opsRepository->sumExpenses(
|
||||
$currentStart,
|
||||
$currentEnd,
|
||||
$accounts,
|
||||
new Collection()->push($budget),
|
||||
$currency
|
||||
);
|
||||
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency);
|
||||
$amount = Steam::positive($sum[$currency->id]['sum'] ?? '0');
|
||||
$chartData[0]['entries'][$title] = Steam::bcround($amount, $currency->decimal_places);
|
||||
|
||||
|
||||
@@ -40,10 +40,9 @@ class Authenticate
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*/
|
||||
public function __construct(
|
||||
/**
|
||||
* The authentication factory instance.
|
||||
*/
|
||||
public function __construct(/**
|
||||
* The authentication factory instance.
|
||||
*/
|
||||
protected Auth $auth
|
||||
) {}
|
||||
|
||||
|
||||
@@ -42,10 +42,9 @@ class Binder
|
||||
/**
|
||||
* Binder constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
/**
|
||||
* The authentication factory instance.
|
||||
*/
|
||||
public function __construct(/**
|
||||
* The authentication factory instance.
|
||||
*/
|
||||
protected Auth $auth
|
||||
) {
|
||||
$this->binders = Domain::getBindables();
|
||||
|
||||
@@ -122,13 +122,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
|
||||
// if has one, calculate expenses and use that as a base.
|
||||
$repository = app(OperationsRepositoryInterface::class);
|
||||
$repository->setUser($autoBudget->budget->user);
|
||||
$spent = $repository->sumExpenses(
|
||||
$previousStart,
|
||||
$previousEnd,
|
||||
null,
|
||||
new Collection()->push($autoBudget->budget),
|
||||
$autoBudget->transactionCurrency
|
||||
);
|
||||
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
|
||||
$currencyId = $autoBudget->transaction_currency_id;
|
||||
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
|
||||
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
|
||||
@@ -218,13 +212,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
|
||||
// if has one, calculate expenses and use that as a base.
|
||||
$repository = app(OperationsRepositoryInterface::class);
|
||||
$repository->setUser($autoBudget->budget->user);
|
||||
$spent = $repository->sumExpenses(
|
||||
$previousStart,
|
||||
$previousEnd,
|
||||
null,
|
||||
new Collection()->push($autoBudget->budget),
|
||||
$autoBudget->transactionCurrency
|
||||
);
|
||||
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
|
||||
$currencyId = $autoBudget->transaction_currency_id;
|
||||
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
|
||||
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Listeners\Model\CurrencyExchangeRate;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\Model\CurrencyExchangeRate\CreatedCurrencyExchangeRate;
|
||||
use FireflyIII\Events\Model\CurrencyExchangeRate\DestroyedCurrencyExchangeRate;
|
||||
use FireflyIII\Events\Model\CurrencyExchangeRate\UpdatedCurrencyExchangeRate;
|
||||
@@ -42,20 +43,22 @@ class ProcessesExchangeRates
|
||||
Preferences::mark();
|
||||
Cache::clear();
|
||||
if ($event instanceof DestroyedCurrencyExchangeRate) {
|
||||
$this->handleCurrency($event->userGroup, $event->from);
|
||||
$this->handleCurrency($event->userGroup, $event->to);
|
||||
$this->handleCurrency($event->userGroup, $event->from, $event->date);
|
||||
$this->handleCurrency($event->userGroup, $event->to, $event->date);
|
||||
|
||||
return;
|
||||
}
|
||||
$this->handleCurrency($event->rate->userGroup, $event->rate->fromCurrency);
|
||||
$this->handleCurrency($event->rate->userGroup, $event->rate->toCurrency);
|
||||
$this->handleCurrency($event->rate->userGroup, $event->rate->fromCurrency, $event->rate->date);
|
||||
$this->handleCurrency($event->rate->userGroup, $event->rate->toCurrency, $event->rate->date);
|
||||
}
|
||||
|
||||
private function handleCurrency(UserGroup $userGroup, TransactionCurrency $currency): void
|
||||
private function handleCurrency(UserGroup $userGroup, TransactionCurrency $currency, Carbon $date): void
|
||||
{
|
||||
$calculator = new PrimaryAmountRecalculationService();
|
||||
$calculator->setDate($date);
|
||||
if (Amount::convertToPrimary()) {
|
||||
Log::debug(sprintf('Will now convert amounts to primary currency for currency %s.', $currency->code));
|
||||
$date->startOfDay();
|
||||
Log::debug(sprintf('Will now convert amounts to primary currency for currency %s after %s.', $currency->code, $date->format('Y-m-d')));
|
||||
|
||||
$calculator->recalculateForGroupAndCurrency($userGroup, $currency);
|
||||
// $calculator->recalculateForGroup($userGroup);
|
||||
|
||||
@@ -385,9 +385,9 @@ trait ModifiesPiggyBanks
|
||||
$piggyBank->target_date = $data['target_date'];
|
||||
$piggyBank->target_date_tz = $data['target_date']?->format('e');
|
||||
}
|
||||
if (array_key_exists('start_date', $data)) {
|
||||
if (array_key_exists('start_date', $data) && '' !== $data['start_date']) {
|
||||
$piggyBank->start_date = $data['start_date'];
|
||||
$piggyBank->start_date_tz = $data['target_date']?->format('e');
|
||||
$piggyBank->start_date_tz = $data['start_date']?->format('e');
|
||||
}
|
||||
$piggyBank->save();
|
||||
|
||||
|
||||
@@ -342,33 +342,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
||||
return $piggyBank->piggyBankRepetitions()->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the suggested amount the user should save per month, or "".
|
||||
*/
|
||||
public function getSuggestedMonthlyAmount(PiggyBank $piggyBank): string
|
||||
{
|
||||
$savePerMonth = '0';
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank);
|
||||
if (null !== $piggyBank->target_date && $currentAmount < $piggyBank->target_amount) {
|
||||
$now = today(config('app.timezone'));
|
||||
$startDate = null !== $piggyBank->start_date && $piggyBank->start_date->gte($now) ? $piggyBank->start_date : $now;
|
||||
$diffInMonths = (int) $startDate->diffInMonths($piggyBank->target_date);
|
||||
$remainingAmount = bcsub((string) $piggyBank->target_amount, $currentAmount);
|
||||
|
||||
// more than 1 month to go and still need money to save:
|
||||
if ($diffInMonths > 0 && 1 === bccomp($remainingAmount, '0')) {
|
||||
$savePerMonth = bcdiv($remainingAmount, (string) $diffInMonths);
|
||||
}
|
||||
|
||||
// less than 1 month to go but still need money to save:
|
||||
if (0 === $diffInMonths && 1 === bccomp($remainingAmount, '0')) {
|
||||
$savePerMonth = $remainingAmount;
|
||||
}
|
||||
}
|
||||
|
||||
return $savePerMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get for piggy account what is left to put in piggies.
|
||||
*/
|
||||
|
||||
@@ -111,11 +111,6 @@ interface PiggyBankRepositoryInterface
|
||||
|
||||
public function getRepetition(PiggyBank $piggyBank, bool $overrule = false): ?PiggyBankRepetition;
|
||||
|
||||
/**
|
||||
* Returns the suggested amount the user should save per month, or "".
|
||||
*/
|
||||
public function getSuggestedMonthlyAmount(PiggyBank $piggyBank): string;
|
||||
|
||||
/**
|
||||
* Get for piggy account what is left to put in piggies.
|
||||
*/
|
||||
|
||||
@@ -166,7 +166,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
$set = TransactionJournalLink::where(static function (Builder $q) use ($journals): void {
|
||||
$q->whereIn('source_id', $journals);
|
||||
$q->orWhereIn('destination_id', $journals);
|
||||
})->with(['source', 'destination', 'source.transactions'])->leftJoin('link_types', 'link_types.id', '=', 'journal_links.link_type_id')->get([
|
||||
})->with(['source', 'notes', 'destination', 'source.transactions'])->leftJoin('link_types', 'link_types.id', '=', 'journal_links.link_type_id')->get([
|
||||
'journal_links.*',
|
||||
'link_types.inward',
|
||||
'link_types.outward',
|
||||
@@ -191,6 +191,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
'editable' => 1 === (int) $entry->editable,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
'notes' => null === $entry->notes->first() ? '' : $entry->notes->first()->text,
|
||||
];
|
||||
}
|
||||
if ($journalId === $entry->destination_id) {
|
||||
@@ -204,6 +205,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
'editable' => 1 === (int) $entry->editable,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
'notes' => null === $entry->notes->first() ? '' : $entry->notes->first()->text,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Internal\Recalculate;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\Model\Account\UpdatedExistingAccount;
|
||||
use FireflyIII\Handlers\Observer\TransactionObserver;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -52,6 +53,13 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PrimaryAmountRecalculationService
|
||||
{
|
||||
private Carbon $date;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->date = Carbon::createFromDate(1970, 1, 1);
|
||||
}
|
||||
|
||||
public function recalculate(): void
|
||||
{
|
||||
if (false === FireflyConfig::get('enable_exchange_rates', config('cer.enabled'))->data) {
|
||||
@@ -106,12 +114,18 @@ class PrimaryAmountRecalculationService
|
||||
$this->calculateTransactionsForCurrency($userGroup, $currency, $limitCurrency);
|
||||
}
|
||||
|
||||
public function setDate(?Carbon $date): void
|
||||
{
|
||||
$this->date = $date;
|
||||
}
|
||||
|
||||
private function calculateTransactions(UserGroup $userGroup, TransactionCurrency $currency): void
|
||||
{
|
||||
// custom query because of the potential size of this update.
|
||||
$set = DB::table('transactions')
|
||||
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.user_group_id', $userGroup->id)
|
||||
->where('transaction_journals.date', '>=', $this->date)
|
||||
->where(static function (DatabaseBuilder $q1) use ($currency): void {
|
||||
$q1->where(static function (DatabaseBuilder $q2) use ($currency): void {
|
||||
$q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id');
|
||||
@@ -147,6 +161,7 @@ class PrimaryAmountRecalculationService
|
||||
$set = DB::table('transactions')
|
||||
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.user_group_id', $userGroup->id)
|
||||
->where('transaction_journals.date', '>=', $this->date)
|
||||
->where(static function (DatabaseBuilder $q1) use ($currency): void {
|
||||
$q1->where(static function (DatabaseBuilder $q2) use ($currency): void {
|
||||
$q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id');
|
||||
@@ -279,7 +294,15 @@ class PrimaryAmountRecalculationService
|
||||
|
||||
private function recalculateBudgetLimits(Budget $budget, TransactionCurrency $currency): void
|
||||
{
|
||||
$set = $budget->budgetlimits()->where('transaction_currency_id', '!=', $currency->id)->get();
|
||||
$set = $budget
|
||||
->budgetlimits()
|
||||
->where(function (EloquentBuilder $q): void {
|
||||
$q->where('budget_limits.start_date', '>=', $this->date);
|
||||
$q->orWhere('budget_limits.end_date', '<=', $this->date);
|
||||
})
|
||||
->where('transaction_currency_id', '!=', $currency->id)
|
||||
->get()
|
||||
;
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($set as $limit) {
|
||||
@@ -436,6 +459,7 @@ class PrimaryAmountRecalculationService
|
||||
$success = DB::table('transactions')
|
||||
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.user_group_id', $userGroup->id)
|
||||
->where('transaction_journals.date', '>=', $this->date)
|
||||
->where(static function (Builder $q): void {
|
||||
$q->whereNotNull('native_amount')->orWhereNotNull('native_foreign_amount');
|
||||
})
|
||||
|
||||
@@ -741,12 +741,12 @@ class JournalUpdateService
|
||||
if (null === $group || null === $this->transactionJournal) {
|
||||
return;
|
||||
}
|
||||
if (0 === bccomp($source->foreign_amount, $foreignAmount)) {
|
||||
if (0 === bccomp(Steam::positive($originalSourceAmount), Steam::positive($foreignAmount))) {
|
||||
Log::debug('Amount was not actually changed, return.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('Amount was changed, needs audit log entry.');
|
||||
Log::debug(sprintf('Amount was changed (%s -> %s), needs audit log entry.', $originalSourceAmount, $foreignAmount));
|
||||
$transfer = TransactionTypeEnum::TRANSFER->value === $this->transactionJournal->transactionType->type;
|
||||
// $withdrawal = TransactionTypeEnum::WITHDRAWAL->value === $this->transactionJournal->transactionType->type;
|
||||
$deposit = TransactionTypeEnum::DEPOSIT->value === $this->transactionJournal->transactionType->type;
|
||||
|
||||
@@ -222,14 +222,7 @@ trait AugumentData
|
||||
$currentEnd->addMonth();
|
||||
}
|
||||
// primary currency amount.
|
||||
$expenses = $opsRepository->sumExpenses(
|
||||
$currentStart,
|
||||
$currentEnd,
|
||||
null,
|
||||
$budgetCollection,
|
||||
$entry->transactionCurrency,
|
||||
$this->convertToPrimary
|
||||
);
|
||||
$expenses = $opsRepository->sumExpenses($currentStart, $currentEnd, null, $budgetCollection, $entry->transactionCurrency, $this->convertToPrimary);
|
||||
$spent = $expenses[$currency->id]['sum'] ?? '0';
|
||||
$entry->pc_spent = $spent;
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// get suggested per month.
|
||||
|
||||
$meta['save_per_month'] = Steam::bcround(
|
||||
$this->getSuggestedMonthlyAmount($this->date, $item->target_date, $meta['target_amount'], $meta['current_amount']),
|
||||
$currency->decimal_places
|
||||
@@ -301,23 +302,21 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
if (null === $targetAmount || !$targetDate instanceof Carbon || !$startDate instanceof Carbon) {
|
||||
return '0';
|
||||
}
|
||||
$savePerMonth = '0';
|
||||
if (1 === bccomp($targetAmount, $currentAmount)) {
|
||||
$now = today(config('app.timezone'));
|
||||
$diffInMonths = (int) $startDate->diffInMonths($targetDate);
|
||||
$diffInMonths = ceil($startDate->diffInMonths($targetDate));
|
||||
$remainingAmount = bcsub($targetAmount, $currentAmount);
|
||||
|
||||
// more than 1 month to go and still need money to save:
|
||||
if ($diffInMonths > 0 && 1 === bccomp($remainingAmount, '0')) {
|
||||
$savePerMonth = bcdiv($remainingAmount, (string) $diffInMonths);
|
||||
return bcdiv($remainingAmount, (string) $diffInMonths);
|
||||
}
|
||||
|
||||
// less than 1 month to go but still need money to save:
|
||||
if (0 === $diffInMonths && 1 === bccomp($remainingAmount, '0')) {
|
||||
$savePerMonth = $remainingAmount;
|
||||
if (1 === bccomp($remainingAmount, '0')) {
|
||||
return $remainingAmount;
|
||||
}
|
||||
}
|
||||
|
||||
return $savePerMonth;
|
||||
return '0';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,10 +354,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
|
||||
/** @var RecurrenceRepetition $repetition */
|
||||
foreach ($set as $repetition) {
|
||||
$recurrence = $this->collection
|
||||
->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)
|
||||
->first()
|
||||
;
|
||||
$recurrence = $this->collection->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)->first();
|
||||
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
|
||||
$recurrenceId = (int) $repetition->recurrence_id;
|
||||
$repId = (int) $repetition->id;
|
||||
|
||||
@@ -111,7 +111,9 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-ide-helper": "^3",
|
||||
"carthage-software/mago": "^1.24.0",
|
||||
"driftingly/rector-laravel": "^2.0",
|
||||
"ergebnis/phpstan-rules": "^2",
|
||||
"fakerphp/faker": "1.*",
|
||||
"filp/whoops": "2.*",
|
||||
"fruitcake/laravel-debugbar": "^4.0",
|
||||
@@ -124,8 +126,7 @@
|
||||
"phpstan/phpstan-strict-rules": "^2",
|
||||
"phpunit/phpunit": "^13",
|
||||
"rector/rector": "^2.3",
|
||||
"thecodingmachine/phpstan-safe-rule": "^1.4",
|
||||
"ergebnis/phpstan-rules": "^2"
|
||||
"thecodingmachine/phpstan-safe-rule": "^1.4"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-php54": "*",
|
||||
|
||||
313
composer.lock
generated
313
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "4f1f0dcde32d2f02333bd7af2cbc90eb",
|
||||
"content-hash": "7f960fa15bddd432267fb2bb9b730195",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -1879,16 +1879,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v13.6.0",
|
||||
"version": "v13.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "416a93ea9c53161e0d4b8a44045f447b65a7d2f1"
|
||||
"reference": "f13b85b2cce7ef5e8f3bcdf2b6c6364bbdedae0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/416a93ea9c53161e0d4b8a44045f447b65a7d2f1",
|
||||
"reference": "416a93ea9c53161e0d4b8a44045f447b65a7d2f1",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/f13b85b2cce7ef5e8f3bcdf2b6c6364bbdedae0b",
|
||||
"reference": "f13b85b2cce7ef5e8f3bcdf2b6c6364bbdedae0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1931,6 +1931,7 @@
|
||||
"symfony/mime": "^7.4.0 || ^8.0.0",
|
||||
"symfony/polyfill-php84": "^1.33",
|
||||
"symfony/polyfill-php85": "^1.33",
|
||||
"symfony/polyfill-php86": "^1.36",
|
||||
"symfony/process": "^7.4.5 || ^8.0.5",
|
||||
"symfony/routing": "^7.4.0 || ^8.0.0",
|
||||
"symfony/uid": "^7.4.0 || ^8.0.0",
|
||||
@@ -2098,7 +2099,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2026-04-21T13:32:11+00:00"
|
||||
"time": "2026-04-28T17:18:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
@@ -2236,16 +2237,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v2.0.12",
|
||||
"version": "v2.0.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/serializable-closure.git",
|
||||
"reference": "a6abb4e54f6fcd3138120b9ad497f0bd146f9919"
|
||||
"reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/a6abb4e54f6fcd3138120b9ad497f0bd146f9919",
|
||||
"reference": "a6abb4e54f6fcd3138120b9ad497f0bd146f9919",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b566ee0dd251f3c4078bed003a7ce015f5ea6dce",
|
||||
"reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2293,7 +2294,7 @@
|
||||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"time": "2026-04-14T13:33:34+00:00"
|
||||
"time": "2026-04-16T14:03:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/slack-notification-channel",
|
||||
@@ -6496,16 +6497,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/cache.git",
|
||||
"reference": "8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78"
|
||||
"reference": "2866a183cd942bbaa81e9fdbd1ef1ea902c5ee2d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78",
|
||||
"reference": "8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/2866a183cd942bbaa81e9fdbd1ef1ea902c5ee2d",
|
||||
"reference": "2866a183cd942bbaa81e9fdbd1ef1ea902c5ee2d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6572,7 +6573,7 @@
|
||||
"psr6"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/cache/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/cache/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6592,7 +6593,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:18:51+00:00"
|
||||
"time": "2026-04-29T15:02:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache-contracts",
|
||||
@@ -6749,16 +6750,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7"
|
||||
"reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/5b66d385dc58f69652e56f78a4184615e3f2b7f7",
|
||||
"reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/7113778e2e91f4709cb3194a75dfa9c0d028d94d",
|
||||
"reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6815,7 +6816,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/console/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6835,20 +6836,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-29T15:02:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "8db1c00226a94d8ab6aa89d9224eeee91e2ea2ed"
|
||||
"reference": "3665cfade90565430909b906394c73c8739e57d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/8db1c00226a94d8ab6aa89d9224eeee91e2ea2ed",
|
||||
"reference": "8db1c00226a94d8ab6aa89d9224eeee91e2ea2ed",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/3665cfade90565430909b906394c73c8739e57d0",
|
||||
"reference": "3665cfade90565430909b906394c73c8739e57d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6884,7 +6885,7 @@
|
||||
"description": "Converts CSS selectors to XPath expressions",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/css-selector/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/css-selector/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6904,7 +6905,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-18T13:51:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -7056,16 +7057,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6"
|
||||
"reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f662acc6ab22a3d6d716dcb44c381c6002940df6",
|
||||
"reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0c3c1a17604c4dbbec4b93fe162c538482096e1f",
|
||||
"reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7117,7 +7118,7 @@
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7137,7 +7138,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-18T13:51:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
@@ -7352,16 +7353,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-client",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-client.git",
|
||||
"reference": "356e43d6994ae9d7761fd404d40f78691deabe0e"
|
||||
"reference": "537c7f164078975b800f3f1c56810791024e4c77"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/356e43d6994ae9d7761fd404d40f78691deabe0e",
|
||||
"reference": "356e43d6994ae9d7761fd404d40f78691deabe0e",
|
||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/537c7f164078975b800f3f1c56810791024e4c77",
|
||||
"reference": "537c7f164078975b800f3f1c56810791024e4c77",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7424,7 +7425,7 @@
|
||||
"http"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-client/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/http-client/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7444,7 +7445,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-29T15:02:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-client-contracts",
|
||||
@@ -7860,16 +7861,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "ddff21f14c7ce04b98101b399a9463dce8b0ce66"
|
||||
"reference": "a9fcb293650c054b62a5b406f4e92e7b711ea333"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/ddff21f14c7ce04b98101b399a9463dce8b0ce66",
|
||||
"reference": "ddff21f14c7ce04b98101b399a9463dce8b0ce66",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/a9fcb293650c054b62a5b406f4e92e7b711ea333",
|
||||
"reference": "a9fcb293650c054b62a5b406f4e92e7b711ea333",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7922,7 +7923,7 @@
|
||||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/mime/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7942,7 +7943,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-29T15:02:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
@@ -8596,6 +8597,86 @@
|
||||
],
|
||||
"time": "2026-04-26T13:10:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php86",
|
||||
"version": "v1.37.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php86.git",
|
||||
"reference": "33d8fc5a705481e21fe3a81212b26f9b1f61749c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/33d8fc5a705481e21fe3a81212b26f9b1f61749c",
|
||||
"reference": "33d8fc5a705481e21fe3a81212b26f9b1f61749c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php86\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.6+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php86/tree/v1.37.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-26T13:13:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-uuid",
|
||||
"version": "v1.37.0",
|
||||
@@ -8833,16 +8914,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
"reference": "0de330ec2ea922a7b08ec45615bd51179de7fda4"
|
||||
"reference": "75d1bd8e5da3424e4db2fc3ff0222cb4d0c73038"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/0de330ec2ea922a7b08ec45615bd51179de7fda4",
|
||||
"reference": "0de330ec2ea922a7b08ec45615bd51179de7fda4",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/75d1bd8e5da3424e4db2fc3ff0222cb4d0c73038",
|
||||
"reference": "75d1bd8e5da3424e4db2fc3ff0222cb4d0c73038",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8889,7 +8970,7 @@
|
||||
"url"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/routing/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/routing/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8909,7 +8990,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-29T15:02:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@@ -9265,16 +9346,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/uid",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/uid.git",
|
||||
"reference": "f63fa6096a24147283bce4d29327d285326438e0"
|
||||
"reference": "4d9d6510bbe88ebb4608b7200d18606cdf80825c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/uid/zipball/f63fa6096a24147283bce4d29327d285326438e0",
|
||||
"reference": "f63fa6096a24147283bce4d29327d285326438e0",
|
||||
"url": "https://api.github.com/repos/symfony/uid/zipball/4d9d6510bbe88ebb4608b7200d18606cdf80825c",
|
||||
"reference": "4d9d6510bbe88ebb4608b7200d18606cdf80825c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9319,7 +9400,7 @@
|
||||
"uuid"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/uid/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/uid/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9339,7 +9420,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-30T16:10:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
@@ -9430,16 +9511,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-exporter",
|
||||
"version": "v8.0.8",
|
||||
"version": "v8.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-exporter.git",
|
||||
"reference": "15776bb07a91b089037da89f8832fa41d5fa6ec6"
|
||||
"reference": "24cf67be4dd0926e4413635418682f4fff831412"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/15776bb07a91b089037da89f8832fa41d5fa6ec6",
|
||||
"reference": "15776bb07a91b089037da89f8832fa41d5fa6ec6",
|
||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/24cf67be4dd0926e4413635418682f4fff831412",
|
||||
"reference": "24cf67be4dd0926e4413635418682f4fff831412",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9486,7 +9567,7 @@
|
||||
"serialize"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/var-exporter/tree/v8.0.8"
|
||||
"source": "https://github.com/symfony/var-exporter/tree/v8.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9506,7 +9587,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
"time": "2026-04-18T13:51:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "thecodingmachine/safe",
|
||||
@@ -10093,6 +10174,62 @@
|
||||
},
|
||||
"time": "2026-03-05T20:09:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "carthage-software/mago",
|
||||
"version": "1.25.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/carthage-software/mago.git",
|
||||
"reference": "54e9645d15381aa78bf7113e01dcd1734ec43737"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/carthage-software/mago/zipball/54e9645d15381aa78bf7113e01dcd1734ec43737",
|
||||
"reference": "54e9645d15381aa78bf7113e01dcd1734ec43737",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5 || ~8.6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "To show binary download progress"
|
||||
},
|
||||
"bin": [
|
||||
"composer/bin/mago"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"composer/functions.php",
|
||||
"composer/internal.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT OR Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Saif Eddin Gmati",
|
||||
"email": "azjezz@carthage.software"
|
||||
}
|
||||
],
|
||||
"description": "Mago is a toolchain for PHP that aims to provide a set of tools to help developers write better code.",
|
||||
"keywords": [
|
||||
"dev"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/carthage-software/mago/issues",
|
||||
"source": "https://github.com/carthage-software/mago/tree/1.25.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/azjezz",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-02T23:21:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "cloudcreativity/json-api-testing",
|
||||
"version": "v6.4.0",
|
||||
@@ -11141,16 +11278,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-debugbar/php-debugbar",
|
||||
"version": "v3.7.5",
|
||||
"version": "v3.7.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-debugbar/php-debugbar.git",
|
||||
"reference": "dbf77f48fa6e6b57ed57ae67aa047b2535697788"
|
||||
"reference": "1690ee1728827f9deb4b60457fa387cf44672c56"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/dbf77f48fa6e6b57ed57ae67aa047b2535697788",
|
||||
"reference": "dbf77f48fa6e6b57ed57ae67aa047b2535697788",
|
||||
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/1690ee1728827f9deb4b60457fa387cf44672c56",
|
||||
"reference": "1690ee1728827f9deb4b60457fa387cf44672c56",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11227,7 +11364,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
|
||||
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.7.5"
|
||||
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.7.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11239,7 +11376,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-15T11:58:43+00:00"
|
||||
"time": "2026-04-30T07:31:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-debugbar/symfony-bridge",
|
||||
@@ -11357,11 +11494,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.51",
|
||||
"version": "2.1.54",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59",
|
||||
"reference": "dc3b523c45e714c70de2ac5113b958223b55dc59",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/8be50c3992107dc837b17da4d140fbbdf9a5c5bd",
|
||||
"reference": "8be50c3992107dc837b17da4d140fbbdf9a5c5bd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11406,7 +11543,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-21T18:22:01+00:00"
|
||||
"time": "2026-04-29T13:31:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
@@ -11460,16 +11597,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "2.0.10",
|
||||
"version": "2.0.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f"
|
||||
"reference": "9b000a578b85b32945b358b172c7b20e91189024"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f",
|
||||
"reference": "1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/9b000a578b85b32945b358b172c7b20e91189024",
|
||||
"reference": "9b000a578b85b32945b358b172c7b20e91189024",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11505,9 +11642,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.10"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.11"
|
||||
},
|
||||
"time": "2026-02-11T14:17:32+00:00"
|
||||
"time": "2026-05-02T06:54:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
@@ -11894,16 +12031,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "13.1.7",
|
||||
"version": "13.1.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "ddd6401641861cdef94b922ef10d484f436e8dcd"
|
||||
"reference": "f49a2b5e51ffb33421745368cc099cf66830d71b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ddd6401641861cdef94b922ef10d484f436e8dcd",
|
||||
"reference": "ddd6401641861cdef94b922ef10d484f436e8dcd",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f49a2b5e51ffb33421745368cc099cf66830d71b",
|
||||
"reference": "f49a2b5e51ffb33421745368cc099cf66830d71b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11917,7 +12054,7 @@
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.4.1",
|
||||
"phpunit/php-code-coverage": "^14.1.3",
|
||||
"phpunit/php-code-coverage": "^14.1.6",
|
||||
"phpunit/php-file-iterator": "^7.0.0",
|
||||
"phpunit/php-invoker": "^7.0.0",
|
||||
"phpunit/php-text-template": "^6.0.0",
|
||||
@@ -11973,7 +12110,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/13.1.7"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/13.1.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11981,7 +12118,7 @@
|
||||
"type": "other"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-18T06:14:52+00:00"
|
||||
"time": "2026-05-01T04:22:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
use Pdo\Mysql;
|
||||
|
||||
use function Safe\parse_url;
|
||||
|
||||
@@ -52,22 +53,22 @@ $mySqlSSLOptions = [];
|
||||
$useSSL = env_default_when_empty(env('MYSQL_USE_SSL'), false);
|
||||
if (false !== $useSSL && null !== $useSSL && '' !== $useSSL) {
|
||||
if (null !== $mysql_ssl_ca_dir) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CAPATH] = $mysql_ssl_ca_dir;
|
||||
$mySqlSSLOptions[Mysql::ATTR_SSL_CAPATH] = $mysql_ssl_ca_dir;
|
||||
}
|
||||
if (null !== $mysql_ssl_ca_file) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CA] = $mysql_ssl_ca_file;
|
||||
$mySqlSSLOptions[Mysql::ATTR_SSL_CA] = $mysql_ssl_ca_file;
|
||||
}
|
||||
if (null !== $mysql_ssl_cert) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CERT] = $mysql_ssl_cert;
|
||||
$mySqlSSLOptions[Mysql::ATTR_SSL_CERT] = $mysql_ssl_cert;
|
||||
}
|
||||
if (null !== $mysql_ssl_key) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_KEY] = $mysql_ssl_key;
|
||||
$mySqlSSLOptions[Mysql::ATTR_SSL_KEY] = $mysql_ssl_key;
|
||||
}
|
||||
if (null !== $mysql_ssl_ciphers) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CIPHER] = $mysql_ssl_ciphers;
|
||||
$mySqlSSLOptions[Mysql::ATTR_SSL_CIPHER] = $mysql_ssl_ciphers;
|
||||
}
|
||||
if (null !== $mysql_ssl_verify) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $mysql_ssl_verify;
|
||||
$mySqlSSLOptions[Mysql::ATTR_SSL_VERIFY_SERVER_CERT] = $mysql_ssl_verify;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ return [
|
||||
'running_balance_column' => (bool)env_default_when_empty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2026-04-27',
|
||||
'build_time' => 1777306297,
|
||||
'version' => 'develop/2026-05-03',
|
||||
'build_time' => 1777786936,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 28, // field is no longer used.
|
||||
|
||||
|
||||
109
package-lock.json
generated
109
package-lock.json
generated
@@ -32,9 +32,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
|
||||
"integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
|
||||
"integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -140,9 +140,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-create-class-features-plugin": {
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
|
||||
"integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz",
|
||||
"integrity": "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -151,7 +151,7 @@
|
||||
"@babel/helper-optimise-call-expression": "^7.27.1",
|
||||
"@babel/helper-replace-supers": "^7.28.6",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
|
||||
"@babel/traverse": "^7.28.6",
|
||||
"@babel/traverse": "^7.29.0",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -405,9 +405,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.29.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
|
||||
"integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
|
||||
"integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -469,6 +469,23 @@
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": {
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz",
|
||||
"integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz",
|
||||
@@ -1501,19 +1518,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.29.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz",
|
||||
"integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.3.tgz",
|
||||
"integrity": "sha512-ySZypNLAIH1ClygLDQzVMoGQRViATnkHkYYV6TcNDz+8+jwZCdsguGvsb3EY5d9wyWyhmF1iSuFM0Yh5XPnqSA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.29.0",
|
||||
"@babel/compat-data": "^7.29.3",
|
||||
"@babel/helper-compilation-targets": "^7.28.6",
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"@babel/helper-validator-option": "^7.27.1",
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
|
||||
"@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-rest-destructuring-rhs-array": "^7.29.3",
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6",
|
||||
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
||||
@@ -3384,9 +3402,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/alpinejs": {
|
||||
"version": "3.15.11",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.11.tgz",
|
||||
"integrity": "sha512-m26gkTg/MId8O+F4jHKK3vB3SjbFxxk/JHP+qzmw1H6aQrZuPAg4CUoAefnASzzp/eNroBjrRQe7950bNeaBJw==",
|
||||
"version": "3.15.12",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.12.tgz",
|
||||
"integrity": "sha512-nJvPAQVNPdZZ0NrExJ/kzQco3ijR8LwvCOadQecllESiqT4NyZ/57sN9V2XyvhlBGAbmlKYgeWZvYdKq99ij/Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "~3.1.1"
|
||||
@@ -3569,13 +3587,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
|
||||
"integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz",
|
||||
"integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.11",
|
||||
"follow-redirects": "^1.16.0",
|
||||
"form-data": "^4.0.5",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
@@ -3681,9 +3699,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.10.23",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.23.tgz",
|
||||
"integrity": "sha512-xwVXGqevyKPsiuQdLj+dZMVjidjJV508TBqexND5HrF89cGdCYCJFB3qhcxRHSeMctdCfbR1jrxBajhDy7o29g==",
|
||||
"version": "2.10.25",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.25.tgz",
|
||||
"integrity": "sha512-QO/VHsXCQdnzADMfmkeOPvHdIAkoB7i0/rGjINPJEetLx75hNttVWGQ/jycHUDP9zZ9rupbm60WRxcwViB0MiA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -5321,9 +5339,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.344",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz",
|
||||
"integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==",
|
||||
"version": "1.5.349",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.349.tgz",
|
||||
"integrity": "sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
@@ -7377,9 +7395,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/laravel-vite-plugin": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-3.0.1.tgz",
|
||||
"integrity": "sha512-Bx8sVcLIaZT1d0eisABcmjQ1GZdJpaXcV66A8RhXGp9JgR3iL8jDnvakVDXuH87Tn5S9KNx3VOhmJZW1CSexOg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-3.1.0.tgz",
|
||||
"integrity": "sha512-Fzocl+X4eQ9jOi0RwdphYRGkUbPJ3ky1pTAST5Ot18cS2gw6d2vldK2eCrlKDVjtibCjCx5qptYDlA0373n7qg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -7394,7 +7412,13 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"fontaine": "^0.5.0",
|
||||
"vite": "^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"fontaine": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/launch-editor": {
|
||||
@@ -8107,9 +8131,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"version": "3.3.12",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
|
||||
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -8741,9 +8765,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.12",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz",
|
||||
"integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==",
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz",
|
||||
"integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -11216,6 +11240,7 @@
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -11964,9 +11989,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/webpack-sources": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.0.tgz",
|
||||
"integrity": "sha512-gHwIe1cgBvvfLeu1Yz/dcFpmHfKDVxxyqI+kzqmuxZED81z2ChxpyqPaWcNqigPywhaEke7AjSGga+kxY55gjQ==",
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz",
|
||||
"integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -12146,9 +12171,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
|
||||
"integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
|
||||
"version": "2.8.4",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz",
|
||||
"integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
|
||||
@@ -100,29 +100,29 @@ $(function () {
|
||||
// show rule triggers
|
||||
$('.rule-triggers-show').click(function (e) {
|
||||
var obj = $(e.currentTarget);
|
||||
$('.rule-trigger-list[data-id="' + obj.data('id') + '"]').show();
|
||||
$('.rule-triggers-show[data-id="' + obj.data('id') + '"]').hide();
|
||||
$('.rule-trigger-list[data-id="' + obj.data('id') + '"]').removeClass('hidden');
|
||||
$('.rule-triggers-show[data-id="' + obj.data('id') + '"]').addClass('hidden');
|
||||
});
|
||||
|
||||
$('.rule-trigger-list').each(function(i,v) {
|
||||
var obj = $(v);
|
||||
if(obj.data('count') > 2) {
|
||||
obj.hide();
|
||||
$('.rule-triggers-show[data-id="' + obj.data('id') + '"]').show();
|
||||
obj.addClass('hidden');
|
||||
$('.rule-triggers-show[data-id="' + obj.data('id') + '"]').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
// show rule actions
|
||||
$('.rule-actions-show').click(function (e) {
|
||||
var obj = $(e.currentTarget);
|
||||
$('.rule-action-list[data-id="' + obj.data('id') + '"]').show();
|
||||
$('.rule-actions-show[data-id="' + obj.data('id') + '"]').hide();
|
||||
$('.rule-action-list[data-id="' + obj.data('id') + '"]').removeClass('hidden');
|
||||
$('.rule-actions-show[data-id="' + obj.data('id') + '"]').addClass('hidden');
|
||||
});
|
||||
|
||||
$('.rule-action-list').each(function(i,v) {
|
||||
var obj = $(v);
|
||||
if(obj.data('count') > 1) {
|
||||
obj.hide();
|
||||
$('.rule-actions-show[data-id="' + obj.data('id') + '"]').show();
|
||||
obj.addClass('hidden');
|
||||
$('.rule-actions-show[data-id="' + obj.data('id') + '"]').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -194,9 +194,9 @@ function testRuleTriggers(e) {
|
||||
// Show warning if appropriate
|
||||
if (data.warning) {
|
||||
modal.find(".transaction-warning .warning-contents").text(data.warning);
|
||||
modal.find(".transaction-warning").show();
|
||||
modal.find(".transaction-warning").removeClass('hidden');
|
||||
} else {
|
||||
modal.find(".transaction-warning").hide();
|
||||
modal.find(".transaction-warning").addClass('hidden');
|
||||
}
|
||||
|
||||
// Show the modal dialog
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"firefly": {
|
||||
"explain_pats": "Personal Access Tokens are long lived (with a maximum of 1 year) keys that allow direct and unlimited access to your Firefly III data. Tools like the Firefly III Data Importer and the Firefly III integration in Home Assistant use such tokens to connect to Firefly III and do their thing. When you create a token, it is only visible once. The token is also very long.",
|
||||
"profile_oauth_clients_explain": "An OAuth client can be used to connect \"smart\" applications to Firefly III: applications that are capable of redirecting you to your Firefly III, get your permission, and return you back. The Firefly III Data Importer is such an application. OAuth clients can be generated with or without a \"secret\". This secret is used to authenticate the client. Since not all clients are capable of storing the secret, so you have the option to generate a client without one.",
|
||||
"regenerate_secret": "Regenerate secret",
|
||||
"explain_pats": "\u4e2a\u4eba\u8bbf\u95ee\u4ee4\u724c\u662f\u4e00\u79cd\u957f\u671f\u6709\u6548\uff08\u6700\u957f1\u5e74\uff09\u7684\u4ee4\u724c\uff0c\u53ef\u8ba9\u60a8\u76f4\u63a5\u3001\u65e0\u9650\u5236\u5730\u8bbf\u95ee Firefly III \u6570\u636e\u3002\u8bf8\u5982 `Firefly III Data Importer` \u4ee5\u53ca Home Assistant \u4e2d\u7684 Firefly III \u96c6\u6210\u7b49\u5de5\u5177\uff0c\u6b63\u662f\u4f7f\u7528\u6b64\u7c7b\u4ee4\u724c\u8fde\u63a5\u81f3 Firefly III \u5e76\u5b8c\u6210\u5404\u81ea\u7684\u4efb\u52a1\u3002\u521b\u5efa\u4ee4\u724c\u65f6\uff0c\u5b83\u4ec5\u4f1a\u663e\u793a\u4e00\u6b21\u3002\u4ee4\u724c\u5b57\u7b26\u4e32\u901a\u5e38\u4f1a\u5f88\u957f\u3002",
|
||||
"profile_oauth_clients_explain": "OAuth\u5ba2\u6237\u7aef\u53ef\u7528\u4e8e\u5c06\u201c\u667a\u80fd\u201d\u5e94\u7528\u8fde\u63a5\u5230 Firefly III\uff1a\u5b83\u4eec\u80fd\u591f\u5c06\u60a8\u91cd\u5b9a\u5411\u5230\u60a8\u7684Firefly III\uff0c\u83b7\u53d6\u60a8\u7684\u6388\u6743\uff0c\u7136\u540e\u8fd4\u56de\u5e94\u7528\u3002`Firefly III Data Importer`\u5c31\u662f\u8fd9\u6837\u7684\u5e94\u7528\u3002\u751f\u6210OAuth\u5ba2\u6237\u7aef\u65f6\u53ef\u4ee5\u9009\u62e9\u662f\u5426\u9644\u5e26\u201c\u5bc6\u94a5\uff08secret\uff09\u201d\uff0c\u5b83\u7528\u4e8e\u9a8c\u8bc1\u5ba2\u6237\u7aef\u3002\u5e76\u975e\u6240\u6709\u5ba2\u6237\u7aef\u90fd\u80fd\u591f\u5b89\u5168\u5b58\u50a8\u5bc6\u94a5\uff0c\u6240\u4ee5\u60a8\u53ef\u4ee5\u9009\u62e9\u751f\u6210\u4e00\u4e2a\u4e0d\u5e26\u5bc6\u94a5\u7684\u5ba2\u6237\u7aef\u3002",
|
||||
"regenerate_secret": "\u91cd\u65b0\u751f\u6210\u5bc6\u94a5",
|
||||
"administrations_page_title": "\u8d22\u52a1\u7ba1\u7406",
|
||||
"administrations_index_menu": "\u8d22\u52a1\u7ba1\u7406",
|
||||
"expires_at": "\u8fc7\u671f\u4e8e",
|
||||
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its primary currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
|
||||
"administration_currency_form_help": "It may take a long time for the page to load if you change the primary currency because transaction may need to be converted to your (new) primary currency.",
|
||||
"temp_administrations_introduction": "Firefly III \u4e0d\u4e45\u5c06\u652f\u6301\u7ba1\u7406\u591a\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002\u76ee\u524d\u60a8\u53ea\u6709\u4e00\u4e2a\u3002\u60a8\u53ef\u4ee5\u8bbe\u7f6e\u8fd9\u4e2a\u8d22\u52a1\u7ba1\u7406\u7684\u540d\u79f0\u53ca\u5176\u4e3b\u8981\u8d27\u5e01\u3002\u8fd9\u53d6\u4ee3\u4e86\u4e4b\u524d\u201c\u9ed8\u8ba4\u8d27\u5e01\u201d\u7684\u8bbe\u7f6e\u3002\u8be5\u8bbe\u7f6e\u73b0\u5728\u5df2\u4e0e\u8d22\u52a1\u7ba1\u7406\u6302\u94a9\uff0c\u6bcf\u4e2a\u8d22\u52a1\u7ba1\u7406\u53ef\u4ee5\u6709\u4e0d\u540c\u8bbe\u7f6e\u3002",
|
||||
"administration_currency_form_help": "\u5982\u679c\u60a8\u66f4\u6539\u4e3b\u8981\u8d27\u5e01\uff0c\u9875\u9762\u52a0\u8f7d\u53ef\u80fd\u9700\u8981\u5f88\u957f\u65f6\u95f4\uff0c\u56e0\u4e3a\u4ea4\u6613\u53ef\u80fd\u9700\u8981\u8f6c\u6362\u4e3a\u60a8\u7684(\u65b0)\u4e3b\u8981\u8d27\u5e01\u3002",
|
||||
"administrations_page_edit_sub_title_js": "\u7f16\u8f91\u8d22\u52a1\u7ba1\u7406{title}",
|
||||
"table": "\u8868\u683c",
|
||||
"welcome_back": "\u4eca\u5929\u7406\u8d22\u4e86\u5417\uff1f",
|
||||
@@ -75,8 +75,8 @@
|
||||
"profile_whoops": "\u5f88\u62b1\u6b49\uff01",
|
||||
"profile_something_wrong": "\u53d1\u751f\u9519\u8bef\uff01",
|
||||
"profile_try_again": "\u53d1\u751f\u9519\u8bef\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\u3002",
|
||||
"profile_oauth_clients": "OAuth Clients and Applications",
|
||||
"profile_oauth_no_clients": "You have not created any OAuth clients or applications.",
|
||||
"profile_oauth_clients": "OAuth \u5ba2\u6237\u7aef\u548c\u5e94\u7528\u7a0b\u5e8f",
|
||||
"profile_oauth_no_clients": "\u60a8\u8fd8\u6ca1\u6709\u521b\u5efa\u4efb\u4f55 OAuth \u5ba2\u6237\u7aef\u6216\u5e94\u7528\u7a0b\u5e8f\u3002",
|
||||
"profile_oauth_clients_header": "\u5ba2\u6237\u7aef",
|
||||
"profile_oauth_client_id": "\u5ba2\u6237\u7aef ID",
|
||||
"profile_oauth_client_name": "\u540d\u79f0",
|
||||
@@ -86,7 +86,7 @@
|
||||
"profile_oauth_edit_client": "\u7f16\u8f91\u5ba2\u6237\u7aef",
|
||||
"profile_oauth_name_help": "\u60a8\u7684\u7528\u6237\u53ef\u4ee5\u8bc6\u522b\u5e76\u4fe1\u4efb\u7684\u4fe1\u606f",
|
||||
"profile_oauth_redirect_url": "\u8df3\u8f6c\u7f51\u5740",
|
||||
"profile_oauth_clients_external_auth": "Please note that if you're using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.",
|
||||
"profile_oauth_clients_external_auth": "\u8bf7\u6ce8\u610f\uff1a\u5982\u679c\u60a8\u6b63\u5728\u4f7f\u7528\u5982 Authelia \u7684\u5916\u90e8\u8eab\u4efd\u9a8c\u8bc1\u63d0\u4f9b\u5546\uff0cOAuth \u5ba2\u6237\u7aef\u5c06\u65e0\u6cd5\u4f7f\u7528\u3002\u60a8\u53ea\u80fd\u4f7f\u7528\u4e2a\u4eba\u8bbf\u95ee\u4ee4\u724c\u3002",
|
||||
"profile_oauth_redirect_url_help": "\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u7684\u6388\u6743\u56de\u8c03\u7f51\u5740",
|
||||
"profile_authorized_apps": "\u5df2\u6388\u6743\u5e94\u7528",
|
||||
"profile_authorized_clients": "\u5df2\u6388\u6743\u5ba2\u6237\u7aef",
|
||||
@@ -104,24 +104,24 @@
|
||||
"piggy_bank": "\u5b58\u94b1\u7f50",
|
||||
"profile_oauth_client_secret_title": "\u5ba2\u6237\u7aef\u5bc6\u94a5",
|
||||
"profile_oauth_client_secret_expl": "\u8bf7\u59a5\u5584\u4fdd\u5b58\u60a8\u7684\u65b0\u5ba2\u6237\u7aef\u7684\u5bc6\u94a5\uff0c\u6b64\u5bc6\u94a5\u4ec5\u4f1a\u5728\u8fd9\u91cc\u5c55\u793a\u4e00\u6b21\u3002\u60a8\u73b0\u5728\u5df2\u53ef\u4ee5\u4f7f\u7528\u6b64\u5bc6\u94a5\u8fdb\u884c API \u8bf7\u6c42\u3002",
|
||||
"profile_oauth_confidential": "Keep a secret?",
|
||||
"profile_oauth_confidential_help": "Can the application you're using this for keep a secret? The Firefly III Data Importer CANNOT keep a secret, so UNCHECK the box. In other cases, it's up to you.",
|
||||
"profile_oauth_confidential": "\u9644\u5e26\u5bc6\u94a5\uff1f",
|
||||
"profile_oauth_confidential_help": "\u60a8\u8981\u8fde\u63a5\u7684\u5e94\u7528\u80fd\u5426\u5b89\u5168\u4fdd\u5b58\u5bc6\u94a5\uff1f`Firefly III Data Importer`\u65e0\u6cd5\u4fdd\u5b58\u5bc6\u94a5\uff0c\u56e0\u6b64\u8bf7\u53d6\u6d88\u52fe\u9009\u6b64\u6846\u3002\u5176\u4ed6\u60c5\u51b5\u7531\u60a8\u81ea\u884c\u51b3\u5b9a\u3002",
|
||||
"multi_account_warning_unknown": "\u6839\u636e\u60a8\u521b\u5efa\u7684\u4ea4\u6613\u7c7b\u578b\uff0c\u540e\u7eed\u62c6\u5206\u7684\u6765\u6e90\u548c\/\u6216\u76ee\u6807\u8d26\u6237\u53ef\u80fd\u88ab\u4ea4\u6613\u7684\u9996\u7b14\u62c6\u5206\u7684\u914d\u7f6e\u6240\u8986\u76d6\u3002",
|
||||
"multi_account_warning_withdrawal": "\u8bf7\u6ce8\u610f\uff0c\u540e\u7eed\u62c6\u5206\u7684\u6765\u6e90\u8d26\u6237\u5c06\u4f1a\u88ab\u652f\u51fa\u7684\u9996\u7b14\u62c6\u5206\u7684\u914d\u7f6e\u6240\u8986\u76d6\u3002",
|
||||
"multi_account_warning_deposit": "\u8bf7\u6ce8\u610f\uff0c\u540e\u7eed\u62c6\u5206\u7684\u76ee\u6807\u8d26\u6237\u5c06\u4f1a\u88ab\u6536\u5165\u7684\u9996\u7b14\u62c6\u5206\u7684\u914d\u7f6e\u6240\u8986\u76d6\u3002",
|
||||
"multi_account_warning_transfer": "\u8bf7\u6ce8\u610f\uff0c\u540e\u7eed\u62c6\u5206\u7684\u6765\u6e90\u548c\u76ee\u6807\u8d26\u6237\u5c06\u4f1a\u88ab\u8f6c\u8d26\u7684\u9996\u7b14\u62c6\u5206\u7684\u914d\u7f6e\u6240\u8986\u76d6\u3002",
|
||||
"webhook_trigger_ANY": "After any event",
|
||||
"webhook_trigger_ANY": "\u5728\u4efb\u4f55\u4e8b\u4ef6\u4e4b\u540e",
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u4ea4\u6613\u521b\u5efa\u540e",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u4ea4\u6613\u66f4\u65b0\u540e",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u4ea4\u6613\u5220\u9664\u540e",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_trigger_STORE_BUDGET": "\u9884\u7b97\u521b\u5efa\u540e",
|
||||
"webhook_trigger_UPDATE_BUDGET": "\u9884\u7b97\u66f4\u65b0\u540e",
|
||||
"webhook_trigger_DESTROY_BUDGET": "\u9884\u7b97\u5220\u9664\u540e",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "\u9884\u7b97\u91d1\u989d\u53d8\u66f4\u540e",
|
||||
"webhook_response_TRANSACTIONS": "\u4ea4\u6613\u8be6\u60c5",
|
||||
"webhook_response_RELEVANT": "Relevant details",
|
||||
"webhook_response_RELEVANT": "\u76f8\u5173\u660e\u7ec6",
|
||||
"webhook_response_ACCOUNTS": "\u8d26\u6237\u8be6\u60c5",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_response_NONE": "\u65e0\u8be6\u7ec6\u4fe1\u606f",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u64cd\u4f5c",
|
||||
"meta_data": "\u540e\u8bbe\u8d44\u6599",
|
||||
@@ -163,7 +163,7 @@
|
||||
"url": "\u7f51\u5740",
|
||||
"active": "\u542f\u7528",
|
||||
"interest_date": "\u5229\u606f\u65e5\u671f",
|
||||
"administration_currency": "Primary currency",
|
||||
"administration_currency": "\u4e3b\u8981\u8d27\u5e01",
|
||||
"title": "\u6807\u9898",
|
||||
"date": "\u65e5\u671f",
|
||||
"book_date": "\u767b\u8bb0\u65e5\u671f",
|
||||
@@ -183,7 +183,7 @@
|
||||
"list": {
|
||||
"title": "\u6807\u9898",
|
||||
"active": "\u662f\u5426\u542f\u7528\uff1f",
|
||||
"primary_currency": "Primary currency",
|
||||
"primary_currency": "\u4e3b\u8981\u8d27\u5e01",
|
||||
"trigger": "\u89e6\u53d1\u6761\u4ef6",
|
||||
"response": "\u7b54\u590d",
|
||||
"delivery": "\u4ea4\u4ed8",
|
||||
|
||||
@@ -1621,7 +1621,7 @@ return [
|
||||
'secure_pw_ff' => 'Do you use the same password all over the internet? If one site loses your password, hackers have access to all your data. Firefly III relies on you to choose a strong and unique password to protect your financial records.',
|
||||
'secure_pw_check_box' => 'To help you do that Firefly III can check if the password you want to use has been stolen in the past. If this is the case, Firefly III advises you NOT to use that password.',
|
||||
'secure_pw_working_title' => 'How does it work?',
|
||||
'secure_pw_working' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to <a href="https://www.troyhunt.com/introducing-306-million-freely-downloadable-pwned-passwords/">the website of Troy Hunt</a> to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">NIST Special Publication</a> on this subject.',
|
||||
'secure_pw_working' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to <a href="https://haveibeenpwned.com/API/v3#PwnedPasswords">the website of Troy Hunt</a> to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">NIST Special Publication</a> on this subject.',
|
||||
'secure_pw_should' => 'Should I check the box?',
|
||||
'secure_pw_long_password' => 'Yes. Always verify your password is safe.',
|
||||
'command_line_token' => 'Command line token',
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<input type="checkbox" id="verify_password" checked name="verify_password" value="1">
|
||||
<input type="checkbox" id="verify_password" name="verify_password" value="1">
|
||||
<label for="verify_password">
|
||||
{{ trans('form.verify_password') }}
|
||||
<a href="#"
|
||||
|
||||
@@ -487,6 +487,9 @@
|
||||
{% if '' != link.foreign_amount %}
|
||||
({{ link.foreign_amount|raw }})
|
||||
{% endif %}
|
||||
{% if link.notes != "" %}
|
||||
({{ link.notes }})
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
Reference in New Issue
Block a user