mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-03-17 02:50:22 +00:00
Compare commits
5 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae3d0a3e49 | ||
|
|
61e8d7d7a2 | ||
|
|
62c5440605 | ||
|
|
0aa90b9453 | ||
|
|
855bc2f8e7 |
96
.ci/php-cs-fixer/composer.lock
generated
96
.ci/php-cs-fixer/composer.lock
generated
@@ -402,16 +402,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.87.2",
|
||||
"version": "v3.88.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "da5f0a7858c79b56fc0b8c36d3efcfe5f37f0992"
|
||||
"reference": "f23469674ae50d40e398bfff8018911a2a2b0dbe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/da5f0a7858c79b56fc0b8c36d3efcfe5f37f0992",
|
||||
"reference": "da5f0a7858c79b56fc0b8c36d3efcfe5f37f0992",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/f23469674ae50d40e398bfff8018911a2a2b0dbe",
|
||||
"reference": "f23469674ae50d40e398bfff8018911a2a2b0dbe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -438,12 +438,13 @@
|
||||
"symfony/polyfill-mbstring": "^1.33",
|
||||
"symfony/polyfill-php80": "^1.33",
|
||||
"symfony/polyfill-php81": "^1.33",
|
||||
"symfony/polyfill-php84": "^1.33",
|
||||
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2",
|
||||
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.7",
|
||||
"infection/infection": "^0.29.14",
|
||||
"infection/infection": "^0.31.0",
|
||||
"justinrainbow/json-schema": "^6.5",
|
||||
"keradus/cli-executor": "^2.2",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
@@ -451,7 +452,6 @@
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
||||
"phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34",
|
||||
"symfony/polyfill-php84": "^1.33",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2"
|
||||
},
|
||||
@@ -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.87.2"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -502,7 +502,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-10T09:51:40+00:00"
|
||||
"time": "2025-09-24T21:31:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -2283,6 +2283,86 @@
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php84",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php84.git",
|
||||
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
|
||||
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
|
||||
"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\\Php84\\": ""
|
||||
},
|
||||
"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.4+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php84/tree/v1.33.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": "2025-06-24T13:30:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v7.3.3",
|
||||
|
||||
@@ -158,18 +158,23 @@ class ShowController extends Controller
|
||||
Log::debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
|
||||
Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id));
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser(auth()->user());
|
||||
|
||||
// tell the generator which trigger it should look for
|
||||
$engine->setTrigger(WebhookTrigger::tryFrom($webhook->trigger));
|
||||
// tell the generator which objects to process
|
||||
$engine->setObjects(new Collection()->push($group));
|
||||
// set the webhook to trigger
|
||||
$engine->setWebhooks(new Collection()->push($webhook));
|
||||
// tell the generator to generate the messages
|
||||
$engine->generateMessages();
|
||||
/** @var \FireflyIII\Models\WebhookTrigger $trigger */
|
||||
foreach ($webhook->webhookTriggers as $trigger) {
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser(auth()->user());
|
||||
|
||||
// tell the generator which trigger it should look for
|
||||
$engine->setTrigger(WebhookTrigger::tryFrom((int)$trigger->key));
|
||||
// tell the generator which objects to process
|
||||
$engine->setObjects(new Collection()->push($group));
|
||||
// set the webhook to trigger
|
||||
$engine->setWebhooks(new Collection()->push($webhook));
|
||||
// tell the generator to generate the messages
|
||||
$engine->generateMessages();
|
||||
}
|
||||
|
||||
|
||||
// trigger event to send them:
|
||||
Log::debug('send event RequestedSendWebhookMessages from ShowController::triggerTransaction()');
|
||||
|
||||
@@ -86,6 +86,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
|
||||
return $this->handleAttachment($request, $e);
|
||||
|
||||
case 'bills.show':
|
||||
case 'subscriptions.show':
|
||||
$request->session()->reflash();
|
||||
|
||||
return redirect(route('bills.index'));
|
||||
|
||||
@@ -241,4 +241,11 @@ class Account extends Model
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
public function primaryPeriodStatistics(): MorphMany
|
||||
{
|
||||
|
||||
return $this->morphMany(PeriodStatistic::class, 'primary_statable');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
58
app/Models/PeriodStatistic.php
Normal file
58
app/Models/PeriodStatistic.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class PeriodStatistic extends Model
|
||||
{
|
||||
use ReturnsIntegerUserIdTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
];
|
||||
}
|
||||
|
||||
protected function count(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
public function primaryStatable(): MorphTo
|
||||
{
|
||||
|
||||
return $this->morphTo();
|
||||
|
||||
}
|
||||
|
||||
public function secondaryStatable(): MorphTo
|
||||
{
|
||||
|
||||
return $this->morphTo();
|
||||
|
||||
}
|
||||
|
||||
public function tertiaryStatable(): MorphTo
|
||||
{
|
||||
|
||||
return $this->morphTo();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -43,6 +43,8 @@ use FireflyIII\Repositories\AuditLogEntry\ALERepository;
|
||||
use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepository;
|
||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
||||
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepository;
|
||||
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface;
|
||||
use FireflyIII\Repositories\TransactionType\TransactionTypeRepository;
|
||||
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepository;
|
||||
@@ -161,6 +163,7 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
|
||||
$this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class);
|
||||
$this->app->bind(ALERepositoryInterface::class, ALERepository::class);
|
||||
$this->app->bind(PeriodStatisticRepositoryInterface::class, PeriodStatisticRepository::class);
|
||||
|
||||
$this->app->bind(
|
||||
static function (Application $app): ObjectGroupRepositoryInterface {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* PeriodStatisticRepository.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Repositories\PeriodStatistic;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PeriodStatistic;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class PeriodStatisticRepository implements PeriodStatisticRepositoryInterface
|
||||
{
|
||||
public function findPeriodStatistics(Model $model, Carbon $start, Carbon $end, array $types): Collection
|
||||
{
|
||||
return $model->primaryPeriodStatistics()
|
||||
->where('start', $start)
|
||||
->where('end', $end)
|
||||
->whereIn('type', $types)
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
public function findPeriodStatistic(Model $model, Carbon $start, Carbon $end, string $type): Collection
|
||||
{
|
||||
return $model->primaryPeriodStatistics()
|
||||
->where('start', $start)
|
||||
->where('end', $end)
|
||||
->where('type', $type)
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
public function saveStatistic(Model $model, int $currencyId, Carbon $start, Carbon $end, string $type, int $count, string $amount): PeriodStatistic
|
||||
{
|
||||
$stat = new PeriodStatistic();
|
||||
$stat->primaryStatable()->associate($model);
|
||||
$stat->transaction_currency_id = $currencyId;
|
||||
$stat->start = $start;
|
||||
$stat->start_tz = $start->format('e');
|
||||
$stat->end = $end;
|
||||
$stat->end_tz = $end->format('e');
|
||||
$stat->amount = $amount;
|
||||
$stat->count = $count;
|
||||
$stat->type = $type;
|
||||
$stat->save();
|
||||
|
||||
return $stat;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* PeriodStatisticRepositoryInterface.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Repositories\PeriodStatistic;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PeriodStatistic;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
interface PeriodStatisticRepositoryInterface
|
||||
{
|
||||
public function findPeriodStatistics(Model $model, Carbon $start, Carbon $end, array $types): Collection;
|
||||
|
||||
public function findPeriodStatistic(Model $model, Carbon $start, Carbon $end, string $type): Collection;
|
||||
|
||||
public function saveStatistic(Model $model, int $currencyId, Carbon $start, Carbon $end, string $type, int $count, string $amount): PeriodStatistic;
|
||||
}
|
||||
@@ -30,11 +30,13 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\PeriodStatistic;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\Support\Debug\Timer;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -67,8 +69,9 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
trait PeriodOverview
|
||||
{
|
||||
protected AccountRepositoryInterface $accountRepository;
|
||||
protected JournalRepositoryInterface $journalRepos;
|
||||
protected AccountRepositoryInterface $accountRepository;
|
||||
protected JournalRepositoryInterface $journalRepos;
|
||||
protected PeriodStatisticRepositoryInterface $periodStatisticRepo;
|
||||
|
||||
/**
|
||||
* This method returns "period entries", so nov-2015, dec-2015, etc. (this depends on the users session range)
|
||||
@@ -79,68 +82,118 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug('Now in getAccountPeriodOverview()');
|
||||
$timer = Timer::getInstance();
|
||||
$timer->start('account-period-total');
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$range = Navigation::getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('account-show-period-entries');
|
||||
$cache->addProperty($account->id);
|
||||
if ($cache->has()) {
|
||||
Log::debug('Return CACHED in getAccountPeriodOverview()');
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
Log::debug(sprintf('Now in getAccountPeriodOverview(#%d, %s %s)', $account->id, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->periodStatisticRepo = app(PeriodStatisticRepositoryInterface::class);
|
||||
$range = Navigation::getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = Navigation::blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// run a custom query because doing this with the collector is MEGA slow.
|
||||
$timer->start('account-period-collect');
|
||||
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
||||
$timer->stop('account-period-collect');
|
||||
// loop dates
|
||||
$dates = Navigation::blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
Log::debug(sprintf('Count of loops: %d', count($dates)));
|
||||
$loops = 0;
|
||||
// stop after 10 loops for memory reasons.
|
||||
$timer->start('account-period-loop');
|
||||
foreach ($dates as $currentDate) {
|
||||
$title = Navigation::periodShow($currentDate['start'], $currentDate['period']);
|
||||
[$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']);
|
||||
[$transactions, $earned] = $this->filterTransactionsByType(TransactionTypeEnum::DEPOSIT, $transactions, $currentDate['start'], $currentDate['end']);
|
||||
[$transactions, $transferredAway] = $this->filterTransfers('away', $transactions, $currentDate['start'], $currentDate['end']);
|
||||
[$transactions, $transferredIn] = $this->filterTransfers('in', $transactions, $currentDate['start'], $currentDate['end']);
|
||||
$entries[]
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('accounts.show', [$account->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferredAway) + count($transferredIn),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred_away' => $this->groupByCurrency($transferredAway),
|
||||
'transferred_in' => $this->groupByCurrency($transferredIn),
|
||||
];
|
||||
++$loops;
|
||||
$entries[] = $this->getSingleAccountPeriod($account, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
$timer->stop('account-period-loop');
|
||||
$cache->store($entries);
|
||||
$timer->stop('account-period-total');
|
||||
Log::debug('End of getAccountPeriodOverview()');
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
protected function getSingleAccountPeriod(Account $account, Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug(sprintf('Now in getSingleAccountPeriod(#%d, %s %s)', $account->id, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
$types = ['spent', 'earned', 'transferred_in', 'transferred_away'];
|
||||
$return = [
|
||||
'title' => Navigation::periodShow($start, $end),
|
||||
'route' => route('accounts.show', [$account->id, $start->format('Y-m-d'), $start->format('Y-m-d')]),
|
||||
'total_transactions' => 0,
|
||||
];
|
||||
foreach ($types as $type) {
|
||||
$set = $this->getSingleAccountPeriodByType($account, $start, $end, $type);
|
||||
$return['total_transactions'] += $set['count'];
|
||||
unset($set['count']);
|
||||
$return[$type] = $set;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
protected function getSingleAccountPeriodByType(Account $account, Carbon $start, Carbon $end, string $type): array
|
||||
{
|
||||
Log::debug(sprintf('Now in getSingleAccountPeriodByType(#%d, %s %s, %s)', $account->id, $start->format('Y-m-d'), $end->format('Y-m-d'), $type));
|
||||
$statistics = $this->periodStatisticRepo->findPeriodStatistic($account, $start, $end, $type);
|
||||
|
||||
// nothing found, regenerate them.
|
||||
if (0 === $statistics->count()) {
|
||||
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
||||
|
||||
switch ($type) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot deal with account period type %s', $type));
|
||||
|
||||
case 'spent':
|
||||
$result = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $start, $end);
|
||||
|
||||
break;
|
||||
|
||||
case 'earned':
|
||||
$result = $this->filterTransactionsByType(TransactionTypeEnum::DEPOSIT, $transactions, $start, $end);
|
||||
|
||||
break;
|
||||
|
||||
case 'transferred_in':
|
||||
$result = $this->filterTransfers('in', $transactions, $start, $end);
|
||||
|
||||
break;
|
||||
|
||||
case 'transferred_away':
|
||||
$result = $this->filterTransfers('away', $transactions, $start, $end);
|
||||
|
||||
break;
|
||||
}
|
||||
// each result must be grouped by currency, then saved as period statistic.
|
||||
$grouped = $this->groupByCurrency($result);
|
||||
|
||||
// TODO save as statistic.
|
||||
$this->saveGroupedAsStatistics($account, $start, $end, $type, $grouped);
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
$grouped = [
|
||||
'count' => 0,
|
||||
];
|
||||
|
||||
/** @var PeriodStatistic $statistic */
|
||||
foreach ($statistics as $statistic) {
|
||||
$id = (int) $statistic->transaction_currency_id;
|
||||
$currency = Amount::getTransactionCurrencyById($id);
|
||||
$grouped[$id] = [
|
||||
'amount' => (string) $statistic->amount,
|
||||
'count' => (int) $statistic->count,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
];
|
||||
$grouped['count'] += (int) $statistic->count;
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
protected function saveGroupedAsStatistics(Account $account, Carbon $start, Carbon $end, string $type, array $array): void
|
||||
{
|
||||
unset($array['count']);
|
||||
foreach ($array as $entry) {
|
||||
$this->periodStatisticRepo->saveStatistic($account, $entry['currency_id'], $start, $end, $type, $entry['count'], $entry['amount']);
|
||||
}
|
||||
}
|
||||
|
||||
private function filterTransactionsByType(TransactionTypeEnum $type, array $transactions, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$result = [];
|
||||
$filtered = [];
|
||||
$result = [];
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
@@ -153,25 +206,21 @@ trait PeriodOverview
|
||||
$result[] = $item;
|
||||
unset($transactions[$index]);
|
||||
}
|
||||
if (!$fits) {
|
||||
$filtered[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return [$filtered, $result];
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function filterTransfers(string $direction, array $transactions, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$result = [];
|
||||
$filtered = [];
|
||||
$result = [];
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var array $item
|
||||
*/
|
||||
foreach ($transactions as $index => $item) {
|
||||
$date = Carbon::parse($item['date']);
|
||||
$date = Carbon::parse($item['date']);
|
||||
if ($date >= $start && $date <= $end) {
|
||||
if ('away' === $direction && -1 === bccomp((string)$item['amount'], '0')) {
|
||||
$result[] = $item;
|
||||
@@ -184,18 +233,28 @@ trait PeriodOverview
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$filtered[] = $item;
|
||||
}
|
||||
|
||||
return [$filtered, $result];
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function groupByCurrency(array $journals): array
|
||||
{
|
||||
$return = [];
|
||||
Log::debug('groupByCurrency()');
|
||||
$return = [
|
||||
'count' => 0,
|
||||
];
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
|
||||
if (!array_key_exists('currency_id', $journal)) {
|
||||
Log::debug('very strange!');
|
||||
var_dump($journals);
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$currencyName = $journal['currency_name'];
|
||||
@@ -233,6 +292,7 @@ trait PeriodOverview
|
||||
|
||||
$return[$currencyId]['amount'] = bcadd($return[$currencyId]['amount'], $amount);
|
||||
++$return[$currencyId]['count'];
|
||||
++$return['count'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
@@ -593,13 +653,13 @@ trait PeriodOverview
|
||||
}
|
||||
$entries[]
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
'title' => $title,
|
||||
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
++$loops;
|
||||
}
|
||||
|
||||
|
||||
62
composer.lock
generated
62
composer.lock
generated
@@ -4235,16 +4235,16 @@
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/constant_time_encoding.git",
|
||||
"reference": "5e9b582660b997de205a84c02a3aac7c060900c9"
|
||||
"reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/5e9b582660b997de205a84c02a3aac7c060900c9",
|
||||
"reference": "5e9b582660b997de205a84c02a3aac7c060900c9",
|
||||
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77",
|
||||
"reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4300,7 +4300,7 @@
|
||||
"issues": "https://github.com/paragonie/constant_time_encoding/issues",
|
||||
"source": "https://github.com/paragonie/constant_time_encoding"
|
||||
},
|
||||
"time": "2025-09-22T21:00:33+00:00"
|
||||
"time": "2025-09-24T15:06:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
@@ -11406,16 +11406,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.28",
|
||||
"version": "2.1.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "578fa296a166605d97b94091f724f1257185d278"
|
||||
"url": "https://github.com/phpstan/phpstan-phar-composer-source.git",
|
||||
"reference": "git"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/578fa296a166605d97b94091f724f1257185d278",
|
||||
"reference": "578fa296a166605d97b94091f724f1257185d278",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d618573eed4a1b6b75e37b2e0b65ac65c885d88e",
|
||||
"reference": "d618573eed4a1b6b75e37b2e0b65ac65c885d88e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11460,7 +11460,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-19T08:58:49+00:00"
|
||||
"time": "2025-09-25T06:58:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
@@ -11559,16 +11559,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "12.3.8",
|
||||
"version": "12.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "99e692c6a84708211f7536ba322bbbaef57ac7fc"
|
||||
"reference": "67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/99e692c6a84708211f7536ba322bbbaef57ac7fc",
|
||||
"reference": "99e692c6a84708211f7536ba322bbbaef57ac7fc",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c",
|
||||
"reference": "67e8aed88f93d0e6e1cb7effe1a2dfc2fee6022c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11595,7 +11595,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "12.3.x-dev"
|
||||
"dev-main": "12.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -11624,7 +11624,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.8"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11644,7 +11644,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-17T11:31:43+00:00"
|
||||
"time": "2025-09-24T13:44:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@@ -11893,16 +11893,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "12.3.13",
|
||||
"version": "12.3.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "44f15312c4968fa8102e491fc6f3746410819c16"
|
||||
"reference": "13e9b2bea9327b094176147250d2c10319a10f5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/44f15312c4968fa8102e491fc6f3746410819c16",
|
||||
"reference": "44f15312c4968fa8102e491fc6f3746410819c16",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/13e9b2bea9327b094176147250d2c10319a10f5b",
|
||||
"reference": "13e9b2bea9327b094176147250d2c10319a10f5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11925,7 +11925,7 @@
|
||||
"sebastian/comparator": "^7.1.3",
|
||||
"sebastian/diff": "^7.0.0",
|
||||
"sebastian/environment": "^8.0.3",
|
||||
"sebastian/exporter": "^7.0.1",
|
||||
"sebastian/exporter": "^7.0.2",
|
||||
"sebastian/global-state": "^8.0.2",
|
||||
"sebastian/object-enumerator": "^7.0.0",
|
||||
"sebastian/type": "^6.0.3",
|
||||
@@ -11970,7 +11970,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.13"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11994,7 +11994,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-23T06:25:02+00:00"
|
||||
"time": "2025-09-24T06:34:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
@@ -12420,16 +12420,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "7.0.1",
|
||||
"version": "7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "b759164a8e02263784b662889cc6cbb686077af6"
|
||||
"reference": "016951ae10980765e4e7aee491eb288c64e505b7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/b759164a8e02263784b662889cc6cbb686077af6",
|
||||
"reference": "b759164a8e02263784b662889cc6cbb686077af6",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/016951ae10980765e4e7aee491eb288c64e505b7",
|
||||
"reference": "016951ae10980765e4e7aee491eb288c64e505b7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12486,7 +12486,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"security": "https://github.com/sebastianbergmann/exporter/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/7.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12506,7 +12506,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-22T05:39:29+00:00"
|
||||
"time": "2025-09-24T06:16:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
|
||||
@@ -78,8 +78,8 @@ return [
|
||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2025-09-23',
|
||||
'build_time' => 1758652788,
|
||||
'version' => 'develop/2025-09-25',
|
||||
'build_time' => 1758820163,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 27,
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('period_statistics', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
$table->integer('primary_statable_id', false, true)->nullable();
|
||||
$table->string('primary_statable_type', 255)->nullable();
|
||||
|
||||
$table->integer('secondary_statable_id', false, true)->nullable();
|
||||
$table->string('secondary_statable_type', 255)->nullable();
|
||||
|
||||
$table->integer('tertiary_statable_id', false, true)->nullable();
|
||||
$table->string('tertiary_statable_type', 255)->nullable();
|
||||
|
||||
$table->integer('transaction_currency_id', false, true);
|
||||
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
|
||||
|
||||
$table->dateTime('start')->nullable();
|
||||
$table->string('start_tz', 50)->nullable();
|
||||
$table->dateTime('end')->nullable();
|
||||
$table->string('end_tz', 50)->nullable();
|
||||
$table->string('type',255);
|
||||
$table->integer('count', false, true)->default(0);
|
||||
$table->decimal('amount', 32, 12);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('period_statistics');
|
||||
}
|
||||
};
|
||||
115
package-lock.json
generated
115
package-lock.json
generated
@@ -3281,57 +3281,57 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz",
|
||||
"integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==",
|
||||
"version": "3.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz",
|
||||
"integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.3",
|
||||
"@vue/shared": "3.5.21",
|
||||
"@babel/parser": "^7.28.4",
|
||||
"@vue/shared": "3.5.22",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz",
|
||||
"integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==",
|
||||
"version": "3.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz",
|
||||
"integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
"@vue/compiler-core": "3.5.22",
|
||||
"@vue/shared": "3.5.22"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz",
|
||||
"integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==",
|
||||
"version": "3.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz",
|
||||
"integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.3",
|
||||
"@vue/compiler-core": "3.5.21",
|
||||
"@vue/compiler-dom": "3.5.21",
|
||||
"@vue/compiler-ssr": "3.5.21",
|
||||
"@vue/shared": "3.5.21",
|
||||
"@babel/parser": "^7.28.4",
|
||||
"@vue/compiler-core": "3.5.22",
|
||||
"@vue/compiler-dom": "3.5.22",
|
||||
"@vue/compiler-ssr": "3.5.22",
|
||||
"@vue/shared": "3.5.22",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.18",
|
||||
"magic-string": "^0.30.19",
|
||||
"postcss": "^8.5.6",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz",
|
||||
"integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==",
|
||||
"version": "3.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz",
|
||||
"integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
"@vue/compiler-dom": "3.5.22",
|
||||
"@vue/shared": "3.5.22"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/component-compiler-utils": {
|
||||
@@ -3413,9 +3413,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz",
|
||||
"integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==",
|
||||
"version": "3.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz",
|
||||
"integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -4075,9 +4075,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.8.6",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz",
|
||||
"integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==",
|
||||
"version": "2.8.7",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.7.tgz",
|
||||
"integrity": "sha512-bxxN2M3a4d1CRoQC//IqsR5XrLh0IJ8TCv2x6Y9N0nckNz/rTjZB3//GGscZziZOxmjP55rzxg/ze7usFI9FqQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -4329,9 +4329,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserify-sign": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.4.tgz",
|
||||
"integrity": "sha512-pbZw0FHibrwXcpLQlXwHp21A5undDBo+RaGNL0K3KOm8nK8uP6PThhS301VDzoMgURZPiVRWRrVHlo6NyU57kA==",
|
||||
"version": "4.2.5",
|
||||
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz",
|
||||
"integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -4341,12 +4341,12 @@
|
||||
"create-hmac": "^1.1.7",
|
||||
"elliptic": "^6.6.1",
|
||||
"inherits": "^2.0.4",
|
||||
"parse-asn1": "^5.1.7",
|
||||
"parse-asn1": "^5.1.9",
|
||||
"readable-stream": "^2.3.8",
|
||||
"safe-buffer": "^5.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/browserify-zlib": {
|
||||
@@ -4521,9 +4521,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001743",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz",
|
||||
"integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==",
|
||||
"version": "1.0.30001745",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz",
|
||||
"integrity": "sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -4651,14 +4651,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cipher-base": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz",
|
||||
"integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz",
|
||||
"integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"safe-buffer": "^5.2.1"
|
||||
"safe-buffer": "^5.2.1",
|
||||
"to-buffer": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
@@ -8760,20 +8761,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parse-asn1": {
|
||||
"version": "5.1.8",
|
||||
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.8.tgz",
|
||||
"integrity": "sha512-e90aVPe/1q/g7BrNeYvbJy++5tln4ShE+I3qZ5LxFpUbu+uavfKMuzH2R3SH141O7Pvruwif0BZRwKoVf6vW6w==",
|
||||
"version": "5.1.9",
|
||||
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz",
|
||||
"integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"asn1.js": "^4.10.1",
|
||||
"browserify-aes": "^1.2.0",
|
||||
"evp_bytestokey": "^1.0.3",
|
||||
"pbkdf2": "^3.1.3",
|
||||
"pbkdf2": "^3.1.5",
|
||||
"safe-buffer": "^5.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-json": {
|
||||
@@ -8935,9 +8936,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.4.tgz",
|
||||
"integrity": "sha512-0yPXNT01PxSUdkIxL85Fd+yPdeCcvGwFPAAHbR3Z2ukMERcRrJFfLUKK3oglbQ9eUPeX6qDY3QiELqiDarZYUQ==",
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz",
|
||||
"integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8949,7 +8950,7 @@
|
||||
"to-buffer": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
@@ -10222,9 +10223,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.93.1",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.93.1.tgz",
|
||||
"integrity": "sha512-wLAeLB7IksO2u+cCfhHqcy7/2ZUMPp/X2oV6+LjmweTqgjhOKrkaE/Q1wljxtco5EcOcupZ4c981X0gpk5Tiag==",
|
||||
"version": "1.93.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz",
|
||||
"integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -11233,9 +11234,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/to-buffer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
|
||||
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
|
||||
"integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
Reference in New Issue
Block a user