mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-05-04 21:23:36 +00:00
Compare commits
35 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b80a5bdbe | ||
|
|
0202f4abd9 | ||
|
|
615d568479 | ||
|
|
2ace0d3f23 | ||
|
|
42204f8dc1 | ||
|
|
cfac8fa569 | ||
|
|
04704392f3 | ||
|
|
4b9bbc9d6a | ||
|
|
f24f535d39 | ||
|
|
3a9ac03358 | ||
|
|
4ac7fec5f6 | ||
|
|
b6759c3fa0 | ||
|
|
4a83b1e3e5 | ||
|
|
4b701dfc4c | ||
|
|
b2997d0a5a | ||
|
|
fd8722e401 | ||
|
|
e46153330a | ||
|
|
525f0c752a | ||
|
|
13e4160e85 | ||
|
|
7806d63f91 | ||
|
|
8c620b6536 | ||
|
|
e47ce30579 | ||
|
|
7e6eadc047 | ||
|
|
dae4f6f351 | ||
|
|
8c8af51bc4 | ||
|
|
a5e1cba39c | ||
|
|
96d56ad723 | ||
|
|
e4b1c3045e | ||
|
|
e974594fe3 | ||
|
|
c93a2dc23a | ||
|
|
639efee78a | ||
|
|
eb4971fec6 | ||
|
|
0c63a3380d | ||
|
|
edd30b2d42 | ||
|
|
e8ab7d8a93 |
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",
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
) {}
|
||||
|
||||
|
||||
@@ -245,13 +245,8 @@ 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,
|
||||
@@ -289,7 +284,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'] = Steam::negative(bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']));
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -335,7 +335,9 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
|
||||
$limit = new BudgetLimit();
|
||||
$limit->budget()->associate($budget);
|
||||
$limit->start_date = $data['start_date']->format('Y-m-d');
|
||||
$limit->start_date_tz = $data['start_date']->format('e');
|
||||
$limit->end_date = $data['end_date']->format('Y-m-d');
|
||||
$limit->end_date_tz = $data['end_date']->format('e');
|
||||
$limit->amount = $data['amount'];
|
||||
$limit->generated = $data['generated'] ?? false;
|
||||
$limit->period = $data['period'] ?? '';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' => 1777307205,
|
||||
'version' => 'develop/2026-05-03',
|
||||
'build_time' => 1777795578,
|
||||
'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",
|
||||
|
||||
@@ -1398,6 +1398,7 @@ return [
|
||||
'pref_locale' => 'Locale settings',
|
||||
'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
|
||||
'pref_locale_help' => 'Firefly III allows you to set other local settings, like how currencies, numbers and dates are formatted. Entries in this list may not be supported by your system. Firefly III doesn\'t have the correct date settings for every locale; contact me for improvements.',
|
||||
'pref_locale_exception' => 'Firefly III can only change how you view dates. Entering a date will always be formatted according to your browser settings, not Firefly III settings. If your browser is set to "English (US)" you must always enter the date formatted as mm/dd/yyyy. No setting in Firefly III can change that.',
|
||||
'pref_locale_no_demo' => 'This feature won\'t work for the demo user.',
|
||||
'pref_convert_to_primary' => 'Display amounts in your primary currency',
|
||||
'pref_convert_to_primary_help' => 'This option will make Firefly III try to display and show your primary currency in as many places as possible, converting amounts where necessary. This sacrifices accuracy for ease of use, because conversion is not always exact. Please verify that Firefly III has the necessary conversion rates on the "exchange rates"-page.',
|
||||
@@ -1621,7 +1622,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',
|
||||
@@ -1813,6 +1814,13 @@ return [
|
||||
'options' => 'Options',
|
||||
|
||||
// budgets:
|
||||
'spent_this_period' => 'Spent on this budget',
|
||||
'spent_this_period_per_day' => 'Spent on this budget per day (:days day(s))',
|
||||
'spent_in_budget_limit_outside_period' => 'Spent on this budget, but NOT in this period',
|
||||
'spent_in_budget_limit_outside_period_per_day' => 'Spent on this budget, but NOT in this period per day (:days day(s))',
|
||||
'left_in_budget_limit_overview' => 'Left in this budget',
|
||||
'left_in_budget_limit_per_day' => 'Left in this budget per day (:days day(s))',
|
||||
'nothing_left_in_budget' => 'The budget is now empty',
|
||||
'daily_budgets' => 'Daily budgets',
|
||||
'weekly_budgets' => 'Weekly budgets',
|
||||
'monthly_budgets' => 'Monthly budgets',
|
||||
|
||||
@@ -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="#"
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
{% for budgetLimit in budget.budgeted %}
|
||||
<span class="left_span" data-currency="{{ budgetLimit.currency_id }}" data-limit="{{ budgetLimit.id }}" data-value="{{ budgetLimit.left }}" class="amount_left">
|
||||
{# the amount left #}
|
||||
{{ formatAmountBySymbol(budgetLimit.left, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}
|
||||
<span title="{{ 'left_in_budget_limit_overview'|_ }}">{{ formatAmountBySymbol(budgetLimit.left, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}</span>
|
||||
|
||||
{# if the budget limit is in the past, this is not interesting. #}
|
||||
{# if there is nothing left, this is not interesting. #}
|
||||
{% if not budgetLimit.in_past and -1 == bccomp('0',budgetLimit.left) %}
|
||||
{% if 0 == budgetLimit.active_days_left %}
|
||||
({{ formatAmountBySymbol(budgetLimit.left, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||
<span title="{{ trans('firefly.left_in_budget_limit_per_day', {days: 0}) }}">({{ formatAmountBySymbol(budgetLimit.left, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||
{% else %}
|
||||
({{ formatAmountBySymbol(budgetLimit.left / budgetLimit.active_days_left, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||
<span title="{{ trans('firefly.left_in_budget_limit_per_day', {days: budgetLimit.active_days_left}) }}">({{ formatAmountBySymbol(budgetLimit.left / budgetLimit.active_days_left, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# if there is nothing left, just format 0.00 #}
|
||||
{% if not budgetLimit.in_past and -1 != bccomp('0',budgetLimit.left) %}
|
||||
({{ formatAmountBySymbol('0', budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||
<span title="{{ 'nothing_left_in_budget'|_ }}">({{ formatAmountBySymbol('0', budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})</span>
|
||||
{% endif %}
|
||||
</span><br />
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{# this is spent in budget limits: #}
|
||||
{% for budgetLimit in budget.budgeted %}
|
||||
{{ formatAmountBySymbol(budgetLimit.spent, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}
|
||||
<span title="{{ 'spent_this_period'|_ }}">{{ formatAmountBySymbol(budgetLimit.spent, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}</span>
|
||||
{% if 0 == budgetLimit.active_days_passed %}
|
||||
({{ formatAmountBySymbol(budgetLimit.spent, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||
<span title="{{ trans('firefly.spent_this_period_per_day', {days: 0}) }}">({{ formatAmountBySymbol(budgetLimit.spent, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})</span>
|
||||
{% else %}
|
||||
({{ formatAmountBySymbol(budgetLimit.spent / budgetLimit.active_days_passed, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||
<span title="{{ trans('firefly.spent_this_period_per_day', {days: budgetLimit.active_days_passed}) }}">({{ formatAmountBySymbol(budgetLimit.spent / budgetLimit.active_days_passed, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})</span>
|
||||
{% endif %}
|
||||
<br />
|
||||
{% endfor %}
|
||||
@@ -12,11 +12,11 @@
|
||||
{# this is spent NOT in budget limits: #}
|
||||
{% for spent in budget.spent %}
|
||||
{% if 0 != bccomp('0', spent.spent_outside) %}
|
||||
{{ formatAmountBySymbol(spent.spent_outside, spent.currency_symbol, spent.currency_decimal_places) }}
|
||||
<span title="{{ 'spent_in_budget_limit_outside_period'|_ }}">{{ formatAmountBySymbol(spent.spent_outside, spent.currency_symbol, spent.currency_decimal_places) }}</span>
|
||||
{% if 0 == activeDaysPassed %}
|
||||
({{ formatAmountBySymbol(spent.spent_outside, spent.currency_symbol, spent.currency_decimal_places) }})
|
||||
<span title="{{ trans('firefly.spent_in_budget_limit_outside_period_per_day', {days: 0}) }}">({{ formatAmountBySymbol(spent.spent_outside, spent.currency_symbol, spent.currency_decimal_places) }})</span>
|
||||
{% else %}
|
||||
({{ formatAmountBySymbol(spent.spent_outside / activeDaysPassed, spent.currency_symbol, spent.currency_decimal_places) }})
|
||||
<span title="{{ trans('firefly.spent_in_budget_limit_outside_period_per_day', {days: activeDaysPassed}) }}">({{ formatAmountBySymbol(spent.spent_outside / activeDaysPassed, spent.currency_symbol, spent.currency_decimal_places) }})</span>
|
||||
{% endif %}
|
||||
<br />
|
||||
{% endif %}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
{# language #}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_languages'|_ }}</h3>
|
||||
<p class="text-info">{{ 'pref_languages_help'|_ }}</p>
|
||||
<p>{{ 'pref_languages_help'|_ }}</p>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" id="lang_holder" name="language">
|
||||
@@ -63,7 +63,7 @@
|
||||
</div>
|
||||
|
||||
|
||||
<p class="text-info">
|
||||
<p>
|
||||
<br/>
|
||||
{{ 'pref_languages_locale'|_ }}
|
||||
</p>
|
||||
@@ -73,7 +73,8 @@
|
||||
{% if not isDocker %}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_locale'|_ }}</h3>
|
||||
<p class="text-info">{{ 'pref_locale_help'|_ }}</p>
|
||||
<p>{{ 'pref_locale_help'|_ }}</p>
|
||||
<p class="text-warning">{{ 'pref_locale_exception'|_ }}</p>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<select class="form-control" id="locale_holder" name="locale">
|
||||
@@ -104,7 +105,7 @@
|
||||
{# fiscal year #}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_custom_fiscal_year'|_ }}</h3>
|
||||
<p class="text-info">
|
||||
<p>
|
||||
{{ 'pref_custom_fiscal_year_help'|_ }}
|
||||
</p>
|
||||
{% set isCustomFiscalYear = customFiscalYear == 1 ? true : false %}
|
||||
@@ -116,7 +117,7 @@
|
||||
{% if fireflyiiiconfig('enable_exchange_rates', true) %}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_convert_to_primary'|_ }}</h3>
|
||||
<p class="text-info">
|
||||
<p>
|
||||
{{ 'pref_convert_to_primary_help'|_ }}
|
||||
</p>
|
||||
{{ ExpandedForm.checkbox('convertToPrimary','1',convertToPrimary,{ 'label' : 'pref_convert_primary_help'|_ }) }}
|
||||
@@ -125,7 +126,7 @@
|
||||
{# conversion back to primary currency #}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_anonymous'|_ }}</h3>
|
||||
<p class="text-info">
|
||||
<p>
|
||||
{{ 'pref_anonymous_help'|_ }}
|
||||
</p>
|
||||
{{ ExpandedForm.checkbox('anonymous','1',anonymous,{ 'label' : 'pref_anonymous_label'|_ }) }}
|
||||
@@ -138,7 +139,7 @@
|
||||
{# transaction preferences #}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_optional_fields_transaction'|_ }}</h3>
|
||||
<p class="text-info">
|
||||
<p>
|
||||
{{ 'pref_optional_fields_transaction_help'|_ }}
|
||||
</p>
|
||||
<h4>{{ 'optional_tj_date_fields'|_ }}</h4>
|
||||
@@ -169,7 +170,7 @@
|
||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_home_screen_accounts'|_ }}</h3>
|
||||
<p class="text-info">{{ 'pref_home_screen_accounts_help'|_ }}</p>
|
||||
<p>{{ 'pref_home_screen_accounts_help'|_ }}</p>
|
||||
{% for type, accounts in groupedAccounts %}
|
||||
<strong>{{ type }}</strong>
|
||||
{% for id, name in accounts %}
|
||||
@@ -206,7 +207,7 @@
|
||||
{# view range #}
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'pref_view_range'|_ }}</h3>
|
||||
<p class="text-info">{{ 'pref_view_range_help'|_ }}</p>
|
||||
<p>{{ 'pref_view_range_help'|_ }}</p>
|
||||
|
||||
<div class="radio">
|
||||
<label>
|
||||
@@ -311,12 +312,12 @@
|
||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'list_page_size_title'|_ }}</h3>
|
||||
<p class="text-info">{{ 'list_page_size_help'|_ }}</p>
|
||||
<p>{{ 'list_page_size_help'|_ }}</p>
|
||||
{{ ExpandedForm.integer('listPageSize',listPageSize,{'label' : 'list_page_size_label'|_}) }}
|
||||
</div>
|
||||
<div class="preferences-box">
|
||||
<h3>{{ 'dark_mode_preference'|_ }}</h3>
|
||||
<p class="text-info">{{ 'dark_mode_preference_help'|_ }}</p>
|
||||
<p>{{ 'dark_mode_preference_help'|_ }}</p>
|
||||
{% for mode in availableDarkModes %}
|
||||
<div class="radio">
|
||||
<label>
|
||||
|
||||
@@ -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