mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-08-17 16:35:20 -05:00
🤖 Auto commit for release 'develop' on 2026-01-10
This commit is contained in:
Generated
+6
-6
@@ -402,16 +402,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.92.4",
|
||||
"version": "v3.92.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "9e7488b19403423e02e8403cc1eb596baf4673b0"
|
||||
"reference": "260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/9e7488b19403423e02e8403cc1eb596baf4673b0",
|
||||
"reference": "9e7488b19403423e02e8403cc1eb596baf4673b0",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58",
|
||||
"reference": "260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -494,7 +494,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.4"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -502,7 +502,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-04T00:38:52+00:00"
|
||||
"time": "2026-01-08T21:57:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
Over time, many people have contributed to Firefly III. Their efforts are not always visible, but always remembered and appreciated.
|
||||
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
|
||||
|
||||
## 2026
|
||||
- embedded
|
||||
|
||||
## 2025
|
||||
- Diego Algorta
|
||||
- Jihad
|
||||
|
||||
@@ -784,20 +784,21 @@ trait MetaCollection
|
||||
$filter = static function (array $object) use ($list): bool {
|
||||
Log::debug(sprintf('Now in setTags(%s) filter', implode(', ', $list)));
|
||||
foreach ($object['transactions'] as $transaction) {
|
||||
$total = count($transaction['tags']);
|
||||
$total = count($transaction['tags']);
|
||||
$matched = 0;
|
||||
foreach ($transaction['tags'] as $tag) {
|
||||
Log::debug(sprintf('"%s" versus', strtolower((string) $tag['name'])), $list);
|
||||
if (in_array(strtolower((string) $tag['name']), $list, true)) {
|
||||
Log::debug(sprintf('Transaction has tag "%s" so return true.', $tag['name']));
|
||||
$matched++;
|
||||
if(1 === count($list)) {
|
||||
++$matched;
|
||||
if (1 === count($list)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count($list) > 1 && $total === $matched && $matched === count($list)) {
|
||||
if (count($list) > 1 && $total === $matched && $matched === count($list)) {
|
||||
Log::debug(sprintf('All %d searched tags are present.', $total));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use JsonException;
|
||||
use Safe\Exceptions\FilesystemException;
|
||||
|
||||
use function Safe\file_get_contents;
|
||||
use function Safe\json_decode;
|
||||
|
||||
@@ -78,16 +79,16 @@ class PreferencesController extends Controller
|
||||
* @throws FireflyException
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public function index(AccountRepositoryInterface $repository): Factory | \Illuminate\Contracts\View\View
|
||||
public function index(AccountRepositoryInterface $repository): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$accounts = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]);
|
||||
$isDocker = env('IS_DOCKER', false); // @phpstan-ignore-line
|
||||
$groupedAccounts = [];
|
||||
$accounts = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]);
|
||||
$isDocker = env('IS_DOCKER', false); // @phpstan-ignore-line
|
||||
$groupedAccounts = [];
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$type = $account->accountType->type;
|
||||
$role = sprintf('opt_group_%s', $repository->getMetaValue($account, 'account_role'));
|
||||
$type = $account->accountType->type;
|
||||
$role = sprintf('opt_group_%s', $repository->getMetaValue($account, 'account_role'));
|
||||
|
||||
if (in_array($type, [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value], true)) {
|
||||
$role = sprintf('opt_group_l_%s', $type);
|
||||
@@ -101,50 +102,50 @@ class PreferencesController extends Controller
|
||||
ksort($groupedAccounts);
|
||||
|
||||
/** @var array<int, int> $accountIds */
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
$viewRange = Navigation::getViewRange(false);
|
||||
$frontpageAccountsPref = Preferences::get('frontpageAccounts', $accountIds);
|
||||
$frontpageAccounts = $frontpageAccountsPref->data;
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
$viewRange = Navigation::getViewRange(false);
|
||||
$frontpageAccountsPref = Preferences::get('frontpageAccounts', $accountIds);
|
||||
$frontpageAccounts = $frontpageAccountsPref->data;
|
||||
if (!is_array($frontpageAccounts)) {
|
||||
$frontpageAccounts = $accountIds;
|
||||
}
|
||||
$language = Steam::getLanguage();
|
||||
$languages = config('firefly.languages');
|
||||
$locale = Preferences::get('locale', config('firefly.default_locale', 'equal'))->data;
|
||||
$listPageSize = Preferences::get('listPageSize', 50)->data;
|
||||
$darkMode = Preferences::get('darkMode', 'browser')->data;
|
||||
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
|
||||
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
|
||||
$convertToPrimary = $this->convertToPrimary;
|
||||
$language = Steam::getLanguage();
|
||||
$languages = config('firefly.languages');
|
||||
$locale = Preferences::get('locale', config('firefly.default_locale', 'equal'))->data;
|
||||
$listPageSize = Preferences::get('listPageSize', 50)->data;
|
||||
$darkMode = Preferences::get('darkMode', 'browser')->data;
|
||||
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
|
||||
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
|
||||
$convertToPrimary = $this->convertToPrimary;
|
||||
if (is_array($fiscalYearStartStr)) {
|
||||
$fiscalYearStartStr = '01-01';
|
||||
}
|
||||
$fiscalYearStart = sprintf('%s-%s', Carbon::now()->format('Y'), (string)$fiscalYearStartStr);
|
||||
$tjOptionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
|
||||
$availableDarkModes = config('firefly.available_dark_modes');
|
||||
$fiscalYearStart = sprintf('%s-%s', Carbon::now()->format('Y'), (string)$fiscalYearStartStr);
|
||||
$tjOptionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
|
||||
$availableDarkModes = config('firefly.available_dark_modes');
|
||||
|
||||
// notifications settings
|
||||
$slackUrl = Preferences::getEncrypted('slack_webhook_url', '')->data;
|
||||
$pushoverAppToken = (string)Preferences::getEncrypted('pushover_app_token', '')->data;
|
||||
$pushoverUserToken = (string)Preferences::getEncrypted('pushover_user_token', '')->data;
|
||||
$ntfyServer = Preferences::getEncrypted('ntfy_server', 'https://ntfy.sh')->data;
|
||||
$ntfyTopic = (string)Preferences::getEncrypted('ntfy_topic', '')->data;
|
||||
$ntfyAuth = '1' === Preferences::get('ntfy_auth', false)->data;
|
||||
$ntfyUser = Preferences::getEncrypted('ntfy_user', '')->data;
|
||||
$ntfyPass = (string)Preferences::getEncrypted('ntfy_pass', '')->data;
|
||||
$channels = config('notifications.channels');
|
||||
$forcedAvailability = [];
|
||||
$anonymous = Steam::anonymous();
|
||||
$slackUrl = Preferences::getEncrypted('slack_webhook_url', '')->data;
|
||||
$pushoverAppToken = (string)Preferences::getEncrypted('pushover_app_token', '')->data;
|
||||
$pushoverUserToken = (string)Preferences::getEncrypted('pushover_user_token', '')->data;
|
||||
$ntfyServer = Preferences::getEncrypted('ntfy_server', 'https://ntfy.sh')->data;
|
||||
$ntfyTopic = (string)Preferences::getEncrypted('ntfy_topic', '')->data;
|
||||
$ntfyAuth = '1' === Preferences::get('ntfy_auth', false)->data;
|
||||
$ntfyUser = Preferences::getEncrypted('ntfy_user', '')->data;
|
||||
$ntfyPass = (string)Preferences::getEncrypted('ntfy_pass', '')->data;
|
||||
$channels = config('notifications.channels');
|
||||
$forcedAvailability = [];
|
||||
$anonymous = Steam::anonymous();
|
||||
|
||||
// notification preferences
|
||||
$notifications = [];
|
||||
$notifications = [];
|
||||
foreach (config('notifications.notifications.user') as $key => $info) {
|
||||
if (true === $info['enabled']) {
|
||||
$notifications[$key]
|
||||
= [
|
||||
'enabled' => true === Preferences::get(sprintf('notification_%s', $key), true)->data,
|
||||
'configurable' => $info['configurable'],
|
||||
];
|
||||
'enabled' => true === Preferences::get(sprintf('notification_%s', $key), true)->data,
|
||||
'configurable' => $info['configurable'],
|
||||
];
|
||||
}
|
||||
}
|
||||
// loop all channels to see if they are available.
|
||||
@@ -164,7 +165,7 @@ class PreferencesController extends Controller
|
||||
Log::error($e->getMessage());
|
||||
$locales = [];
|
||||
}
|
||||
$locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales;
|
||||
$locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales;
|
||||
// an important fallback is that the frontPageAccount array gets refilled automatically
|
||||
// when it turns up empty.
|
||||
if (0 === count($frontpageAccounts)) {
|
||||
@@ -195,7 +196,7 @@ class PreferencesController extends Controller
|
||||
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
|
||||
* @SuppressWarnings("PHPMD.NPathComplexity")
|
||||
*/
|
||||
public function postIndex(PreferencesRequest $request): Redirector | RedirectResponse
|
||||
public function postIndex(PreferencesRequest $request): Redirector|RedirectResponse
|
||||
{
|
||||
Log::debug('postIndex for preferences.');
|
||||
// front page accounts
|
||||
@@ -209,7 +210,7 @@ class PreferencesController extends Controller
|
||||
}
|
||||
|
||||
// extract notifications:
|
||||
$all = $request->all();
|
||||
$all = $request->all();
|
||||
foreach (config('notifications.notifications.user') as $key => $info) {
|
||||
$key = sprintf('notification_%s', $key);
|
||||
if (array_key_exists($key, $all)) {
|
||||
@@ -246,7 +247,7 @@ class PreferencesController extends Controller
|
||||
}
|
||||
|
||||
// convert primary
|
||||
$convertToPrimary = 1 === (int)$request->get('convertToPrimary');
|
||||
$convertToPrimary = 1 === (int)$request->get('convertToPrimary');
|
||||
if ($convertToPrimary && !$this->convertToPrimary) {
|
||||
// set to true!
|
||||
Log::debug('User sets convertToPrimary to true.');
|
||||
@@ -258,9 +259,9 @@ class PreferencesController extends Controller
|
||||
Preferences::set('convert_to_primary', $convertToPrimary);
|
||||
|
||||
// custom fiscal year
|
||||
$customFiscalYear = 1 === (int)$request->get('customFiscalYear');
|
||||
$customFiscalYear = 1 === (int)$request->get('customFiscalYear');
|
||||
Preferences::set('customFiscalYear', $customFiscalYear);
|
||||
$fiscalYearString = (string)$request->get('fiscalYearStart');
|
||||
$fiscalYearString = (string)$request->get('fiscalYearStart');
|
||||
if ('' !== $fiscalYearString) {
|
||||
$fiscalYearStart = Carbon::parse($fiscalYearString, config('app.timezone'))->format('m-d');
|
||||
Preferences::set('fiscalYearStart', $fiscalYearStart);
|
||||
@@ -268,15 +269,15 @@ class PreferencesController extends Controller
|
||||
|
||||
// save page size:
|
||||
Preferences::set('listPageSize', 50);
|
||||
$listPageSize = (int)$request->get('listPageSize');
|
||||
$listPageSize = (int)$request->get('listPageSize');
|
||||
if ($listPageSize > 0 && $listPageSize < 1337) {
|
||||
Preferences::set('listPageSize', $listPageSize);
|
||||
}
|
||||
|
||||
// language:
|
||||
/** @var Preference $currentLang */
|
||||
$currentLang = Preferences::get('language', 'en_US');
|
||||
$lang = $request->get('language');
|
||||
$currentLang = Preferences::get('language', 'en_US');
|
||||
$lang = $request->get('language');
|
||||
if (array_key_exists($lang, config('firefly.languages'))) {
|
||||
Preferences::set('language', $lang);
|
||||
}
|
||||
@@ -293,8 +294,8 @@ class PreferencesController extends Controller
|
||||
}
|
||||
|
||||
// optional fields for transactions:
|
||||
$setOptions = $request->get('tj') ?? [];
|
||||
$optionalTj = [
|
||||
$setOptions = $request->get('tj') ?? [];
|
||||
$optionalTj = [
|
||||
'interest_date' => array_key_exists('interest_date', $setOptions),
|
||||
'book_date' => array_key_exists('book_date', $setOptions),
|
||||
'process_date' => array_key_exists('process_date', $setOptions),
|
||||
@@ -311,13 +312,13 @@ class PreferencesController extends Controller
|
||||
Preferences::set('transaction_journal_optional_fields', $optionalTj);
|
||||
|
||||
// dark mode
|
||||
$darkMode = $request->get('darkMode') ?? 'browser';
|
||||
$darkMode = $request->get('darkMode') ?? 'browser';
|
||||
if (in_array($darkMode, config('firefly.available_dark_modes'), true)) {
|
||||
Preferences::set('darkMode', $darkMode);
|
||||
}
|
||||
|
||||
// anonymous amounts?
|
||||
$anonymous = '1' === $request->get('anonymous');
|
||||
$anonymous = '1' === $request->get('anonymous');
|
||||
Preferences::set('anonymous', $anonymous);
|
||||
|
||||
// save and continue
|
||||
|
||||
@@ -58,7 +58,7 @@ class AcceptHeaders
|
||||
// some routes are exempt from this.
|
||||
$exempt = [
|
||||
'api.v1.data.bulk.transactions',
|
||||
'api.v1.attachments.upload'
|
||||
'api.v1.attachments.upload',
|
||||
];
|
||||
|
||||
if (('POST' === $method || 'PUT' === $method) && !$request->hasHeader('Content-Type') && !in_array($request->route()->getName(), $exempt, true)) {
|
||||
|
||||
@@ -50,6 +50,7 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* Class BillRepository.
|
||||
@@ -66,7 +67,8 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
$search->whereLike('name', sprintf('%%%s', $query));
|
||||
}
|
||||
$search->orderBy('name', 'ASC')
|
||||
->where('active', true);
|
||||
->where('active', true)
|
||||
;
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
@@ -78,7 +80,8 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
$search->whereLike('name', sprintf('%s%%', $query));
|
||||
}
|
||||
$search->orderBy('name', 'ASC')
|
||||
->where('active', true);
|
||||
->where('active', true)
|
||||
;
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
@@ -180,9 +183,10 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function getBills(): Collection
|
||||
{
|
||||
return $this->user->bills()
|
||||
->orderBy('order', 'ASC')
|
||||
->orderBy('active', 'DESC')
|
||||
->orderBy('name', 'ASC')->get();
|
||||
->orderBy('order', 'ASC')
|
||||
->orderBy('active', 'DESC')
|
||||
->orderBy('name', 'ASC')->get()
|
||||
;
|
||||
}
|
||||
|
||||
public function getBillsForAccounts(Collection $accounts): Collection
|
||||
@@ -206,24 +210,25 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
|
||||
return $this->user->bills()
|
||||
->leftJoin(
|
||||
'transaction_journals',
|
||||
static function (JoinClause $join): void {
|
||||
$join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions',
|
||||
static function (JoinClause $join): void {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->whereIn('transactions.account_id', $ids)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->orderBy('bills.active', 'DESC')
|
||||
->orderBy('bills.name', 'ASC')
|
||||
->groupBy($fields)
|
||||
->get($fields);
|
||||
->leftJoin(
|
||||
'transaction_journals',
|
||||
static function (JoinClause $join): void {
|
||||
$join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions',
|
||||
static function (JoinClause $join): void {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->whereIn('transactions.account_id', $ids)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->orderBy('bills.active', 'DESC')
|
||||
->orderBy('bills.name', 'ASC')
|
||||
->groupBy($fields)
|
||||
->get($fields)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +253,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function getOverallAverage(Bill $bill): array
|
||||
{
|
||||
/** @var JournalRepositoryInterface $repos */
|
||||
$repos = app(JournalRepositoryInterface::class);
|
||||
$repos = app(JournalRepositoryInterface::class);
|
||||
$repos->setUser($this->user);
|
||||
|
||||
// get and sort on currency
|
||||
@@ -261,7 +266,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
$currencyId = (int)$journal->transaction_currency_id;
|
||||
$currency = $journal->transactionCurrency;
|
||||
$result[$currencyId] ??= [
|
||||
$result[$currencyId] ??= [
|
||||
'sum' => '0',
|
||||
'pc_sum' => '0',
|
||||
'count' => 0,
|
||||
@@ -296,8 +301,9 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function getPaginator(int $size): LengthAwarePaginator
|
||||
{
|
||||
return $this->user->bills()
|
||||
->orderBy('active', 'DESC')
|
||||
->orderBy('name', 'ASC')->paginate($size);
|
||||
->orderBy('active', 'DESC')
|
||||
->orderBy('name', 'ASC')->paginate($size)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,11 +316,11 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
Log::debug(sprintf('Search for linked journals between %s and %s', $start->toW3cString(), $end->toW3cString()));
|
||||
|
||||
return $bill->transactionJournals()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_currencies AS currency', 'currency.id', '=', 'transactions.transaction_currency_id')
|
||||
->leftJoin('transaction_currencies AS foreign_currency', 'foreign_currency.id', '=', 'transactions.foreign_currency_id')
|
||||
->where('transactions.amount', '>', 0)
|
||||
->before($end)->after($start)->get(
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_currencies AS currency', 'currency.id', '=', 'transactions.transaction_currency_id')
|
||||
->leftJoin('transaction_currencies AS foreign_currency', 'foreign_currency.id', '=', 'transactions.foreign_currency_id')
|
||||
->where('transactions.amount', '>', 0)
|
||||
->before($end)->after($start)->get(
|
||||
[
|
||||
'transaction_journals.id',
|
||||
'transaction_journals.date',
|
||||
@@ -328,7 +334,8 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
'transactions.amount',
|
||||
'transactions.foreign_amount',
|
||||
]
|
||||
);
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,10 +344,11 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function getRulesForBill(Bill $bill): Collection
|
||||
{
|
||||
return $this->user->rules()
|
||||
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
||||
->where('rule_actions.action_type', 'link_to_bill')
|
||||
->where('rule_actions.action_value', $bill->name)
|
||||
->get(['rules.*']);
|
||||
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
||||
->where('rule_actions.action_type', 'link_to_bill')
|
||||
->where('rule_actions.action_value', $bill->name)
|
||||
->get(['rules.*'])
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,15 +359,16 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
*/
|
||||
public function getRulesForBills(Collection $collection): array
|
||||
{
|
||||
$rules = $this->user->rules()
|
||||
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
||||
->where('rule_actions.action_type', 'link_to_bill')
|
||||
->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active']);
|
||||
$array = [];
|
||||
$rules = $this->user->rules()
|
||||
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
||||
->where('rule_actions.action_type', 'link_to_bill')
|
||||
->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active'])
|
||||
;
|
||||
$array = [];
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$array[$rule->action_value] ??= [];
|
||||
$array[$rule->action_value] ??= [];
|
||||
$array[$rule->action_value][] = ['id' => $rule->id, 'title' => $rule->title, 'active' => $rule->active];
|
||||
}
|
||||
$return = [];
|
||||
@@ -373,27 +382,28 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function getYearAverage(Bill $bill, Carbon $date): array
|
||||
{
|
||||
/** @var JournalRepositoryInterface $repos */
|
||||
$repos = app(JournalRepositoryInterface::class);
|
||||
$repos = app(JournalRepositoryInterface::class);
|
||||
$repos->setUser($this->user);
|
||||
|
||||
// get and sort on currency
|
||||
$result = [];
|
||||
$result = [];
|
||||
|
||||
$journals = $bill->transactionJournals()
|
||||
->where('date', '>=', $date->year . '-01-01 00:00:00')
|
||||
->where('date', '<=', $date->year . '-12-31 23:59:59')
|
||||
->get();
|
||||
->where('date', '>=', $date->year.'-01-01 00:00:00')
|
||||
->where('date', '<=', $date->year.'-12-31 23:59:59')
|
||||
->get()
|
||||
;
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
/** @var null|Transaction $transaction */
|
||||
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
if (null === $transaction) {
|
||||
continue;
|
||||
}
|
||||
$currencyId = (int)$journal->transaction_currency_id;
|
||||
$currency = $journal->transactionCurrency;
|
||||
$result[$currencyId] ??= [
|
||||
$result[$currencyId] ??= [
|
||||
'sum' => '0',
|
||||
'pc_sum' => '0',
|
||||
'count' => 0,
|
||||
@@ -443,7 +453,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
*/
|
||||
public function nextExpectedMatch(Bill $bill, Carbon $date): Carbon
|
||||
{
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($bill->id);
|
||||
$cache->addProperty('nextExpectedMatch');
|
||||
$cache->addProperty($date);
|
||||
@@ -451,17 +461,17 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
return $cache->get();
|
||||
}
|
||||
// find the most recent date for this bill NOT in the future. Cache this date:
|
||||
$start = clone $bill->date;
|
||||
$start = clone $bill->date;
|
||||
$start->startOfDay();
|
||||
Log::debug('nextExpectedMatch: Start is ' . $start->format('Y-m-d'));
|
||||
Log::debug('nextExpectedMatch: Start is '.$start->format('Y-m-d'));
|
||||
|
||||
while ($start < $date) {
|
||||
Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d H:i:s'), $date->format('Y-m-d H:i:s')));
|
||||
$start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||
Log::debug('Start is now ' . $start->format('Y-m-d H:i:s'));
|
||||
Log::debug('Start is now '.$start->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||
$end->endOfDay();
|
||||
|
||||
// see if the bill was paid in this period.
|
||||
@@ -473,8 +483,8 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
$start = clone $end;
|
||||
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||
}
|
||||
Log::debug('nextExpectedMatch: Final start is ' . $start->format('Y-m-d'));
|
||||
Log::debug('nextExpectedMatch: Matching end is ' . $end->format('Y-m-d'));
|
||||
Log::debug('nextExpectedMatch: Final start is '.$start->format('Y-m-d'));
|
||||
Log::debug('nextExpectedMatch: Matching end is '.$end->format('Y-m-d'));
|
||||
|
||||
$cache->store($start);
|
||||
|
||||
@@ -535,8 +545,8 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
foreach ($bills as $bill) {
|
||||
|
||||
/** @var Collection $set */
|
||||
$set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']);
|
||||
$currency = $convertToPrimary && $bill->transactionCurrency->id !== $primary->id ? $primary : $bill->transactionCurrency;
|
||||
$set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']);
|
||||
$currency = $convertToPrimary && $bill->transactionCurrency->id !== $primary->id ? $primary : $bill->transactionCurrency;
|
||||
$return[(int)$currency->id] ??= [
|
||||
'id' => (string)$currency->id,
|
||||
'name' => $currency->name,
|
||||
@@ -545,12 +555,12 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
'decimal_places' => $currency->decimal_places,
|
||||
'sum' => '0',
|
||||
];
|
||||
$setAmount = '0';
|
||||
$setAmount = '0';
|
||||
|
||||
/** @var TransactionJournal $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
// grab currency from transaction.
|
||||
$transactionCurrency = $transactionJournal->transactionCurrency;
|
||||
$transactionCurrency = $transactionJournal->transactionCurrency;
|
||||
$return[(int)$transactionCurrency->id] ??= [
|
||||
'id' => (string)$transactionCurrency->id,
|
||||
'name' => $transactionCurrency->name,
|
||||
@@ -569,7 +579,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
// Log::debug(sprintf('Total sum is now %s', $return[$currency->id]['sum']));
|
||||
}
|
||||
// remove empty sets
|
||||
$final = [];
|
||||
$final = [];
|
||||
foreach ($return as $entry) {
|
||||
if (0 === bccomp($entry['sum'], '0')) {
|
||||
continue;
|
||||
@@ -583,10 +593,10 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function getActiveBills(): Collection
|
||||
{
|
||||
return $this->user->bills()
|
||||
->where('active', true)
|
||||
->orderBy('bills.name', 'ASC')
|
||||
->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line
|
||||
;
|
||||
->where('active', true)
|
||||
->orderBy('bills.name', 'ASC')
|
||||
->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line
|
||||
;
|
||||
}
|
||||
|
||||
public function sumUnpaidInRange(Carbon $start, Carbon $end): array
|
||||
@@ -600,9 +610,9 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
// \Illuminate\Support\Facades\Log::debug(sprintf('Processing bill #%d ("%s")', $bill->id, $bill->name));
|
||||
$dates = $this->getPayDatesInRange($bill, $start, $end);
|
||||
$count = $bill->transactionJournals()->after($start)->before($end)->count();
|
||||
$total = $dates->count() - $count;
|
||||
$dates = $this->getPayDatesInRange($bill, $start, $end);
|
||||
$count = $bill->transactionJournals()->after($start)->before($end)->count();
|
||||
$total = $dates->count() - $count;
|
||||
// \Illuminate\Support\Facades\Log::debug(sprintf('Pay dates: %d, count: %d, left: %d', $dates->count(), $count, $total));
|
||||
// \Illuminate\Support\Facades\Log::debug('dates', $dates->toArray());
|
||||
|
||||
@@ -611,10 +621,10 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
// Log::debug(sprintf('min field is %s, max field is %s', $minField, $maxField));
|
||||
|
||||
if ($total > 0) {
|
||||
$currency = $convertToPrimary && $bill->transactionCurrency->id !== $primary->id ? $primary : $bill->transactionCurrency;
|
||||
$average = bcdiv(bcadd($bill->{$maxField} ?? '0', $bill->{$minField} ?? '0'), '2');
|
||||
$currency = $convertToPrimary && $bill->transactionCurrency->id !== $primary->id ? $primary : $bill->transactionCurrency;
|
||||
$average = bcdiv(bcadd($bill->{$maxField} ?? '0', $bill->{$minField} ?? '0'), '2');
|
||||
Log::debug(sprintf('Amount to pay is %s %s (%d times)', $currency->code, $average, $total));
|
||||
$return[$currency->id] ??= [
|
||||
$return[$currency->id] ??= [
|
||||
'id' => (string)$currency->id,
|
||||
'name' => $currency->name,
|
||||
'symbol' => $currency->symbol,
|
||||
@@ -652,7 +662,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
|
||||
// \Illuminate\Support\Facades\Log::debug(sprintf('Currentstart (%s) has become %s.', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d')));
|
||||
|
||||
$currentStart = clone $nextExpectedMatch;
|
||||
$currentStart = clone $nextExpectedMatch;
|
||||
}
|
||||
|
||||
return $set;
|
||||
@@ -698,7 +708,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
return $service->update($bill, $data);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
#[Override]
|
||||
public function correctTransfers(): void
|
||||
{
|
||||
/** @var null|TransactionType $withdrawal */
|
||||
|
||||
@@ -53,6 +53,7 @@ interface BillRepositoryInterface
|
||||
* Add correct order to bills.
|
||||
*/
|
||||
public function correctOrder(): void;
|
||||
|
||||
public function correctTransfers(): void;
|
||||
|
||||
public function destroy(Bill $bill): bool;
|
||||
|
||||
@@ -417,10 +417,11 @@ trait RenderPartialViews
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$tags = $repository->get();
|
||||
|
||||
$grouped = [];
|
||||
$grouped = [];
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach($tags as $tag) {
|
||||
$year = (int) $tag->date?->year;
|
||||
foreach ($tags as $tag) {
|
||||
$year = (int) $tag->date?->year;
|
||||
$grouped[$year] ??= [
|
||||
'tags' => [],
|
||||
'year' => 0 === $year ? trans('firefly.no_date') : $year,
|
||||
@@ -428,6 +429,7 @@ trait RenderPartialViews
|
||||
$grouped[$year]['tags'][] = $tag;
|
||||
}
|
||||
ksort($grouped);
|
||||
|
||||
try {
|
||||
$result = view('reports.options.tag', ['tags' => $grouped])->render();
|
||||
} catch (Throwable $e) {
|
||||
|
||||
@@ -46,19 +46,20 @@ class LinkToBill implements ActionInterface
|
||||
public function actOnArray(array $journal): bool
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = User::find($journal['user_id']);
|
||||
$user = User::find($journal['user_id']);
|
||||
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
$billName = $this->action->getValue($journal);
|
||||
$bill = $repository->findByName($billName);
|
||||
$billName = $this->action->getValue($journal);
|
||||
$bill = $repository->findByName($billName);
|
||||
|
||||
/** @var TransactionJournal $object */
|
||||
$object = TransactionJournal::with('transactionType')->find($journal['transaction_journal_id']);
|
||||
$type = $object->transactionType->type;
|
||||
$object = TransactionJournal::with('transactionType')->find($journal['transaction_journal_id']);
|
||||
$type = $object->transactionType->type;
|
||||
|
||||
if (null !== $bill && TransactionTypeEnum::WITHDRAWAL->value === $type) {
|
||||
$count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id'])->where('bill_id', $bill->id)->count();
|
||||
$count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id'])->where('bill_id', $bill->id)->count();
|
||||
if (0 !== $count) {
|
||||
Log::error(sprintf('RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": already set.', $journal['transaction_journal_id'], $billName));
|
||||
// event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_linked_to_subscription', ['name' => $billName])));
|
||||
|
||||
@@ -143,8 +143,9 @@ class ActionExpression
|
||||
private function evaluateExpression(string $expr, array $journal): string
|
||||
{
|
||||
$result = $this->expressionLanguage->evaluate($expr, $journal);
|
||||
if(is_array($result)) {
|
||||
if (is_array($result)) {
|
||||
Log::error('Result of evaluating the expression is an array, please investigate', $result);
|
||||
|
||||
throw new FireflyException('Result of evaluating the expression is an array, please open a GitHub issue about this and include the error logs.');
|
||||
}
|
||||
|
||||
|
||||
@@ -457,9 +457,9 @@ class FireflyValidator extends Validator
|
||||
*
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function validateSecurePassword($attribute, string|null $value): bool
|
||||
public function validateSecurePassword($attribute, ?string $value): bool
|
||||
{
|
||||
$value = (string)$value;
|
||||
$value = (string)$value;
|
||||
$verify = false;
|
||||
if (array_key_exists('verify_password', $this->data)) {
|
||||
$verify = 1 === (int) $this->data['verify_password'];
|
||||
@@ -468,7 +468,7 @@ class FireflyValidator extends Validator
|
||||
/** @var Verifier $service */
|
||||
$service = app(Verifier::class);
|
||||
|
||||
return $service->validPassword( $value);
|
||||
return $service->validPassword($value);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Generated
+10
-10
@@ -1878,16 +1878,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.45.0",
|
||||
"version": "v12.46.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "9dfd2afc48f2519bfdbe6862dfb9849491c673ad"
|
||||
"reference": "9dcff48d25a632c1fadb713024c952fec489c4ae"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/9dfd2afc48f2519bfdbe6862dfb9849491c673ad",
|
||||
"reference": "9dfd2afc48f2519bfdbe6862dfb9849491c673ad",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/9dcff48d25a632c1fadb713024c952fec489c4ae",
|
||||
"reference": "9dcff48d25a632c1fadb713024c952fec489c4ae",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2096,7 +2096,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2026-01-06T15:24:52+00:00"
|
||||
"time": "2026-01-07T23:26:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
@@ -2235,16 +2235,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/sanctum",
|
||||
"version": "v4.2.1",
|
||||
"version": "v4.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/sanctum.git",
|
||||
"reference": "f5fb373be39a246c74a060f2cf2ae2c2145b3664"
|
||||
"reference": "fd447754d2d3f56950d53b930128af2e3b617de9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/sanctum/zipball/f5fb373be39a246c74a060f2cf2ae2c2145b3664",
|
||||
"reference": "f5fb373be39a246c74a060f2cf2ae2c2145b3664",
|
||||
"url": "https://api.github.com/repos/laravel/sanctum/zipball/fd447754d2d3f56950d53b930128af2e3b617de9",
|
||||
"reference": "fd447754d2d3f56950d53b930128af2e3b617de9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2294,7 +2294,7 @@
|
||||
"issues": "https://github.com/laravel/sanctum/issues",
|
||||
"source": "https://github.com/laravel/sanctum"
|
||||
},
|
||||
"time": "2025-11-21T13:59:03+00:00"
|
||||
"time": "2026-01-06T23:11:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
|
||||
+2
-2
@@ -78,8 +78,8 @@ return [
|
||||
'running_balance_column' => (bool)envNonEmpty('USE_RUNNING_BALANCE', true), // this is only the default value, is not used.
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => '6.4.15',
|
||||
'build_time' => 1767729818,
|
||||
'version' => 'develop/2026-01-10',
|
||||
'build_time' => 1768053746,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 28, // field is no longer used.
|
||||
|
||||
|
||||
Generated
+21
-21
@@ -3092,9 +3092,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express-serve-static-core": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.0.tgz",
|
||||
"integrity": "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz",
|
||||
"integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3105,9 +3105,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express/node_modules/@types/express-serve-static-core": {
|
||||
"version": "4.19.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz",
|
||||
"integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==",
|
||||
"version": "4.19.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
|
||||
"integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3218,9 +3218,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
|
||||
"integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
|
||||
"version": "25.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.5.tgz",
|
||||
"integrity": "sha512-FuLxeLuSVOqHPxSN1fkcD8DLU21gAP7nCKqGRJ/FglbCUBs0NYN6TpHcdmyLeh8C0KwGIaZQJSv+OYG+KZz+Gw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4117,9 +4117,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.9.11",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
|
||||
"integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
|
||||
"version": "2.9.14",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz",
|
||||
"integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -4550,9 +4550,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001762",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz",
|
||||
"integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==",
|
||||
"version": "1.0.30001763",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001763.tgz",
|
||||
"integrity": "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -7093,9 +7093,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "25.7.3",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.3.tgz",
|
||||
"integrity": "sha512-2XaT+HpYGuc2uTExq9TVRhLsso+Dxym6PWaKpn36wfBmTI779OQ7iP/XaZHzrnGyzU4SHpFrTYLKfVyBfAhVNA==",
|
||||
"version": "25.7.4",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.4.tgz",
|
||||
"integrity": "sha512-hRkpEblXXcXSNbw8mBNq9042OEetgyB/ahc/X17uV/khPwzV+uB8RHceHh3qavyrkPJvmXFKXME2Sy1E0KjAfw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -11462,9 +11462,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
|
||||
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
|
||||
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
Reference in New Issue
Block a user