mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-03-19 11:54:03 +00:00
Compare commits
33 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
956d4e09c3 | ||
|
|
6a7c35e7bc | ||
|
|
090aecb5f5 | ||
|
|
b653d63d3d | ||
|
|
258dbf4a98 | ||
|
|
53335077ff | ||
|
|
ecfb3e2f95 | ||
|
|
f512e6724e | ||
|
|
de9efb0727 | ||
|
|
9075fa8ac8 | ||
|
|
768bd892c8 | ||
|
|
9d9483e20f | ||
|
|
935453796e | ||
|
|
c2d3f5da16 | ||
|
|
9e6f9d16e4 | ||
|
|
fad016f92f | ||
|
|
30df6684cb | ||
|
|
4aa911420a | ||
|
|
19555a7046 | ||
|
|
e5c409a8fc | ||
|
|
3adf3d2fdb | ||
|
|
0923d5a23e | ||
|
|
76b8cdc385 | ||
|
|
0a27da83eb | ||
|
|
17d6e2be85 | ||
|
|
7381f3eba9 | ||
|
|
7f2ef1b8e1 | ||
|
|
9dccae2402 | ||
|
|
073afd5b6e | ||
|
|
4167d85be2 | ||
|
|
ee28d1307d | ||
|
|
7562215666 | ||
|
|
adf34805a8 |
@@ -314,8 +314,9 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
|
||||
#
|
||||
# Disable or enable the running balance column data
|
||||
# Please disable this. It's a very experimental feature.
|
||||
# Disable or enable the running balance column data.
|
||||
# If you enable this, please also run "php artisan firefly-iii:correct-database"
|
||||
# This will take some time the first run.
|
||||
#
|
||||
USE_RUNNING_BALANCE=false
|
||||
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -272,7 +272,7 @@ jobs:
|
||||
|
||||
echo "Also merge everything into main since this is a release."
|
||||
echo 'create PR'
|
||||
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body "🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`")
|
||||
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`')
|
||||
echo "PR URL is '$PR_URL'"
|
||||
|
||||
IFS='/' read -ra parts <<< "$PR_URL"
|
||||
|
||||
@@ -67,7 +67,9 @@ class StoreController extends Controller
|
||||
*/
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
$budget = $this->repository->store($request->getAll());
|
||||
$data = $request->getAll();
|
||||
$data['fire_webhooks'] ??= true;
|
||||
$budget = $this->repository->store($data);
|
||||
$budget->refresh();
|
||||
$manager = $this->getManager();
|
||||
|
||||
|
||||
@@ -57,15 +57,10 @@ class UpdateController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/budgets/updateBudget
|
||||
*
|
||||
* Update a budget.
|
||||
*/
|
||||
public function update(UpdateRequest $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['fire_webhooks'] ??= true;
|
||||
$budget = $this->repository->update($budget, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ class StoreController extends Controller
|
||||
$data = $request->getAll();
|
||||
$data['start_date'] = $data['start'];
|
||||
$data['end_date'] = $data['end'];
|
||||
$data['fire_webhooks'] ??= true;
|
||||
$data['budget_id'] = $budget->id;
|
||||
|
||||
$budgetLimit = $this->blRepository->store($data);
|
||||
|
||||
@@ -77,6 +77,7 @@ class UpdateController extends Controller
|
||||
throw new FireflyException('20028: The budget limit does not belong to the budget.');
|
||||
}
|
||||
$data = $request->getAll();
|
||||
$data['fire_webhooks'] ??= true;
|
||||
$data['budget_id'] = $budget->id;
|
||||
$budgetLimit = $this->blRepository->update($budgetLimit, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
@@ -48,17 +48,20 @@ class StoreRequest extends FormRequest
|
||||
public function getAll(): array
|
||||
{
|
||||
$fields = [
|
||||
'name' => ['name', 'convertString'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['active', 'convertInteger'],
|
||||
'notes' => ['notes', 'convertString'],
|
||||
'name' => ['name', 'convertString'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['active', 'convertInteger'],
|
||||
'notes' => ['notes', 'convertString'],
|
||||
|
||||
// auto budget currency:
|
||||
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
|
||||
'currency_code' => ['auto_budget_currency_code', 'convertString'],
|
||||
'auto_budget_type' => ['auto_budget_type', 'convertString'],
|
||||
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
|
||||
'auto_budget_period' => ['auto_budget_period', 'convertString'],
|
||||
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
|
||||
'currency_code' => ['auto_budget_currency_code', 'convertString'],
|
||||
'auto_budget_type' => ['auto_budget_type', 'convertString'],
|
||||
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
|
||||
'auto_budget_period' => ['auto_budget_period', 'convertString'],
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => ['fire_webhooks', 'boolean'],
|
||||
];
|
||||
|
||||
return $this->getAllData($fields);
|
||||
@@ -70,15 +73,18 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|min:1|max:255|uniqueObjectForUser:budgets,name',
|
||||
'active' => [new IsBoolean()],
|
||||
'currency_id' => 'exists:transaction_currencies,id',
|
||||
'currency_code' => 'exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
'name' => 'required|min:1|max:255|uniqueObjectForUser:budgets,name',
|
||||
'active' => [new IsBoolean()],
|
||||
'currency_id' => 'exists:transaction_currencies,id',
|
||||
'currency_code' => 'exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
// auto budget info
|
||||
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
|
||||
'auto_budget_amount' => ['required_if:auto_budget_type,reset', 'required_if:auto_budget_type,rollover', 'required_if:auto_budget_type,adjusted', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly|required_if:auto_budget_type,reset|required_if:auto_budget_type,rollover|required_if:auto_budget_type,adjusted',
|
||||
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
|
||||
'auto_budget_amount' => ['required_if:auto_budget_type,reset', 'required_if:auto_budget_type,rollover', 'required_if:auto_budget_type,adjusted', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly|required_if:auto_budget_type,reset|required_if:auto_budget_type,rollover|required_if:auto_budget_type,adjusted',
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => [new IsBoolean()],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -50,15 +50,18 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
// this is the way:
|
||||
$fields = [
|
||||
'name' => ['name', 'convertString'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['order', 'convertInteger'],
|
||||
'notes' => ['notes', 'convertString'],
|
||||
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
|
||||
'currency_code' => ['auto_budget_currency_code', 'convertString'],
|
||||
'auto_budget_type' => ['auto_budget_type', 'convertString'],
|
||||
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
|
||||
'auto_budget_period' => ['auto_budget_period', 'convertString'],
|
||||
'name' => ['name', 'convertString'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['order', 'convertInteger'],
|
||||
'notes' => ['notes', 'convertString'],
|
||||
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
|
||||
'currency_code' => ['auto_budget_currency_code', 'convertString'],
|
||||
'auto_budget_type' => ['auto_budget_type', 'convertString'],
|
||||
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
|
||||
'auto_budget_period' => ['auto_budget_period', 'convertString'],
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => ['fire_webhooks', 'boolean'],
|
||||
];
|
||||
$allData = $this->getAllData($fields);
|
||||
if (array_key_exists('auto_budget_type', $allData)) {
|
||||
@@ -83,14 +86,17 @@ class UpdateRequest extends FormRequest
|
||||
$budget = $this->route()->parameter('budget');
|
||||
|
||||
return [
|
||||
'name' => sprintf('min:1|max:100|uniqueObjectForUser:budgets,name,%d', $budget->id),
|
||||
'active' => [new IsBoolean()],
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
|
||||
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
|
||||
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
|
||||
'auto_budget_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
|
||||
'name' => sprintf('min:1|max:100|uniqueObjectForUser:budgets,name,%d', $budget->id),
|
||||
'active' => [new IsBoolean()],
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
|
||||
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
|
||||
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
|
||||
'auto_budget_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => [new IsBoolean()],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class StoreRequest
|
||||
@@ -49,6 +55,9 @@ class StoreRequest extends FormRequest
|
||||
'currency_id' => $this->convertInteger('currency_id'),
|
||||
'currency_code' => $this->convertString('currency_code'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
|
||||
// for webhooks:
|
||||
'fire_webhooks' => $this->boolean('fire_webhooks', true),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -58,12 +67,59 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'required|before:end|date',
|
||||
'end' => 'required|after:start|date',
|
||||
'amount' => ['required', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:0|max:32768',
|
||||
'start' => 'required|before:end|date',
|
||||
'end' => 'required|after:start|date',
|
||||
'amount' => ['required', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:0|max:32768',
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => [new IsBoolean()],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$budget = $this->route()->parameter('budget');
|
||||
$validator->after(
|
||||
static function (Validator $validator) use ($budget): void {
|
||||
if (0 !== count($validator->failed())) {
|
||||
return;
|
||||
}
|
||||
$data = $validator->getData();
|
||||
|
||||
// if no currency has been provided, use the user's default currency:
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
|
||||
if (null === $currency) {
|
||||
$currency = Amount::getPrimaryCurrency();
|
||||
}
|
||||
$currency->enabled = true;
|
||||
$currency->save();
|
||||
|
||||
// validator already concluded start and end are valid dates:
|
||||
$start = Carbon::parse($data['start'], config('app.timezone'));
|
||||
$end = Carbon::parse($data['end'], config('app.timezone'));
|
||||
|
||||
// find limit with same date range and currency.
|
||||
$limit = $budget->budgetlimits()
|
||||
->where('budget_limits.start_date', $start->format('Y-m-d'))
|
||||
->where('budget_limits.end_date', $end->format('Y-m-d'))
|
||||
->where('budget_limits.transaction_currency_id', $currency->id)
|
||||
->first(['budget_limits.*'])
|
||||
;
|
||||
if (null !== $limit) {
|
||||
$validator->errors()->add('start', trans('validation.limit_exists'));
|
||||
}
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
@@ -46,12 +47,15 @@ class UpdateRequest extends FormRequest
|
||||
public function getAll(): array
|
||||
{
|
||||
$fields = [
|
||||
'start' => ['start', 'date'],
|
||||
'end' => ['end', 'date'],
|
||||
'amount' => ['amount', 'convertString'],
|
||||
'currency_id' => ['currency_id', 'convertInteger'],
|
||||
'currency_code' => ['currency_code', 'convertString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'start' => ['start', 'date'],
|
||||
'end' => ['end', 'date'],
|
||||
'amount' => ['amount', 'convertString'],
|
||||
'currency_id' => ['currency_id', 'convertInteger'],
|
||||
'currency_code' => ['currency_code', 'convertString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => ['fire_webhooks', 'boolean'],
|
||||
];
|
||||
if (false === $this->has('notes')) {
|
||||
// ignore notes, not submitted.
|
||||
@@ -67,12 +71,15 @@ class UpdateRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date|after:1970-01-02|before:2038-01-17',
|
||||
'end' => 'date|after:1970-01-02|before:2038-01-17',
|
||||
'amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:0|max:32768',
|
||||
'start' => 'date|after:1970-01-02|before:2038-01-17',
|
||||
'end' => 'date|after:1970-01-02|before:2038-01-17',
|
||||
'amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:0|max:32768',
|
||||
|
||||
// webhooks
|
||||
'fire_webhooks' => [new IsBoolean()],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ class StoreRequest extends FormRequest
|
||||
// basic fields for group:
|
||||
'group_title' => 'min:1|max:1000|nullable',
|
||||
'error_if_duplicate_hash' => [new IsBoolean()],
|
||||
'fire_webhooks' => [new IsBoolean()],
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
// location rules
|
||||
|
||||
@@ -75,7 +75,8 @@ class CorrectsDatabase extends Command
|
||||
'correction:recalculates-liabilities',
|
||||
'correction:preferences',
|
||||
// 'correction:transaction-types', // resource heavy, disabled.
|
||||
'correction:recalculate-pc-amounts', // not necessary, disabled.
|
||||
'correction:recalculate-pc-amounts',
|
||||
'correction:remove-links-to-deleted-objects',
|
||||
'firefly-iii:report-integrity',
|
||||
];
|
||||
foreach ($commands as $command) {
|
||||
|
||||
118
app/Console/Commands/Correction/RemovesLinksToDeletedObjects.php
Normal file
118
app/Console/Commands/Correction/RemovesLinksToDeletedObjects.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* RemovesLinksToDeletedObjects.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\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RemovesLinksToDeletedObjects extends Command
|
||||
{
|
||||
use ShowsFriendlyMessages;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'correction:remove-links-to-deleted-objects';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Removes deleted entries from intermediate tables.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$deletedTags = Tag::withTrashed()->whereNotNull('deleted_at')->get('tags.id')->pluck('id')->toArray();
|
||||
$deletedJournals = TransactionJournal::withTrashed()->whereNotNull('deleted_at')->get('transaction_journals.id')->pluck('id')->toArray();
|
||||
$deletedBudgets = Budget::withTrashed()->whereNotNull('deleted_at')->get('budgets.id')->pluck('id')->toArray();
|
||||
$deletedCategories = Category::withTrashed()->whereNotNull('deleted_at')->get('categories.id')->pluck('id')->toArray();
|
||||
|
||||
if (count($deletedTags) > 0) {
|
||||
$this->cleanupTags($deletedTags);
|
||||
}
|
||||
if (count($deletedJournals) > 0) {
|
||||
$this->cleanupJournals($deletedJournals);
|
||||
}
|
||||
if (count($deletedBudgets) > 0) {
|
||||
$this->cleanupBudgets($deletedBudgets);
|
||||
}
|
||||
if (count($deletedCategories) > 0) {
|
||||
$this->cleanupCategories($deletedCategories);
|
||||
}
|
||||
$this->friendlyNeutral('Validated links to deleted objects.');
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function cleanupTags(array $tags): void
|
||||
{
|
||||
$count = DB::table('tag_transaction_journal')->whereIn('tag_id', $tags)->delete();
|
||||
if ($count > 0) {
|
||||
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories transactions and tags.', $count));
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupJournals(array $journals): void
|
||||
{
|
||||
$count = DB::table('tag_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
|
||||
if ($count > 0) {
|
||||
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between tags and transactions.', $count));
|
||||
}
|
||||
$count = DB::table('budget_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
|
||||
if ($count > 0) {
|
||||
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between budgets and transactions.', $count));
|
||||
}
|
||||
$count = DB::table('category_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
|
||||
if ($count > 0) {
|
||||
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories and transactions.', $count));
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupBudgets(array $budgets): void
|
||||
{
|
||||
$count = DB::table('budget_transaction_journal')->whereIn('budget_id', $budgets)->delete();
|
||||
if ($count > 0) {
|
||||
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between budgets and transactions.', $count));
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupCategories(array $categories): void
|
||||
{
|
||||
$count = DB::table('category_transaction_journal')->whereIn('category_id', $categories)->delete();
|
||||
if ($count > 0) {
|
||||
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories categories and transactions.', $count));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\Support\Observers\RecalculatesAvailableBudgetsTrait;
|
||||
use FireflyIII\Support\Singleton\PreferencesSingleton;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -44,17 +45,24 @@ class BudgetLimitObserver
|
||||
$this->updatePrimaryCurrencyAmount($budgetLimit);
|
||||
$this->updateAvailableBudget($budgetLimit);
|
||||
|
||||
$user = $budgetLimit->budget->user;
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budgetLimit));
|
||||
$engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
|
||||
$engine->generateMessages();
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
if (true === $singleton->getPreference('fire_webhooks_bl_store')) {
|
||||
|
||||
$user = $budgetLimit->budget->user;
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budgetLimit));
|
||||
$engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
|
||||
$engine->generateMessages();
|
||||
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
}
|
||||
}
|
||||
|
||||
private function updatePrimaryCurrencyAmount(BudgetLimit $budgetLimit): void
|
||||
@@ -82,16 +90,21 @@ class BudgetLimitObserver
|
||||
$this->updatePrimaryCurrencyAmount($budgetLimit);
|
||||
$this->updateAvailableBudget($budgetLimit);
|
||||
|
||||
$user = $budgetLimit->budget->user;
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budgetLimit));
|
||||
$engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
|
||||
$engine->generateMessages();
|
||||
if (true === $singleton->getPreference('fire_webhooks_bl_update')) {
|
||||
$user = $budgetLimit->budget->user;
|
||||
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budgetLimit));
|
||||
$engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
|
||||
$engine->generateMessages();
|
||||
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Support\Observers\RecalculatesAvailableBudgetsTrait;
|
||||
use FireflyIII\Support\Singleton\PreferencesSingleton;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -45,32 +46,43 @@ class BudgetObserver
|
||||
{
|
||||
Log::debug(sprintf('Observe "created" of budget #%d ("%s").', $budget->id, $budget->name));
|
||||
|
||||
// fire event.
|
||||
$user = $budget->user;
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budget));
|
||||
$engine->setTrigger(WebhookTrigger::STORE_BUDGET);
|
||||
$engine->generateMessages();
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
if (true === $singleton->getPreference('fire_webhooks_budget_create')) {
|
||||
// fire event.
|
||||
$user = $budget->user;
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budget));
|
||||
$engine->setTrigger(WebhookTrigger::STORE_BUDGET);
|
||||
$engine->generateMessages();
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
}
|
||||
}
|
||||
|
||||
public function updated(Budget $budget): void
|
||||
{
|
||||
Log::debug(sprintf('Observe "updated" of budget #%d ("%s").', $budget->id, $budget->name));
|
||||
$user = $budget->user;
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budget));
|
||||
$engine->setTrigger(WebhookTrigger::UPDATE_BUDGET);
|
||||
$engine->generateMessages();
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
|
||||
if (true === $singleton->getPreference('fire_webhooks_budget_update')) {
|
||||
$user = $budget->user;
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($budget));
|
||||
$engine->setTrigger(WebhookTrigger::UPDATE_BUDGET);
|
||||
$engine->generateMessages();
|
||||
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));
|
||||
event(new RequestedSendWebhookMessages());
|
||||
}
|
||||
}
|
||||
|
||||
public function deleting(Budget $budget): void
|
||||
|
||||
@@ -94,7 +94,7 @@ trait AttachmentCollection
|
||||
static function (EloquentBuilder $q1): void { // @phpstan-ignore-line
|
||||
$q1->where('attachments.attachable_type', TransactionJournal::class);
|
||||
// $q1->where('attachments.uploaded', true);
|
||||
$q1->whereNull('attachments.deleted_at');
|
||||
// $q1->whereNull('attachments.deleted_at');
|
||||
$q1->orWhereNull('attachments.attachable_type');
|
||||
}
|
||||
)
|
||||
@@ -107,6 +107,7 @@ trait AttachmentCollection
|
||||
$this->fields[] = 'attachments.id as attachment_id';
|
||||
$this->fields[] = 'attachments.filename as attachment_filename';
|
||||
$this->fields[] = 'attachments.title as attachment_title';
|
||||
$this->fields[] = 'attachments.deleted_at as attachment_deleted_at';
|
||||
$this->fields[] = 'attachments.uploaded as attachment_uploaded';
|
||||
$this->joinAttachmentTables();
|
||||
|
||||
|
||||
@@ -634,7 +634,8 @@ class GroupCollector implements GroupCollectorInterface
|
||||
if (array_key_exists('attachment_id', $result) && null !== $result['attachment_id']) {
|
||||
$uploaded = 1 === (int)$result['attachment_uploaded'];
|
||||
$attachmentId = (int)$augumentedJournal['attachment_id'];
|
||||
if (0 !== $attachmentId && $uploaded) {
|
||||
$deleted = null !== $result['attachment_deleted_at'];
|
||||
if (0 !== $attachmentId && $uploaded && !$deleted) {
|
||||
$result['attachments'][$attachmentId] = [
|
||||
'id' => $attachmentId,
|
||||
'filename' => $augumentedJournal['attachment_filename'],
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Http\Controllers;
|
||||
use FireflyIII\Events\RequestedSendWebhookMessages;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Controllers\RequestInformation;
|
||||
use FireflyIII\Support\Http\Controllers\UserNavigation;
|
||||
@@ -133,7 +134,7 @@ abstract class Controller extends BaseController
|
||||
$this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||
$language = Steam::getLanguage();
|
||||
$locale = Steam::getLocale();
|
||||
$darkMode = app('preferences')->get('darkMode', 'browser')->data;
|
||||
$darkMode = Preferences::get('darkMode', 'browser')->data;
|
||||
$this->convertToPrimary = Amount::convertToPrimary();
|
||||
$page = $this->getPageName();
|
||||
$shownDemo = $this->hasSeenDemo();
|
||||
|
||||
@@ -146,25 +146,7 @@ class ShowController extends Controller
|
||||
$attachments = $this->repository->getAttachments($transactionGroup);
|
||||
$links = $this->repository->getLinks($transactionGroup);
|
||||
|
||||
return view(
|
||||
'transactions.show',
|
||||
compact(
|
||||
'transactionGroup',
|
||||
'amounts',
|
||||
'first',
|
||||
'type',
|
||||
'logEntries',
|
||||
'groupLogEntries',
|
||||
'subTitle',
|
||||
'splits',
|
||||
'selectedGroup',
|
||||
'groupArray',
|
||||
'events',
|
||||
'attachments',
|
||||
'links',
|
||||
'accounts',
|
||||
)
|
||||
);
|
||||
return view('transactions.show', compact('transactionGroup', 'amounts', 'first', 'type', 'logEntries', 'groupLogEntries', 'subTitle', 'splits', 'selectedGroup', 'groupArray', 'events', 'attachments', 'links', 'accounts'));
|
||||
}
|
||||
|
||||
private function getAmounts(array $group): array
|
||||
|
||||
@@ -23,11 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Handlers\Observer\AccountObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@@ -40,6 +42,7 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([AccountObserver::class])]
|
||||
class Account extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
@@ -60,7 +63,7 @@ class Account extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$accountId = (int) $value;
|
||||
$accountId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -95,39 +98,6 @@ class Account extends Model
|
||||
return $this->morphMany(Attachment::class, 'attachable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account number.
|
||||
*/
|
||||
protected function accountNumber(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
/** @var null|AccountMeta $metaValue */
|
||||
$metaValue = $this->accountMeta()
|
||||
->where('name', 'account_number')
|
||||
->first()
|
||||
;
|
||||
|
||||
return null !== $metaValue ? $metaValue->data : '';
|
||||
});
|
||||
}
|
||||
|
||||
public function accountMeta(): HasMany
|
||||
{
|
||||
return $this->hasMany(AccountMeta::class);
|
||||
}
|
||||
|
||||
protected function editName(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
$name = $this->name;
|
||||
if (AccountTypeEnum::CASH->value === $this->accountType->type) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $name;
|
||||
});
|
||||
}
|
||||
|
||||
public function locations(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Location::class, 'locatable');
|
||||
@@ -154,19 +124,9 @@ class Account extends Model
|
||||
return $this->belongsToMany(PiggyBank::class);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function accountTypeIn(EloquentBuilder $query, array $types): void
|
||||
{
|
||||
if (false === $this->joinedAccountTypes) {
|
||||
$query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id');
|
||||
$this->joinedAccountTypes = true;
|
||||
}
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
public function setVirtualBalanceAttribute(mixed $value): void
|
||||
{
|
||||
$value = (string) $value;
|
||||
$value = (string)$value;
|
||||
if ('' === $value) {
|
||||
$value = null;
|
||||
}
|
||||
@@ -186,42 +146,49 @@ class Account extends Model
|
||||
protected function accountId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account number.
|
||||
*/
|
||||
protected function accountNumber(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
/** @var null|AccountMeta $metaValue */
|
||||
$metaValue = $this->accountMeta()
|
||||
->where('name', 'account_number')
|
||||
->first()
|
||||
;
|
||||
|
||||
return null !== $metaValue ? $metaValue->data : '';
|
||||
});
|
||||
}
|
||||
|
||||
public function accountMeta(): HasMany
|
||||
{
|
||||
return $this->hasMany(AccountMeta::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user ID
|
||||
*/
|
||||
protected function accountTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function iban(): Attribute
|
||||
#[Scope]
|
||||
protected function accountTypeIn(EloquentBuilder $query, array $types): void
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => null === $value ? null : trim(str_replace(' ', '', (string) $value)),
|
||||
);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the virtual balance
|
||||
*/
|
||||
protected function virtualBalance(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
if (false === $this->joinedAccountTypes) {
|
||||
$query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id');
|
||||
$this->joinedAccountTypes = true;
|
||||
}
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
@@ -238,4 +205,40 @@ class Account extends Model
|
||||
'native_virtual_balance' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function editName(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
$name = $this->name;
|
||||
if (AccountTypeEnum::CASH->value === $this->accountType->type) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $name;
|
||||
});
|
||||
}
|
||||
|
||||
protected function iban(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => null === $value ? null : trim(str_replace(' ', '', (string)$value)),
|
||||
);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the virtual balance
|
||||
*/
|
||||
protected function virtualBalance(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
@@ -43,11 +43,6 @@ class AccountMeta extends Model
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
protected function data(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn (mixed $value) => (string) json_decode((string) $value, true), set: fn (mixed $value) => ['data' => json_encode($value)]);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -55,4 +50,9 @@ class AccountMeta extends Model
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
protected function data(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn (mixed $value) => (string)json_decode((string)$value, true), set: fn (mixed $value) => ['data' => json_encode($value)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,46 +32,60 @@ class AccountType extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string ASSET = 'Asset account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string BENEFICIARY = 'Beneficiary account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string CASH = 'Cash account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string CREDITCARD = 'Credit card';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string DEBT = 'Debt';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string DEFAULT = 'Default account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string EXPENSE = 'Expense account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string IMPORT = 'Import account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string INITIAL_BALANCE = 'Initial balance account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string LIABILITY_CREDIT = 'Liability credit account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string LOAN = 'Loan';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string MORTGAGE = 'Mortgage';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string RECONCILIATION = 'Reconciliation account';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string REVENUE = 'Revenue account';
|
||||
|
||||
protected $casts
|
||||
|
||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\AttachmentObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -34,6 +36,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([AttachmentObserver::class])]
|
||||
class Attachment extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -50,7 +53,7 @@ class Attachment extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$attachmentId = (int) $value;
|
||||
$attachmentId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -83,7 +86,7 @@ class Attachment extends Model
|
||||
*/
|
||||
public function fileName(): string
|
||||
{
|
||||
return sprintf('at-%s.data', (string) $this->id);
|
||||
return sprintf('at-%s.data', (string)$this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +100,7 @@ class Attachment extends Model
|
||||
protected function attachableId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,14 +48,7 @@ class AuditLogEntry extends Model
|
||||
protected function auditableId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function changerId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,4 +62,11 @@ class AuditLogEntry extends Model
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
protected function changerId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,24 +25,30 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Deprecated;
|
||||
use FireflyIII\Handlers\Observer\AutoBudgetObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
#[ObservedBy([AutoBudgetObserver::class])]
|
||||
class AutoBudget extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int AUTO_BUDGET_ADJUSTED = 3;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int AUTO_BUDGET_RESET = 1;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int AUTO_BUDGET_ROLLOVER = 2;
|
||||
protected $casts
|
||||
= [
|
||||
@@ -64,14 +70,14 @@ class AutoBudget extends Model
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function budgetId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -85,7 +91,7 @@ class AutoBudget extends Model
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,15 +24,18 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Handlers\Observer\AvailableBudgetObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([AvailableBudgetObserver::class])]
|
||||
class AvailableBudget extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -49,7 +52,7 @@ class AvailableBudget extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$availableBudgetId = (int) $value;
|
||||
$availableBudgetId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -77,10 +80,26 @@ class AvailableBudget extends Model
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'transaction_currency_id' => 'int',
|
||||
'amount' => 'string',
|
||||
'native_amount' => 'string',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function endDate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
@@ -100,23 +119,7 @@ class AvailableBudget extends Model
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'transaction_currency_id' => 'int',
|
||||
'amount' => 'string',
|
||||
'native_amount' => 'string',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,11 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\BillObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -36,6 +38,7 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([BillObserver::class])]
|
||||
class Bill extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -75,7 +78,7 @@ class Bill extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$billId = (int) $value;
|
||||
$billId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -121,7 +124,7 @@ class Bill extends Model
|
||||
*/
|
||||
public function setAmountMaxAttribute($value): void
|
||||
{
|
||||
$this->attributes['amount_max'] = (string) $value;
|
||||
$this->attributes['amount_max'] = (string)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,7 +132,7 @@ class Bill extends Model
|
||||
*/
|
||||
public function setAmountMinAttribute($value): void
|
||||
{
|
||||
$this->attributes['amount_min'] = (string) $value;
|
||||
$this->attributes['amount_min'] = (string)$value;
|
||||
}
|
||||
|
||||
public function transactionCurrency(): BelongsTo
|
||||
@@ -148,7 +151,7 @@ class Bill extends Model
|
||||
protected function amountMax(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -158,31 +161,7 @@ class Bill extends Model
|
||||
protected function amountMin(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the skip
|
||||
*/
|
||||
protected function skip(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -206,4 +185,28 @@ class Bill extends Model
|
||||
'native_amount_max' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the skip
|
||||
*/
|
||||
protected function skip(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\BudgetObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -35,6 +37,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([BudgetObserver::class])]
|
||||
class Budget extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -53,7 +56,7 @@ class Budget extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$budgetId = (int) $value;
|
||||
$budgetId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -106,13 +109,6 @@ class Budget extends Model
|
||||
return $this->belongsToMany(Transaction::class, 'budget_transaction', 'budget_id');
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -125,4 +121,11 @@ class Budget extends Model
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,16 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\BudgetLimitObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([BudgetLimitObserver::class])]
|
||||
class BudgetLimit extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -45,7 +48,7 @@ class BudgetLimit extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$budgetLimitId = (int) $value;
|
||||
$budgetLimitId = (int)$value;
|
||||
$budgetLimit = self::where('budget_limits.id', $budgetLimitId)
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('budgets.user_id', auth()->user()->id)
|
||||
@@ -83,21 +86,14 @@ class BudgetLimit extends Model
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function budgetId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,4 +109,11 @@ class BudgetLimit extends Model
|
||||
'native_amount' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\CategoryObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@@ -34,6 +36,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([CategoryObserver::class])]
|
||||
class Category extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -52,7 +55,7 @@ class Category extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$categoryId = (int) $value;
|
||||
$categoryId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
@@ -23,8 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
@@ -38,14 +38,6 @@ class Configuration extends Model
|
||||
|
||||
protected $table = 'configuration';
|
||||
|
||||
/**
|
||||
* TODO can be replaced with native laravel code.
|
||||
*/
|
||||
protected function data(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn ($value) => json_decode((string) $value), set: fn ($value) => ['data' => json_encode($value)]);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -54,4 +46,12 @@ class Configuration extends Model
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO can be replaced with native laravel code.
|
||||
*/
|
||||
protected function data(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn ($value) => json_decode((string)$value), set: fn ($value) => ['data' => json_encode($value)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class CurrencyExchangeRate extends Model
|
||||
use ReturnsIntegerIdTrait;
|
||||
use ReturnsIntegerUserIdTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['user_id', 'from_currency_id', 'to_currency_id', 'date', 'date_tz', 'rate'];
|
||||
|
||||
public function fromCurrency(): BelongsTo
|
||||
@@ -54,34 +55,6 @@ class CurrencyExchangeRate extends Model
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
protected function fromCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function rate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function toCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function userRate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -96,4 +69,32 @@ class CurrencyExchangeRate extends Model
|
||||
'user_rate' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function fromCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function rate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function toCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function userRate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,6 @@ class GroupMembership extends Model
|
||||
return $this->belongsTo(UserRole::class);
|
||||
}
|
||||
|
||||
protected function userRoleId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -69,4 +62,11 @@ class GroupMembership extends Model
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function userRoleId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class InvitedUser extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
use ReturnsIntegerUserIdTrait;
|
||||
|
||||
protected $fillable = ['user_group_id', 'user_id', 'email', 'invite_code', 'expires', 'expires_tz', 'redeemed'];
|
||||
|
||||
/**
|
||||
@@ -44,7 +45,7 @@ class InvitedUser extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$attemptId = (int) $value;
|
||||
$attemptId = (int)$value;
|
||||
|
||||
/** @var null|InvitedUser $attempt */
|
||||
$attempt = self::find($attemptId);
|
||||
|
||||
@@ -44,7 +44,7 @@ class LinkType extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$linkTypeId = (int) $value;
|
||||
$linkTypeId = (int)$value;
|
||||
$linkType = self::find($linkTypeId);
|
||||
if (null !== $linkType) {
|
||||
return $linkType;
|
||||
|
||||
@@ -66,13 +66,6 @@ class Location extends Model
|
||||
return $this->morphMany(TransactionJournal::class, 'locatable');
|
||||
}
|
||||
|
||||
protected function locatableId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -84,4 +77,11 @@ class Location extends Model
|
||||
'longitude' => 'float',
|
||||
];
|
||||
}
|
||||
|
||||
protected function locatableId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,6 @@ class Note extends Model
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
protected function noteableId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -59,4 +52,11 @@ class Note extends Model
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
protected function noteableId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class ObjectGroup extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
use ReturnsIntegerUserIdTrait;
|
||||
|
||||
protected $fillable = ['title', 'order', 'user_id', 'user_group_id'];
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,7 @@ class ObjectGroup extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$objectGroupId = (int) $value;
|
||||
$objectGroupId = (int)$value;
|
||||
|
||||
/** @var null|ObjectGroup $objectGroup */
|
||||
$objectGroup = self::where('object_groups.id', $objectGroupId)
|
||||
@@ -90,13 +91,6 @@ class ObjectGroup extends Model
|
||||
return $this->morphedByMany(PiggyBank::class, 'object_groupable');
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -107,4 +101,11 @@ class ObjectGroup extends Model
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\PiggyBankObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -34,6 +36,7 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([PiggyBankObserver::class])]
|
||||
class PiggyBank extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -49,7 +52,7 @@ class PiggyBank extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$piggyBankId = (int) $value;
|
||||
$piggyBankId = (int)$value;
|
||||
$piggyBank = self::where('piggy_banks.id', $piggyBankId)
|
||||
->leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
|
||||
@@ -109,7 +112,7 @@ class PiggyBank extends Model
|
||||
*/
|
||||
public function setTargetAmountAttribute($value): void
|
||||
{
|
||||
$this->attributes['target_amount'] = (string) $value;
|
||||
$this->attributes['target_amount'] = (string)$value;
|
||||
}
|
||||
|
||||
public function transactionCurrency(): BelongsTo
|
||||
@@ -120,24 +123,7 @@ class PiggyBank extends Model
|
||||
protected function accountId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max amount
|
||||
*/
|
||||
protected function targetAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -156,4 +142,21 @@ class PiggyBank extends Model
|
||||
'native_target_amount' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max amount
|
||||
*/
|
||||
protected function targetAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\PiggyBankEventObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
#[ObservedBy([PiggyBankEventObserver::class])]
|
||||
class PiggyBankEvent extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -47,7 +50,7 @@ class PiggyBankEvent extends Model
|
||||
*/
|
||||
public function setAmountAttribute($value): void
|
||||
{
|
||||
$this->attributes['amount'] = (string) $value;
|
||||
$this->attributes['amount'] = (string)$value;
|
||||
}
|
||||
|
||||
public function transactionJournal(): BelongsTo
|
||||
@@ -61,14 +64,7 @@ class PiggyBankEvent extends Model
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function piggyBankId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,4 +78,11 @@ class PiggyBankEvent extends Model
|
||||
'native_amount' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function piggyBankId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -43,12 +43,48 @@ class PiggyBankRepetition extends Model
|
||||
return $this->belongsTo(PiggyBank::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setCurrentAmountAttribute($value): void
|
||||
{
|
||||
$this->attributes['current_amount'] = (string)$value;
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'start_date' => SeparateTimezoneCaster::class,
|
||||
'target_date' => SeparateTimezoneCaster::class,
|
||||
'virtual_balance' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount
|
||||
*/
|
||||
protected function currentAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function onDates(EloquentBuilder $query, Carbon $start, Carbon $target): EloquentBuilder
|
||||
{
|
||||
return $query->where('start_date', $start->format('Y-m-d'))->where('target_date', $target->format('Y-m-d'));
|
||||
}
|
||||
|
||||
protected function piggyBankId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EloquentBuilder
|
||||
*/
|
||||
@@ -69,40 +105,4 @@ class PiggyBankRepetition extends Model
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setCurrentAmountAttribute($value): void
|
||||
{
|
||||
$this->attributes['current_amount'] = (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount
|
||||
*/
|
||||
protected function currentAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function piggyBankId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'start_date' => SeparateTimezoneCaster::class,
|
||||
'target_date' => SeparateTimezoneCaster::class,
|
||||
'virtual_balance' => 'string',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class Preference extends Model
|
||||
|
||||
// some preferences do not have an administration ID.
|
||||
// some need it, to make sure the correct one is selected.
|
||||
$userGroupId = (int) $user->user_group_id;
|
||||
$userGroupId = (int)$user->user_group_id;
|
||||
$userGroupId = 0 === $userGroupId ? null : $userGroupId;
|
||||
|
||||
/** @var null|Preference $preference */
|
||||
@@ -67,7 +67,7 @@ class Preference extends Model
|
||||
|
||||
// try again with ID, but this time don't care about the preferred user_group_id
|
||||
if (null === $preference) {
|
||||
$preference = $user->preferences()->where('id', (int) $value)->first();
|
||||
$preference = $user->preferences()->where('id', (int)$value)->first();
|
||||
}
|
||||
if (null !== $preference) {
|
||||
/** @var Preference $preference */
|
||||
@@ -78,7 +78,7 @@ class Preference extends Model
|
||||
$preference = new self();
|
||||
$preference->name = $value;
|
||||
$preference->data = $default[$value];
|
||||
$preference->user_id = (int) $user->id;
|
||||
$preference->user_id = (int)$user->id;
|
||||
$preference->user_group_id = in_array($value, $items, true) ? $userGroupId : null;
|
||||
$preference->save();
|
||||
|
||||
|
||||
@@ -25,9 +25,11 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\RecurrenceObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -36,6 +38,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([RecurrenceObserver::class])]
|
||||
class Recurrence extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -55,7 +58,7 @@ class Recurrence extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$recurrenceId = (int) $value;
|
||||
$recurrenceId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -113,13 +116,6 @@ class Recurrence extends Model
|
||||
return $this->belongsTo(TransactionType::class);
|
||||
}
|
||||
|
||||
protected function transactionTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -139,4 +135,11 @@ class Recurrence extends Model
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function transactionTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,6 @@ class RecurrenceMeta extends Model
|
||||
return $this->belongsTo(Recurrence::class);
|
||||
}
|
||||
|
||||
protected function recurrenceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -61,4 +54,11 @@ class RecurrenceMeta extends Model
|
||||
'value' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function recurrenceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,16 +36,20 @@ class RecurrenceRepetition extends Model
|
||||
use ReturnsIntegerIdTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int WEEKEND_DO_NOTHING = 1;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int WEEKEND_SKIP_CREATION = 2;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int WEEKEND_TO_FRIDAY = 3;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const int WEEKEND_TO_MONDAY = 4;
|
||||
|
||||
protected $casts
|
||||
@@ -78,21 +82,21 @@ class RecurrenceRepetition extends Model
|
||||
protected function recurrenceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function repetitionSkip(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function weekend(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\RecurrenceTransactionObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
#[ObservedBy([RecurrenceTransactionObserver::class])]
|
||||
class RecurrenceTransaction extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -88,49 +91,7 @@ class RecurrenceTransaction extends Model
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function destinationId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function foreignAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function recurrenceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function sourceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function userId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -145,4 +106,46 @@ class RecurrenceTransaction extends Model
|
||||
'description' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function destinationId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function foreignAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function recurrenceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function sourceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionCurrencyId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function userId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,6 @@ class RecurrenceTransactionMeta extends Model
|
||||
return $this->belongsTo(RecurrenceTransaction::class, 'rt_id');
|
||||
}
|
||||
|
||||
protected function rtId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -61,4 +54,11 @@ class RecurrenceTransactionMeta extends Model
|
||||
'value' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
protected function rtId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\RuleObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -33,6 +35,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([RuleObserver::class])]
|
||||
class Rule extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -49,7 +52,7 @@ class Rule extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$ruleId = (int) $value;
|
||||
$ruleId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -84,30 +87,11 @@ class Rule extends Model
|
||||
return $this->hasMany(RuleTrigger::class);
|
||||
}
|
||||
|
||||
protected function description(): Attribute
|
||||
{
|
||||
return Attribute::make(set: fn ($value) => ['description' => e($value)]);
|
||||
}
|
||||
|
||||
public function userGroup(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(UserGroup::class);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function ruleGroupId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -123,4 +107,23 @@ class Rule extends Model
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function description(): Attribute
|
||||
{
|
||||
return Attribute::make(set: fn ($value) => ['description' => e($value)]);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function ruleGroupId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class RuleAction extends Model
|
||||
if (false === config('firefly.feature_flags.expression_engine')) {
|
||||
Log::debug('Expression engine is disabled, returning action value as string.');
|
||||
|
||||
return (string) $this->action_value;
|
||||
return (string)$this->action_value;
|
||||
}
|
||||
if (true === config('firefly.feature_flags.expression_engine') && str_starts_with($this->action_value, '\=')) {
|
||||
// return literal string.
|
||||
@@ -54,7 +54,7 @@ class RuleAction extends Model
|
||||
$result = $expr->evaluate($journal);
|
||||
} catch (SyntaxError $e) {
|
||||
Log::error(sprintf('Expression engine failed to evaluate expression "%s" with error "%s".', $this->action_value, $e->getMessage()));
|
||||
$result = (string) $this->action_value;
|
||||
$result = (string)$this->action_value;
|
||||
}
|
||||
Log::debug(sprintf('Expression engine is enabled, result of expression "%s" is "%s".', $this->action_value, $result));
|
||||
|
||||
@@ -66,20 +66,6 @@ class RuleAction extends Model
|
||||
return $this->belongsTo(Rule::class);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function ruleId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -90,4 +76,18 @@ class RuleAction extends Model
|
||||
'stop_processing' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function ruleId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\RuleGroupObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -33,6 +35,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([RuleGroupObserver::class])]
|
||||
class RuleGroup extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -49,7 +52,7 @@ class RuleGroup extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$ruleGroupId = (int) $value;
|
||||
$ruleGroupId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -74,13 +77,6 @@ class RuleGroup extends Model
|
||||
return $this->hasMany(Rule::class);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -94,4 +90,11 @@ class RuleGroup extends Model
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,20 +39,6 @@ class RuleTrigger extends Model
|
||||
return $this->belongsTo(Rule::class);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function ruleId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -63,4 +49,18 @@ class RuleTrigger extends Model
|
||||
'stop_processing' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function ruleId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,11 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\TagObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@@ -34,6 +36,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([TagObserver::class])]
|
||||
class Tag extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -42,7 +45,7 @@ class Tag extends Model
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'tag', 'date', 'date_tz', 'description', 'tag_mode'];
|
||||
|
||||
protected $hidden = ['zoomLevel', 'latitude', 'longitude'];
|
||||
protected $hidden = ['zoomLevel', 'zoom_level', 'latitude', 'longitude'];
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
@@ -52,7 +55,7 @@ class Tag extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$tagId = (int) $value;
|
||||
$tagId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Handlers\Observer\TransactionObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@@ -34,6 +36,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
#[ObservedBy([TransactionObserver::class])]
|
||||
class Transaction extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
@@ -89,6 +92,31 @@ class Transaction extends Model
|
||||
return $this->belongsTo(TransactionCurrency::class, 'foreign_currency_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setAmountAttribute($value): void
|
||||
{
|
||||
$this->attributes['amount'] = (string)$value;
|
||||
}
|
||||
|
||||
public function transactionCurrency(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TransactionCurrency::class);
|
||||
}
|
||||
|
||||
public function transactionJournal(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TransactionJournal::class);
|
||||
}
|
||||
|
||||
protected function accountId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for transactions AFTER a specified date.
|
||||
*/
|
||||
@@ -117,6 +145,23 @@ class Transaction extends Model
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount
|
||||
*/
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function balanceDirty(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => 1 === (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for transactions BEFORE the specified date.
|
||||
*/
|
||||
@@ -129,78 +174,6 @@ class Transaction extends Model
|
||||
$query->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'));
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function transactionTypes(Builder $query, array $types): void
|
||||
{
|
||||
if (!self::isJoined($query, 'transaction_journals')) {
|
||||
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
|
||||
}
|
||||
|
||||
if (!self::isJoined($query, 'transaction_types')) {
|
||||
$query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
|
||||
}
|
||||
$query->whereIn('transaction_types.type', $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setAmountAttribute($value): void
|
||||
{
|
||||
$this->attributes['amount'] = (string) $value;
|
||||
}
|
||||
|
||||
public function transactionCurrency(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TransactionCurrency::class);
|
||||
}
|
||||
|
||||
public function transactionJournal(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TransactionJournal::class);
|
||||
}
|
||||
|
||||
protected function accountId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount
|
||||
*/
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function balanceDirty(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => 1 === (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign amount
|
||||
*/
|
||||
protected function foreignAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionJournalId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -221,4 +194,34 @@ class Transaction extends Model
|
||||
'native_foreign_amount' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign amount
|
||||
*/
|
||||
protected function foreignAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionJournalId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function transactionTypes(Builder $query, array $types): void
|
||||
{
|
||||
if (!self::isJoined($query, 'transaction_journals')) {
|
||||
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
|
||||
}
|
||||
|
||||
if (!self::isJoined($query, 'transaction_types')) {
|
||||
$query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
|
||||
}
|
||||
$query->whereIn('transaction_types.type', $types);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class TransactionCurrency extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$currencyId = (int) $value;
|
||||
$currencyId = (int)$value;
|
||||
$currency = self::find($currencyId);
|
||||
if (null !== $currency) {
|
||||
$currency->refreshForUser(auth()->user());
|
||||
@@ -101,13 +101,6 @@ class TransactionCurrency extends Model
|
||||
return $this->belongsToMany(User::class)->withTimestamps()->withPivot('user_default');
|
||||
}
|
||||
|
||||
protected function decimalPlaces(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -118,4 +111,11 @@ class TransactionCurrency extends Model
|
||||
'enabled' => 'bool',
|
||||
];
|
||||
}
|
||||
|
||||
protected function decimalPlaces(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,15 +23,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\TransactionGroupObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([TransactionGroupObserver::class])]
|
||||
class TransactionGroup extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -49,7 +52,7 @@ class TransactionGroup extends Model
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s("%s")', __METHOD__, $value));
|
||||
if (auth()->check()) {
|
||||
$groupId = (int) $value;
|
||||
$groupId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
@@ -23,13 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Handlers\Observer\TransactionJournalObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@@ -46,6 +48,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @method EloquentBuilder|static after()
|
||||
* @method static EloquentBuilder|static query()
|
||||
*/
|
||||
#[ObservedBy([TransactionJournalObserver::class])]
|
||||
class TransactionJournal extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
@@ -78,7 +81,7 @@ class TransactionJournal extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$journalId = (int) $value;
|
||||
$journalId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -165,32 +168,6 @@ class TransactionJournal extends Model
|
||||
return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function transactionTypes(EloquentBuilder $query, array $types): void
|
||||
{
|
||||
if (!self::isJoined($query, 'transaction_types')) {
|
||||
$query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
|
||||
}
|
||||
if (0 !== count($types)) {
|
||||
$query->whereIn('transaction_types.type', $types);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if tables are joined.
|
||||
*/
|
||||
public static function isJoined(EloquentBuilder $query, string $table): bool
|
||||
{
|
||||
$joins = $query->getQuery()->joins;
|
||||
foreach ($joins as $join) {
|
||||
if ($join->table === $table) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function sourceJournalLinks(): HasMany
|
||||
{
|
||||
return $this->hasMany(TransactionJournalLink::class, 'source_id');
|
||||
@@ -231,20 +208,6 @@ class TransactionJournal extends Model
|
||||
return $this->belongsTo(UserGroup::class);
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -263,4 +226,44 @@ class TransactionJournal extends Model
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
protected function order(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function transactionTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function transactionTypes(EloquentBuilder $query, array $types): void
|
||||
{
|
||||
if (!self::isJoined($query, 'transaction_types')) {
|
||||
$query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
|
||||
}
|
||||
if (0 !== count($types)) {
|
||||
$query->whereIn('transaction_types.type', $types);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if tables are joined.
|
||||
*/
|
||||
public static function isJoined(EloquentBuilder $query, string $table): bool
|
||||
{
|
||||
$joins = $query->getQuery()->joins;
|
||||
foreach ($joins as $join) {
|
||||
if ($join->table === $table) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class TransactionJournalLink extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$linkId = (int) $value;
|
||||
$linkId = (int)$value;
|
||||
$link = self::where('journal_links.id', $linkId)
|
||||
->leftJoin('transaction_journals as t_a', 't_a.id', '=', 'source_id')
|
||||
->leftJoin('transaction_journals as t_b', 't_b.id', '=', 'destination_id')
|
||||
@@ -83,27 +83,6 @@ class TransactionJournalLink extends Model
|
||||
return $this->belongsTo(TransactionJournal::class, 'source_id');
|
||||
}
|
||||
|
||||
protected function destinationId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function linkTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function sourceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -111,4 +90,25 @@ class TransactionJournalLink extends Model
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
protected function destinationId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function linkTypeId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function sourceId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,27 +41,11 @@ class TransactionJournalMeta extends Model
|
||||
|
||||
protected $table = 'journal_meta';
|
||||
|
||||
protected function data(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn ($value) => json_decode((string) $value, false), set: function ($value) {
|
||||
$data = json_encode($value);
|
||||
|
||||
return ['data' => $data, 'hash' => hash('sha256', $data)];
|
||||
});
|
||||
}
|
||||
|
||||
public function transactionJournal(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TransactionJournal::class);
|
||||
}
|
||||
|
||||
protected function transactionJournalId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -70,4 +54,20 @@ class TransactionJournalMeta extends Model
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
protected function data(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn ($value) => json_decode((string)$value, false), set: function ($value) {
|
||||
$data = json_encode($value);
|
||||
|
||||
return ['data' => $data, 'hash' => hash('sha256', $data)];
|
||||
});
|
||||
}
|
||||
|
||||
protected function transactionJournalId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,25 +36,32 @@ class TransactionType extends Model
|
||||
use ReturnsIntegerIdTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string DEPOSIT = 'Deposit';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string INVALID = 'Invalid';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string LIABILITY_CREDIT = 'Liability credit';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string OPENING_BALANCE = 'Opening balance';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string RECONCILIATION = 'Reconciliation';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string TRANSFER = 'Transfer';
|
||||
|
||||
#[Deprecated] /** @deprecated */
|
||||
#[Deprecated]
|
||||
/** @deprecated */
|
||||
public const string WITHDRAWAL = 'Withdrawal';
|
||||
|
||||
protected $casts
|
||||
|
||||
@@ -47,7 +47,7 @@ class UserGroup extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$userGroupId = (int) $value;
|
||||
$userGroupId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
@@ -27,9 +27,11 @@ namespace FireflyIII\Models;
|
||||
use FireflyIII\Enums\WebhookDelivery as WebhookDeliveryEnum;
|
||||
use FireflyIII\Enums\WebhookResponse as WebhookResponseEnum;
|
||||
use FireflyIII\Enums\WebhookTrigger as WebhookTriggerEnum;
|
||||
use FireflyIII\Handlers\Observer\WebhookObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@@ -37,6 +39,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([WebhookObserver::class])]
|
||||
class Webhook extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -151,16 +154,16 @@ class Webhook extends Model
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function webhookMessages(): HasMany
|
||||
{
|
||||
return $this->hasMany(WebhookMessage::class);
|
||||
}
|
||||
|
||||
public function webhookDeliveries(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(WebhookDelivery::class);
|
||||
}
|
||||
|
||||
public function webhookMessages(): HasMany
|
||||
{
|
||||
return $this->hasMany(WebhookMessage::class);
|
||||
}
|
||||
|
||||
public function webhookResponses(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(WebhookResponse::class);
|
||||
|
||||
@@ -45,7 +45,7 @@ class WebhookAttempt extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$attemptId = (int) $value;
|
||||
$attemptId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -68,7 +68,7 @@ class WebhookAttempt extends Model
|
||||
protected function webhookMessageId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class WebhookDelivery extends Model
|
||||
protected function key(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use FireflyIII\Handlers\Observer\WebhookMessageObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
#[ObservedBy([WebhookMessageObserver::class])]
|
||||
class WebhookMessage extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
@@ -44,7 +47,7 @@ class WebhookMessage extends Model
|
||||
public static function routeBinder(string $value): self
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$messageId = (int) $value;
|
||||
$messageId = (int)$value;
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
@@ -69,23 +72,6 @@ class WebhookMessage extends Model
|
||||
return $this->hasMany(WebhookAttempt::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount
|
||||
*/
|
||||
protected function sent(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (bool) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function webhookId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
@@ -96,4 +82,21 @@ class WebhookMessage extends Model
|
||||
'logs' => 'json',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount
|
||||
*/
|
||||
protected function sent(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (bool)$value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function webhookId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class WebhookResponse extends Model
|
||||
protected function key(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class WebhookTrigger extends Model
|
||||
protected function key(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn ($value) => (int) $value,
|
||||
get: static fn ($value) => (int)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,46 +57,6 @@ use FireflyIII\Events\TriggeredAuditLog;
|
||||
use FireflyIII\Events\UpdatedAccount;
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Events\UserChangedEmail;
|
||||
use FireflyIII\Handlers\Observer\AccountObserver;
|
||||
use FireflyIII\Handlers\Observer\AttachmentObserver;
|
||||
use FireflyIII\Handlers\Observer\AutoBudgetObserver;
|
||||
use FireflyIII\Handlers\Observer\AvailableBudgetObserver;
|
||||
use FireflyIII\Handlers\Observer\BillObserver;
|
||||
use FireflyIII\Handlers\Observer\BudgetLimitObserver;
|
||||
use FireflyIII\Handlers\Observer\BudgetObserver;
|
||||
use FireflyIII\Handlers\Observer\CategoryObserver;
|
||||
use FireflyIII\Handlers\Observer\PiggyBankEventObserver;
|
||||
use FireflyIII\Handlers\Observer\PiggyBankObserver;
|
||||
use FireflyIII\Handlers\Observer\RecurrenceObserver;
|
||||
use FireflyIII\Handlers\Observer\RecurrenceTransactionObserver;
|
||||
use FireflyIII\Handlers\Observer\RuleGroupObserver;
|
||||
use FireflyIII\Handlers\Observer\RuleObserver;
|
||||
use FireflyIII\Handlers\Observer\TagObserver;
|
||||
use FireflyIII\Handlers\Observer\TransactionGroupObserver;
|
||||
use FireflyIII\Handlers\Observer\TransactionJournalObserver;
|
||||
use FireflyIII\Handlers\Observer\TransactionObserver;
|
||||
use FireflyIII\Handlers\Observer\WebhookMessageObserver;
|
||||
use FireflyIII\Handlers\Observer\WebhookObserver;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\AutoBudget;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Models\WebhookMessage;
|
||||
use Illuminate\Auth\Events\Login;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Laravel\Passport\Events\AccessTokenCreated;
|
||||
@@ -256,32 +216,5 @@ class EventServiceProvider extends ServiceProvider
|
||||
* Register any events for your application.
|
||||
*/
|
||||
#[Override]
|
||||
public function boot(): void
|
||||
{
|
||||
$this->registerObservers();
|
||||
}
|
||||
|
||||
private function registerObservers(): void
|
||||
{
|
||||
Attachment::observe(new AttachmentObserver());
|
||||
Account::observe(new AccountObserver());
|
||||
AutoBudget::observe(new AutoBudgetObserver());
|
||||
AvailableBudget::observe(new AvailableBudgetObserver());
|
||||
Bill::observe(new BillObserver());
|
||||
Budget::observe(new BudgetObserver());
|
||||
BudgetLimit::observe(new BudgetLimitObserver());
|
||||
Category::observe(new CategoryObserver());
|
||||
PiggyBank::observe(new PiggyBankObserver());
|
||||
PiggyBankEvent::observe(new PiggyBankEventObserver());
|
||||
Recurrence::observe(new RecurrenceObserver());
|
||||
RecurrenceTransaction::observe(new RecurrenceTransactionObserver());
|
||||
Rule::observe(new RuleObserver());
|
||||
RuleGroup::observe(new RuleGroupObserver());
|
||||
Tag::observe(new TagObserver());
|
||||
Transaction::observe(new TransactionObserver());
|
||||
TransactionJournal::observe(new TransactionJournalObserver());
|
||||
TransactionGroup::observe(new TransactionGroupObserver());
|
||||
Webhook::observe(new WebhookObserver());
|
||||
WebhookMessage::observe(new WebhookMessageObserver());
|
||||
}
|
||||
public function boot(): void {}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,10 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use FireflyIII\Support\Singleton\PreferencesSingleton;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -271,7 +273,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
|
||||
if (null === $currency) {
|
||||
$currency = app('amount')->getPrimaryCurrencyByUserGroup($this->user->userGroup);
|
||||
$currency = Amount::getPrimaryCurrencyByUserGroup($this->user->userGroup);
|
||||
}
|
||||
$currency->enabled = true;
|
||||
$currency->save();
|
||||
@@ -293,7 +295,11 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
|
||||
if (null !== $limit) {
|
||||
throw new FireflyException('200027: Budget limit already exists.');
|
||||
}
|
||||
app('log')->debug('No existing budget limit, create a new one');
|
||||
Log::debug('No existing budget limit, create a new one');
|
||||
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
$singleton->setPreference('fire_webhooks_bl_store', $data['fire_webhooks'] ?? true);
|
||||
|
||||
// or create one and return it.
|
||||
$limit = new BudgetLimit();
|
||||
@@ -309,7 +315,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
|
||||
$this->setNoteText($limit, $noteText);
|
||||
}
|
||||
|
||||
app('log')->debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $data['amount']));
|
||||
Log::debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $data['amount']));
|
||||
|
||||
return $limit;
|
||||
}
|
||||
@@ -369,11 +375,15 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
|
||||
}
|
||||
// catch unexpected null:
|
||||
if (null === $currency) {
|
||||
$currency = $budgetLimit->transactionCurrency ?? app('amount')->getPrimaryCurrencyByUserGroup($this->user->userGroup);
|
||||
$currency = $budgetLimit->transactionCurrency ?? Amount::getPrimaryCurrencyByUserGroup($this->user->userGroup);
|
||||
}
|
||||
$currency->enabled = true;
|
||||
$currency->save();
|
||||
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
$singleton->setPreference('fire_webhooks_bl_update', $data['fire_webhooks'] ?? true);
|
||||
|
||||
$budgetLimit->transaction_currency_id = $currency->id;
|
||||
$budgetLimit->save();
|
||||
|
||||
@@ -385,63 +395,63 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
|
||||
return $budgetLimit;
|
||||
}
|
||||
|
||||
public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit
|
||||
{
|
||||
// count the limits:
|
||||
$limits = $budget->budgetlimits()
|
||||
->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00'))
|
||||
->count('budget_limits.*')
|
||||
;
|
||||
app('log')->debug(sprintf('Found %d budget limits.', $limits));
|
||||
|
||||
// there might be a budget limit for these dates:
|
||||
/** @var null|BudgetLimit $limit */
|
||||
$limit = $budget->budgetlimits()
|
||||
->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00'))
|
||||
->first(['budget_limits.*'])
|
||||
;
|
||||
|
||||
// if more than 1 limit found, delete the others:
|
||||
if ($limits > 1 && null !== $limit) {
|
||||
app('log')->debug(sprintf('Found more than 1, delete all except #%d', $limit->id));
|
||||
$budget->budgetlimits()
|
||||
->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.id', '!=', $limit->id)->delete()
|
||||
;
|
||||
}
|
||||
|
||||
// delete if amount is zero.
|
||||
// Returns 0 if the two operands are equal,
|
||||
// 1 if the left_operand is larger than the right_operand, -1 otherwise.
|
||||
if (null !== $limit && bccomp($amount, '0') <= 0) {
|
||||
app('log')->debug(sprintf('%s is zero, delete budget limit #%d', $amount, $limit->id));
|
||||
$limit->delete();
|
||||
|
||||
return null;
|
||||
}
|
||||
// update if exists:
|
||||
if (null !== $limit) {
|
||||
app('log')->debug(sprintf('Existing budget limit is #%d, update this to amount %s', $limit->id, $amount));
|
||||
$limit->amount = $amount;
|
||||
$limit->save();
|
||||
|
||||
return $limit;
|
||||
}
|
||||
app('log')->debug('No existing budget limit, create a new one');
|
||||
// or create one and return it.
|
||||
$limit = new BudgetLimit();
|
||||
$limit->budget()->associate($budget);
|
||||
$limit->start_date = $start->startOfDay();
|
||||
$limit->start_date_tz = $start->format('e');
|
||||
$limit->end_date = $end->startOfDay();
|
||||
$limit->end_date_tz = $end->format('e');
|
||||
$limit->amount = $amount;
|
||||
$limit->save();
|
||||
app('log')->debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $amount));
|
||||
|
||||
return $limit;
|
||||
}
|
||||
// public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit
|
||||
// {
|
||||
// // count the limits:
|
||||
// $limits = $budget->budgetlimits()
|
||||
// ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00'))
|
||||
// ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00'))
|
||||
// ->count('budget_limits.*')
|
||||
// ;
|
||||
// Log::debug(sprintf('Found %d budget limits.', $limits));
|
||||
//
|
||||
// // there might be a budget limit for these dates:
|
||||
// /** @var null|BudgetLimit $limit */
|
||||
// $limit = $budget->budgetlimits()
|
||||
// ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00'))
|
||||
// ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00'))
|
||||
// ->first(['budget_limits.*'])
|
||||
// ;
|
||||
//
|
||||
// // if more than 1 limit found, delete the others:
|
||||
// if ($limits > 1 && null !== $limit) {
|
||||
// Log::debug(sprintf('Found more than 1, delete all except #%d', $limit->id));
|
||||
// $budget->budgetlimits()
|
||||
// ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00'))
|
||||
// ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00'))
|
||||
// ->where('budget_limits.id', '!=', $limit->id)->delete()
|
||||
// ;
|
||||
// }
|
||||
//
|
||||
// // delete if amount is zero.
|
||||
// // Returns 0 if the two operands are equal,
|
||||
// // 1 if the left_operand is larger than the right_operand, -1 otherwise.
|
||||
// if (null !== $limit && bccomp($amount, '0') <= 0) {
|
||||
// Log::debug(sprintf('%s is zero, delete budget limit #%d', $amount, $limit->id));
|
||||
// $limit->delete();
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
// // update if exists:
|
||||
// if (null !== $limit) {
|
||||
// Log::debug(sprintf('Existing budget limit is #%d, update this to amount %s', $limit->id, $amount));
|
||||
// $limit->amount = $amount;
|
||||
// $limit->save();
|
||||
//
|
||||
// return $limit;
|
||||
// }
|
||||
// Log::debug('No existing budget limit, create a new one');
|
||||
// // or create one and return it.
|
||||
// $limit = new BudgetLimit();
|
||||
// $limit->budget()->associate($budget);
|
||||
// $limit->start_date = $start->startOfDay();
|
||||
// $limit->start_date_tz = $start->format('e');
|
||||
// $limit->end_date = $end->startOfDay();
|
||||
// $limit->end_date_tz = $end->format('e');
|
||||
// $limit->amount = $amount;
|
||||
// $limit->save();
|
||||
// Log::debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $amount));
|
||||
//
|
||||
// return $limit;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -81,5 +81,5 @@ interface BudgetLimitRepositoryInterface
|
||||
|
||||
public function update(BudgetLimit $budgetLimit, array $data): BudgetLimit;
|
||||
|
||||
public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit;
|
||||
// public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
|
||||
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use FireflyIII\Support\Singleton\PreferencesSingleton;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -85,7 +86,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
|
||||
public function budgetedInPeriod(Carbon $start, Carbon $end): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in budgetedInPeriod("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
Log::debug(sprintf('Now in budgetedInPeriod("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
$return = [];
|
||||
|
||||
/** @var BudgetLimitRepository $limitRepository */
|
||||
@@ -97,12 +98,12 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
app('log')->debug(sprintf('Budget #%d: "%s"', $budget->id, $budget->name));
|
||||
Log::debug(sprintf('Budget #%d: "%s"', $budget->id, $budget->name));
|
||||
$limits = $limitRepository->getBudgetLimits($budget, $start, $end);
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
app('log')->debug(sprintf('Budget limit #%d', $limit->id));
|
||||
Log::debug(sprintf('Budget limit #%d', $limit->id));
|
||||
$currency = $limit->transactionCurrency;
|
||||
$rate = $converter->getCurrencyRate($currency, $primaryCurrency, $end);
|
||||
$currencyCode = $currency->code;
|
||||
@@ -124,7 +125,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
if ($limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)) {
|
||||
$return[$currencyCode]['sum'] = bcadd($return[$currencyCode]['sum'], (string) $limit->amount);
|
||||
$return[$currencyCode]['pc_sum'] = bcmul($rate, $return[$currencyCode]['sum']);
|
||||
app('log')->debug(sprintf('Add full amount [1]: %s', $limit->amount));
|
||||
Log::debug(sprintf('Add full amount [1]: %s', $limit->amount));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -132,7 +133,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
if ($start->lte($limit->start_date) && $end->gte($limit->end_date)) {
|
||||
$return[$currencyCode]['sum'] = bcadd($return[$currencyCode]['sum'], (string) $limit->amount);
|
||||
$return[$currencyCode]['pc_sum'] = bcmul($rate, $return[$currencyCode]['sum']);
|
||||
app('log')->debug(sprintf('Add full amount [2]: %s', $limit->amount));
|
||||
Log::debug(sprintf('Add full amount [2]: %s', $limit->amount));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -141,7 +142,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
$amount = bcmul(bcdiv((string) $limit->amount, (string) $total), (string) $days);
|
||||
$return[$currencyCode]['sum'] = bcadd($return[$currencyCode]['sum'], $amount);
|
||||
$return[$currencyCode]['pc_sum'] = bcmul($rate, $return[$currencyCode]['sum']);
|
||||
app('log')->debug(
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Amount per day: %s (%s over %d days). Total amount for %d days: %s',
|
||||
bcdiv((string) $limit->amount, (string) $total),
|
||||
@@ -202,19 +203,19 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
|
||||
public function budgetedInPeriodForBudget(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in budgetedInPeriod(#%d, "%s", "%s")', $budget->id, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
Log::debug(sprintf('Now in budgetedInPeriod(#%d, "%s", "%s")', $budget->id, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
$return = [];
|
||||
|
||||
/** @var BudgetLimitRepository $limitRepository */
|
||||
$limitRepository = app(BudgetLimitRepository::class);
|
||||
$limitRepository->setUser($this->user);
|
||||
|
||||
app('log')->debug(sprintf('Budget #%d: "%s"', $budget->id, $budget->name));
|
||||
Log::debug(sprintf('Budget #%d: "%s"', $budget->id, $budget->name));
|
||||
$limits = $limitRepository->getBudgetLimits($budget, $start, $end);
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
app('log')->debug(sprintf('Budget limit #%d', $limit->id));
|
||||
Log::debug(sprintf('Budget limit #%d', $limit->id));
|
||||
$currency = $limit->transactionCurrency;
|
||||
$return[$currency->id] ??= [
|
||||
'id' => (string) $currency->id,
|
||||
@@ -227,14 +228,14 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
// same period
|
||||
if ($limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)) {
|
||||
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], (string) $limit->amount);
|
||||
app('log')->debug(sprintf('Add full amount [1]: %s', $limit->amount));
|
||||
Log::debug(sprintf('Add full amount [1]: %s', $limit->amount));
|
||||
|
||||
continue;
|
||||
}
|
||||
// limit is inside of date range
|
||||
if ($start->lte($limit->start_date) && $end->gte($limit->end_date)) {
|
||||
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], (string) $limit->amount);
|
||||
app('log')->debug(sprintf('Add full amount [2]: %s', $limit->amount));
|
||||
Log::debug(sprintf('Add full amount [2]: %s', $limit->amount));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -242,7 +243,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
$days = $this->daysInOverlap($limit, $start, $end);
|
||||
$amount = bcmul(bcdiv((string) $limit->amount, (string) $total), (string) $days);
|
||||
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount);
|
||||
app('log')->debug(
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Amount per day: %s (%s over %d days). Total amount for %d days: %s',
|
||||
bcdiv((string) $limit->amount, (string) $total),
|
||||
@@ -282,7 +283,11 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
*/
|
||||
public function update(Budget $budget, array $data): Budget
|
||||
{
|
||||
app('log')->debug('Now in update()');
|
||||
Log::debug('Now in update()');
|
||||
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
$singleton->setPreference('fire_webhooks_budget_update', $data['fire_webhooks'] ?? true);
|
||||
|
||||
$oldName = $budget->name;
|
||||
if (array_key_exists('name', $data)) {
|
||||
@@ -330,13 +335,13 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
->where('rule_actions.action_value', $oldName)
|
||||
->get(['rule_actions.*'])
|
||||
;
|
||||
app('log')->debug(sprintf('Found %d actions to update.', $actions->count()));
|
||||
Log::debug(sprintf('Found %d actions to update.', $actions->count()));
|
||||
|
||||
/** @var RuleAction $action */
|
||||
foreach ($actions as $action) {
|
||||
$action->action_value = $newName;
|
||||
$action->save();
|
||||
app('log')->debug(sprintf('Updated action %d: %s', $action->id, $action->action_value));
|
||||
Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,13 +354,13 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
->where('rule_triggers.trigger_value', $oldName)
|
||||
->get(['rule_triggers.*'])
|
||||
;
|
||||
app('log')->debug(sprintf('Found %d triggers to update.', $triggers->count()));
|
||||
Log::debug(sprintf('Found %d triggers to update.', $triggers->count()));
|
||||
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($triggers as $trigger) {
|
||||
$trigger->trigger_value = $newName;
|
||||
$trigger->save();
|
||||
app('log')->debug(sprintf('Updated trigger %d: %s', $trigger->id, $trigger->trigger_value));
|
||||
Log::debug(sprintf('Updated trigger %d: %s', $trigger->id, $trigger->trigger_value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,17 +491,17 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
|
||||
public function findBudget(?int $budgetId, ?string $budgetName): ?Budget
|
||||
{
|
||||
app('log')->debug('Now in findBudget()');
|
||||
app('log')->debug(sprintf('Searching for budget with ID #%d...', $budgetId));
|
||||
Log::debug('Now in findBudget()');
|
||||
Log::debug(sprintf('Searching for budget with ID #%d...', $budgetId));
|
||||
$result = $this->find((int) $budgetId);
|
||||
if (!$result instanceof Budget && null !== $budgetName && '' !== $budgetName) {
|
||||
app('log')->debug(sprintf('Searching for budget with name %s...', $budgetName));
|
||||
Log::debug(sprintf('Searching for budget with name %s...', $budgetName));
|
||||
$result = $this->findByName($budgetName);
|
||||
}
|
||||
if ($result instanceof Budget) {
|
||||
app('log')->debug(sprintf('Found budget #%d: %s', $result->id, $result->name));
|
||||
Log::debug(sprintf('Found budget #%d: %s', $result->id, $result->name));
|
||||
}
|
||||
app('log')->debug(sprintf('Found result is null? %s', var_export(!$result instanceof Budget, true)));
|
||||
Log::debug(sprintf('Found result is null? %s', var_export(!$result instanceof Budget, true)));
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -593,7 +598,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
|
||||
public function spentInPeriod(Carbon $start, Carbon $end): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
|
||||
@@ -655,7 +660,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
|
||||
public function spentInPeriodForBudget(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
|
||||
@@ -724,6 +729,10 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
{
|
||||
$order = $this->getMaxOrder();
|
||||
|
||||
// this is a lame trick to communicate with the observer.
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
$singleton->setPreference('fire_webhooks_budget_create', $data['fire_webhooks'] ?? true);
|
||||
|
||||
try {
|
||||
$newBudget = Budget::create(
|
||||
[
|
||||
@@ -735,8 +744,8 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
|
||||
]
|
||||
);
|
||||
} catch (QueryException $e) {
|
||||
app('log')->error($e->getMessage());
|
||||
app('log')->error($e->getTraceAsString());
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
throw new FireflyException('400002: Could not store budget.', 0, $e);
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
#[Override]
|
||||
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null): array
|
||||
{
|
||||
Log::debug(sprintf('Start of %s(date, date, array, array, "%s").', __METHOD__, $currency?->code));
|
||||
Log::debug(sprintf('Start of %s(%s, %s, array, array, "%s").', __METHOD__, $start->toW3cString(), $end->toW3cString(), $currency?->code));
|
||||
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
||||
// because those expenses only become expenses once they move from the liability to the friend.
|
||||
// 2024-12-24 disable the exclusion for now.
|
||||
|
||||
@@ -370,8 +370,11 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
|
||||
public function getTagObjects(int $journalId): Collection
|
||||
{
|
||||
/** @var TransactionJournal $journal */
|
||||
/** @var null|TransactionJournal $journal */
|
||||
$journal = $this->user->transactionJournals()->find($journalId);
|
||||
if (null === $journal) {
|
||||
return new Collection();
|
||||
}
|
||||
|
||||
return $journal->tags()->whereNull('deleted_at')->get();
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ class Amount
|
||||
}
|
||||
$currency = TransactionCurrency::find($currencyId);
|
||||
if (null === $currency) {
|
||||
$message = sprintf('Could not find a transaction currency with ID #%d', $currencyId);
|
||||
$message = sprintf('Could not find a transaction currency with ID #%d in %s', $currencyId, __METHOD__);
|
||||
Log::error($message);
|
||||
|
||||
throw new FireflyException($message);
|
||||
@@ -150,7 +150,7 @@ class Amount
|
||||
}
|
||||
$currency = TransactionCurrency::whereCode($code)->first();
|
||||
if (null === $currency) {
|
||||
$message = sprintf('Could not find a transaction currency with code "%s"', $code);
|
||||
$message = sprintf('Could not find a transaction currency with code "%s" in %s', $code, __METHOD__);
|
||||
Log::error($message);
|
||||
|
||||
throw new FireflyException($message);
|
||||
|
||||
@@ -40,18 +40,18 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private User $user;
|
||||
private UserGroup $userGroup; // @phpstan-ignore-line
|
||||
private Collection $collection;
|
||||
private array $ids = [];
|
||||
private array $notes = [];
|
||||
private Carbon $start;
|
||||
private Carbon $end;
|
||||
private array $expenses = [];
|
||||
private array $pcExpenses = [];
|
||||
private array $currencyIds = [];
|
||||
private array $currencies = [];
|
||||
private bool $convertToPrimary = true;
|
||||
private User $user;
|
||||
private UserGroup $userGroup; // @phpstan-ignore-line
|
||||
private Collection $collection;
|
||||
private array $ids = [];
|
||||
private array $notes = [];
|
||||
private Carbon $start;
|
||||
private Carbon $end;
|
||||
private array $expenses = [];
|
||||
private array $pcExpenses = [];
|
||||
private array $currencyIds = [];
|
||||
private array $currencies = [];
|
||||
private bool $convertToPrimary = true;
|
||||
private readonly TransactionCurrency $primaryCurrency;
|
||||
|
||||
public function __construct()
|
||||
@@ -154,9 +154,10 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
|
||||
/** @var BudgetLimit $budgetLimit */
|
||||
foreach ($this->collection as $budgetLimit) {
|
||||
Log::debug(sprintf('Filtering expenses for budget limit #%d (budget #%d)', $budgetLimit->id, $budgetLimit->budget_id));
|
||||
$id = (int)$budgetLimit->id;
|
||||
$filteredExpenses = $this->filterToBudget($expenses, $budgetLimit->budget_id);
|
||||
$filteredExpenses = $repository->sumCollectedExpenses($expenses, $budgetLimit->start_date, $budgetLimit->end_date, $budgetLimit->transactionCurrency, false);
|
||||
$filteredExpenses = $repository->sumCollectedExpenses($filteredExpenses, $budgetLimit->start_date, $budgetLimit->end_date, $budgetLimit->transactionCurrency, false);
|
||||
$this->expenses[$id] = array_values($filteredExpenses);
|
||||
|
||||
if (true === $this->convertToPrimary && $budgetLimit->transactionCurrency->id !== $this->primaryCurrency->id) {
|
||||
@@ -195,6 +196,9 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
|
||||
private function filterToBudget(array $expenses, int $budget): array
|
||||
{
|
||||
return array_filter($expenses, fn (array $item) => (int)$item['budget_id'] === $budget);
|
||||
$result = array_filter($expenses, fn (array $item) => (int)$item['budget_id'] === $budget);
|
||||
Log::debug(sprintf('filterToBudget for budget #%d, from %d to %d items', $budget, count($expenses), count($result)));
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +258,12 @@ trait ConvertsDataTypes
|
||||
if ('yes' === $value) {
|
||||
return true;
|
||||
}
|
||||
if ('on' === $value) {
|
||||
return true;
|
||||
}
|
||||
if ('y' === $value) {
|
||||
return true;
|
||||
}
|
||||
if ('1' === $value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -114,20 +114,20 @@ class AmountFormat extends AbstractExtension
|
||||
{
|
||||
return new TwigFunction(
|
||||
'formatAmountBySymbol',
|
||||
static function (string $amount, ?string $symbol, ?int $decimalPlaces = null, ?bool $coloured = null): string {
|
||||
static function (string $amount, ?string $symbol = null, ?int $decimalPlaces = null, ?bool $coloured = null): string {
|
||||
|
||||
if (null === $symbol) {
|
||||
$message = sprintf('formatAmountBySymbol("%s", %s, %d, %s) was called without a symbol. Please browse to /flush to clear your cache.', $amount, var_export($symbol, true), $decimalPlaces, var_export($coloured, true));
|
||||
$message = sprintf('formatAmountBySymbol("%s", %s, %d, %s) was called without a symbol. Please browse to /flush to clear your cache.', $amount, var_export($symbol, true), $decimalPlaces, var_export($coloured, true));
|
||||
Log::error($message);
|
||||
|
||||
throw new FireflyException($message);
|
||||
$currency = Amount::getPrimaryCurrency();
|
||||
}
|
||||
if (null !== $symbol) {
|
||||
$decimalPlaces ??= 2;
|
||||
$coloured ??= true;
|
||||
$currency = new TransactionCurrency();
|
||||
$currency->symbol = $symbol;
|
||||
$currency->decimal_places = $decimalPlaces;
|
||||
}
|
||||
|
||||
$decimalPlaces ??= 2;
|
||||
$coloured ??= true;
|
||||
$currency = new TransactionCurrency();
|
||||
$currency->symbol = $symbol;
|
||||
$currency->decimal_places = $decimalPlaces;
|
||||
|
||||
return Amount::formatAnything($currency, $amount, $coloured);
|
||||
},
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 6.4.0 - 2025-09-19
|
||||
## 6.4.1 - 2025-09-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed a missing filter from [issue 10803](https://github.com/firefly-iii/firefly-iii/issues/10803).
|
||||
|
||||
## 6.4.0 - 2025-09-14
|
||||
|
||||
### Added
|
||||
|
||||
@@ -29,6 +35,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- [Discussion 10846](https://github.com/orgs/firefly-iii/discussions/10846) (Add support for WebP format in attachments) started by @Idestius
|
||||
- [Issue 10853](https://github.com/firefly-iii/firefly-iii/issues/10853) (Failed to Send Discord Notification) reported by @pimonteiro
|
||||
- [Issue 10854](https://github.com/firefly-iii/firefly-iii/issues/10854) (string / null in budget causes budget page to not render) reported by @4e868df3
|
||||
- [Issue 10871](https://github.com/firefly-iii/firefly-iii/issues/10871) (Transactions disappear after deleting attachment) reported by @dvmfa90
|
||||
- [Discussion 10883](https://github.com/orgs/firefly-iii/discussions/10883) (Initial balance for account is missing from exported CSV) started by @ajaskiewiczpl
|
||||
- [Issue 10888](https://github.com/firefly-iii/firefly-iii/issues/10888) (Recurring transation forgets repetition type, skip and weekend action) reported by @mansellrace
|
||||
- [Discussion 10891](https://github.com/orgs/firefly-iii/discussions/10891) (User group id is null when downloading new exchange rates) started by @dakennguyen
|
||||
|
||||
146
composer.lock
generated
146
composer.lock
generated
@@ -324,16 +324,16 @@
|
||||
},
|
||||
{
|
||||
"name": "dasprid/enum",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DASPRiD/Enum.git",
|
||||
"reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90"
|
||||
"reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8dfd07c6d2cf31c8da90c53b83c026c7696dda90",
|
||||
"reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90",
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
|
||||
"reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -368,9 +368,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/DASPRiD/Enum/issues",
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.6"
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.7"
|
||||
},
|
||||
"time": "2024-08-09T14:30:48+00:00"
|
||||
"time": "2025-09-16T12:23:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "defuse/php-encryption",
|
||||
@@ -1878,16 +1878,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.28.1",
|
||||
"version": "v12.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "868c1f2d3dba4df6d21e3a8d818479f094cfd942"
|
||||
"reference": "a9e4c73086f5ba38383e9c1d74b84fe46aac730b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/868c1f2d3dba4df6d21e3a8d818479f094cfd942",
|
||||
"reference": "868c1f2d3dba4df6d21e3a8d818479f094cfd942",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/a9e4c73086f5ba38383e9c1d74b84fe46aac730b",
|
||||
"reference": "a9e4c73086f5ba38383e9c1d74b84fe46aac730b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1915,6 +1915,7 @@
|
||||
"monolog/monolog": "^3.0",
|
||||
"nesbot/carbon": "^3.8.4",
|
||||
"nunomaduro/termwind": "^2.0",
|
||||
"phiki/phiki": "v2.0.0",
|
||||
"php": "^8.2",
|
||||
"psr/container": "^1.1.1|^2.0.1",
|
||||
"psr/log": "^1.0|^2.0|^3.0",
|
||||
@@ -2024,7 +2025,7 @@
|
||||
"ext-pdo": "Required to use all database features.",
|
||||
"ext-posix": "Required to use all features of the queue worker.",
|
||||
"ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).",
|
||||
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
|
||||
"fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).",
|
||||
"filp/whoops": "Required for friendly error pages in development (^2.14.3).",
|
||||
"laravel/tinker": "Required to use the tinker console command (^2.0).",
|
||||
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).",
|
||||
@@ -2093,7 +2094,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-09-04T14:58:12+00:00"
|
||||
"time": "2025-09-16T14:15:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
@@ -4349,6 +4350,77 @@
|
||||
},
|
||||
"time": "2020-10-15T08:29:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phiki/phiki",
|
||||
"version": "v2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phikiphp/phiki.git",
|
||||
"reference": "461f6dd7e91dc3a95463b42f549ac7d0aab4702f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phikiphp/phiki/zipball/461f6dd7e91dc3a95463b42f549ac7d0aab4702f",
|
||||
"reference": "461f6dd7e91dc3a95463b42f549ac7d0aab4702f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"league/commonmark": "^2.5.3",
|
||||
"php": "^8.2",
|
||||
"psr/simple-cache": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/support": "^11.45",
|
||||
"laravel/pint": "^1.18.1",
|
||||
"orchestra/testbench": "^9.15",
|
||||
"pestphp/pest": "^3.5.1",
|
||||
"phpstan/extension-installer": "^1.4.3",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"symfony/var-dumper": "^7.1.6"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Phiki\\Adapters\\Laravel\\PhikiServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Phiki\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ryan Chandler",
|
||||
"email": "support@ryangjchandler.co.uk",
|
||||
"homepage": "https://ryangjchandler.co.uk",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Syntax highlighting using TextMate grammars in PHP.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phikiphp/phiki/issues",
|
||||
"source": "https://github.com/phikiphp/phiki/tree/v2.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/ryangjchandler",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://buymeacoffee.com/ryangjchandler",
|
||||
"type": "other"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-28T18:20:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-http/client-common",
|
||||
"version": "2.7.2",
|
||||
@@ -11332,16 +11404,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.25",
|
||||
"version": "2.1.26",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "4087d28bd252895874e174d65e26b2c202ed893a"
|
||||
"reference": "b13345001a8553ec405b7741be0c6b8d7f8b5bf5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/4087d28bd252895874e174d65e26b2c202ed893a",
|
||||
"reference": "4087d28bd252895874e174d65e26b2c202ed893a",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/b13345001a8553ec405b7741be0c6b8d7f8b5bf5",
|
||||
"reference": "b13345001a8553ec405b7741be0c6b8d7f8b5bf5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11386,7 +11458,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-12T14:26:42+00:00"
|
||||
"time": "2025-09-16T11:33:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
@@ -11819,16 +11891,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "12.3.10",
|
||||
"version": "12.3.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "0d401d0df2e3c1703be425ecdc2d04f5c095938d"
|
||||
"reference": "6a62f2b394e042884e4997ddc8b8db1ce56a0009"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0d401d0df2e3c1703be425ecdc2d04f5c095938d",
|
||||
"reference": "0d401d0df2e3c1703be425ecdc2d04f5c095938d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6a62f2b394e042884e4997ddc8b8db1ce56a0009",
|
||||
"reference": "6a62f2b394e042884e4997ddc8b8db1ce56a0009",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11847,7 +11919,7 @@
|
||||
"phpunit/php-invoker": "^6.0.0",
|
||||
"phpunit/php-text-template": "^5.0.0",
|
||||
"phpunit/php-timer": "^8.0.0",
|
||||
"sebastian/cli-parser": "^4.0.0",
|
||||
"sebastian/cli-parser": "^4.1.0",
|
||||
"sebastian/comparator": "^7.1.3",
|
||||
"sebastian/diff": "^7.0.0",
|
||||
"sebastian/environment": "^8.0.3",
|
||||
@@ -11896,7 +11968,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.10"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11920,7 +11992,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-11T10:35:19+00:00"
|
||||
"time": "2025-09-14T06:21:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
@@ -11984,16 +12056,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
"version": "4.0.0",
|
||||
"version": "4.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/cli-parser.git",
|
||||
"reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c"
|
||||
"reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/6d584c727d9114bcdc14c86711cd1cad51778e7c",
|
||||
"reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04",
|
||||
"reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12005,7 +12077,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "4.0-dev"
|
||||
"dev-main": "4.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -12029,15 +12101,27 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
|
||||
"security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/cli-parser/tree/4.0.0"
|
||||
"source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-07T04:53:50+00:00"
|
||||
"time": "2025-09-14T09:36:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
|
||||
@@ -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-13',
|
||||
'build_time' => 1757740598,
|
||||
'version' => 'develop/2025-09-16',
|
||||
'build_time' => 1758048808,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 26,
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ return new class () extends Migration {
|
||||
$table->dropColumn('transaction_currency_id');
|
||||
|
||||
// 2. make column non-nullable.
|
||||
$table->unsignedInteger('account_id')->change();
|
||||
$table->unsignedInteger('account_id')->nullable()->change();
|
||||
|
||||
// 5. add new index
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
|
||||
234
package-lock.json
generated
234
package-lock.json
generated
@@ -2589,9 +2589,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz",
|
||||
"integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz",
|
||||
"integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2603,9 +2603,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz",
|
||||
"integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz",
|
||||
"integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2617,9 +2617,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz",
|
||||
"integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz",
|
||||
"integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2631,9 +2631,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz",
|
||||
"integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz",
|
||||
"integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2645,9 +2645,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz",
|
||||
"integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz",
|
||||
"integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2659,9 +2659,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz",
|
||||
"integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz",
|
||||
"integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2673,9 +2673,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz",
|
||||
"integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz",
|
||||
"integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2687,9 +2687,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz",
|
||||
"integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz",
|
||||
"integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2701,9 +2701,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz",
|
||||
"integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz",
|
||||
"integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2715,9 +2715,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz",
|
||||
"integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz",
|
||||
"integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2728,10 +2728,10 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz",
|
||||
"integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==",
|
||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz",
|
||||
"integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
@@ -2743,9 +2743,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz",
|
||||
"integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz",
|
||||
"integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -2757,9 +2757,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz",
|
||||
"integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz",
|
||||
"integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -2771,9 +2771,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz",
|
||||
"integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz",
|
||||
"integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -2785,9 +2785,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz",
|
||||
"integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz",
|
||||
"integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -2799,9 +2799,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz",
|
||||
"integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz",
|
||||
"integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2813,9 +2813,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz",
|
||||
"integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz",
|
||||
"integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2827,9 +2827,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz",
|
||||
"integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz",
|
||||
"integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2841,9 +2841,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz",
|
||||
"integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz",
|
||||
"integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2855,9 +2855,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz",
|
||||
"integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz",
|
||||
"integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -2869,9 +2869,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz",
|
||||
"integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz",
|
||||
"integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3159,13 +3159,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.3.tgz",
|
||||
"integrity": "sha512-GKBNHjoNw3Kra1Qg5UXttsY5kiWMEfoHq2TmXb+b1rcm6N7B3wTrFYIf/oSZ1xNQ+hVVijgLkiDZh7jRRsh+Gw==",
|
||||
"version": "24.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.0.tgz",
|
||||
"integrity": "sha512-y1dMvuvJspJiPSDZUQ+WMBvF7dpnEqN4x9DDC9ie5Fs/HUZJA3wFp7EhHoVaKX/iI0cRoECV8X2jL8zi0xrHCg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.10.0"
|
||||
"undici-types": "~7.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-forge": {
|
||||
@@ -3949,9 +3949,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz",
|
||||
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==",
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4061,9 +4061,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.2.tgz",
|
||||
"integrity": "sha512-NvcIedLxrs9llVpX7wI+Jz4Hn9vJQkCPKrTaHIE0sW/Rj1iq6Fzby4NbyTZjQJNoypBXNaG7tEHkTgONZpwgxQ==",
|
||||
"version": "2.8.4",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.4.tgz",
|
||||
"integrity": "sha512-L+YvJwGAgwJBV1p6ffpSTa2KRc69EeeYGYjRVWKs0GKrK+LON0GC0gV+rKSNtALEDvMDqkvCFq9r1r94/Gjwxw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -4347,9 +4347,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.26.0",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz",
|
||||
"integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==",
|
||||
"version": "4.26.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz",
|
||||
"integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -4367,7 +4367,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.2",
|
||||
"baseline-browser-mapping": "^2.8.3",
|
||||
"caniuse-lite": "^1.0.30001741",
|
||||
"electron-to-chromium": "^1.5.218",
|
||||
"node-releases": "^2.0.21",
|
||||
@@ -4508,9 +4508,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001741",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz",
|
||||
"integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==",
|
||||
"version": "1.0.30001743",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz",
|
||||
"integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -5375,9 +5375,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5819,9 +5819,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
|
||||
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -10145,9 +10145,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.50.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.1.tgz",
|
||||
"integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==",
|
||||
"version": "4.50.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz",
|
||||
"integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -10161,27 +10161,27 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.50.1",
|
||||
"@rollup/rollup-android-arm64": "4.50.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.50.1",
|
||||
"@rollup/rollup-darwin-x64": "4.50.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.50.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.50.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.50.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.50.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.50.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.50.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.50.1",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.50.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.50.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.50.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.50.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.50.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.50.1",
|
||||
"@rollup/rollup-openharmony-arm64": "4.50.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.50.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.50.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.50.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.50.2",
|
||||
"@rollup/rollup-android-arm64": "4.50.2",
|
||||
"@rollup/rollup-darwin-arm64": "4.50.2",
|
||||
"@rollup/rollup-darwin-x64": "4.50.2",
|
||||
"@rollup/rollup-freebsd-arm64": "4.50.2",
|
||||
"@rollup/rollup-freebsd-x64": "4.50.2",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.50.2",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.50.2",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.50.2",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.50.2",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.50.2",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.50.2",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.50.2",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.50.2",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.50.2",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.50.2",
|
||||
"@rollup/rollup-linux-x64-musl": "4.50.2",
|
||||
"@rollup/rollup-openharmony-arm64": "4.50.2",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.50.2",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.50.2",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.50.2",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@@ -11357,9 +11357,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
|
||||
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
|
||||
"version": "7.12.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz",
|
||||
"integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -11398,9 +11398,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/unicode-property-aliases-ecmascript": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
|
||||
"integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz",
|
||||
"integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
"url": "URL",
|
||||
"active": "Attivo",
|
||||
"interest_date": "Data di valuta",
|
||||
"administration_currency": "Primary currency",
|
||||
"administration_currency": "Valuta primaria",
|
||||
"title": "Titolo",
|
||||
"date": "Data",
|
||||
"book_date": "Data contabile",
|
||||
@@ -180,7 +180,7 @@
|
||||
"list": {
|
||||
"title": "Titolo",
|
||||
"active": "\u00c8 attivo?",
|
||||
"primary_currency": "Primary currency",
|
||||
"primary_currency": "Valuta primaria",
|
||||
"trigger": "Trigger",
|
||||
"response": "Risposta",
|
||||
"delivery": "Consegna",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'limit_exists' => 'There is already a budget limit (amount) for this budget and currency in the given period.',
|
||||
'invalid_sort_instruction' => 'The sort instruction is invalid for an object of type ":object".',
|
||||
'invalid_sort_instruction_index' => 'The sort instruction at index #:index is invalid for an object of type ":object".',
|
||||
'no_sort_instructions' => 'There are no sort instructions defined for an object of type ":object".',
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
{% set boxSize = 4 %}
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
{% for index,journal in selectedGroup.transactions %}
|
||||
{% for index, journal in selectedGroup.transactions %}
|
||||
<div class="col-lg-{{ boxSize }}">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
@@ -440,7 +440,7 @@
|
||||
<td style="width:40%;">{{ 'tags'|_ }}</td>
|
||||
<td>
|
||||
{% for tag in journal.tags %}
|
||||
{% if null != tag.id %}
|
||||
{% if null != tag.id and '' != tag.id %}
|
||||
<h4 style="display: inline;"><a class="label label-success" href="{{ route('tags.show', [tag.id]) }}"><span class="fa fa-fw fa-tag"></span>{{ tag.tag }}</a></h4>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
Reference in New Issue
Block a user