mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-02-15 16:20:33 +00:00
Compare commits
100 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7110556ef0 | ||
|
|
3e1b703dfc | ||
|
|
fce0750509 | ||
|
|
f5385d0229 | ||
|
|
8599c4a3c1 | ||
|
|
d210e7dcdd | ||
|
|
8de9e0ba29 | ||
|
|
7fa9e79f2a | ||
|
|
4a5281fd80 | ||
|
|
ad60974430 | ||
|
|
195794881b | ||
|
|
3e6a997dd5 | ||
|
|
2eedfd9f26 | ||
|
|
9ec0515bb6 | ||
|
|
6b197eecb9 | ||
|
|
591c970882 | ||
|
|
15d91dbe1b | ||
|
|
6ff87bf447 | ||
|
|
147ce154d8 | ||
|
|
2c8be33000 | ||
|
|
b472890c84 | ||
|
|
2fabcf5193 | ||
|
|
5ed4e7aa79 | ||
|
|
973caad7e4 | ||
|
|
d273503a15 | ||
|
|
cc149adb5d | ||
|
|
ac8bcb786b | ||
|
|
642deefba5 | ||
|
|
5b13b64fd7 | ||
|
|
653a64d0a8 | ||
|
|
c9dcdc90ec | ||
|
|
1f04888331 | ||
|
|
28c21ecb7e | ||
|
|
7382030e61 | ||
|
|
a573e19dbc | ||
|
|
b152a2c8d9 | ||
|
|
7e14c36fc0 | ||
|
|
58bfc7f8ce | ||
|
|
6b8c005108 | ||
|
|
ceb660fd02 | ||
|
|
7fac1e8614 | ||
|
|
809e34f5fe | ||
|
|
73ca57c8c4 | ||
|
|
63088ffeb1 | ||
|
|
4e88ebd52d | ||
|
|
85fd38d146 | ||
|
|
e83d7051eb | ||
|
|
567f2dae17 | ||
|
|
c231ae4016 | ||
|
|
fb13a4cdcb | ||
|
|
724042e1d8 | ||
|
|
84a30c3c8f | ||
|
|
6c9dac831a | ||
|
|
e605ddb779 | ||
|
|
4b19ed8f07 | ||
|
|
57bd8e09d4 | ||
|
|
32f1a7c9c2 | ||
|
|
fc5b0db43f | ||
|
|
c2721f3f48 | ||
|
|
96291c9bce | ||
|
|
ab9400aaee | ||
|
|
31d1ee11cb | ||
|
|
694dc3816c | ||
|
|
c647fa7b94 | ||
|
|
022d59bfdd | ||
|
|
057b82b471 | ||
|
|
2872c6592f | ||
|
|
fa02c15f55 | ||
|
|
c74c8a96b8 | ||
|
|
2c2ebae8fa | ||
|
|
aff9afb767 | ||
|
|
c8e95fe131 | ||
|
|
cef514c22b | ||
|
|
46d2ba3d3b | ||
|
|
45a0504eba | ||
|
|
9711bc1d04 | ||
|
|
cf2343c0dd | ||
|
|
34097cecf0 | ||
|
|
8735be2f6b | ||
|
|
0e8cc91308 | ||
|
|
5cbb311e4d | ||
|
|
c334641b90 | ||
|
|
4c2356881d | ||
|
|
d9a0d06712 | ||
|
|
65b9dedc03 | ||
|
|
e46ef138b1 | ||
|
|
f0fdb57754 | ||
|
|
09799582aa | ||
|
|
850c824da1 | ||
|
|
34160da67a | ||
|
|
2848a64c13 | ||
|
|
998d6bf874 | ||
|
|
b85200e1f6 | ||
|
|
6944001887 | ||
|
|
154abf1fc0 | ||
|
|
0113cc1651 | ||
|
|
38b5b656a1 | ||
|
|
e74163a7ec | ||
|
|
c60094d231 | ||
|
|
39d46d469c |
62
.ci/php-cs-fixer/composer.lock
generated
62
.ci/php-cs-fixer/composer.lock
generated
@@ -402,16 +402,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.93.1",
|
||||
"version": "v3.94.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "b3546ab487c0762c39f308dc1ec0ea2c461fc21a"
|
||||
"reference": "883b20fb38c7866de9844ab6d0a205c423bde2d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/b3546ab487c0762c39f308dc1ec0ea2c461fc21a",
|
||||
"reference": "b3546ab487c0762c39f308dc1ec0ea2c461fc21a",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/883b20fb38c7866de9844ab6d0a205c423bde2d4",
|
||||
"reference": "883b20fb38c7866de9844ab6d0a205c423bde2d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -428,7 +428,7 @@
|
||||
"react/event-loop": "^1.5",
|
||||
"react/socket": "^1.16",
|
||||
"react/stream": "^1.4",
|
||||
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
|
||||
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0",
|
||||
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0",
|
||||
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
|
||||
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
|
||||
@@ -442,18 +442,18 @@
|
||||
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.7",
|
||||
"infection/infection": "^0.32",
|
||||
"justinrainbow/json-schema": "^6.6",
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.7.1",
|
||||
"infection/infection": "^0.32.3",
|
||||
"justinrainbow/json-schema": "^6.6.4",
|
||||
"keradus/cli-executor": "^2.3",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
"php-coveralls/php-coveralls": "^2.9",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
||||
"phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.48",
|
||||
"php-coveralls/php-coveralls": "^2.9.1",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7",
|
||||
"phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51",
|
||||
"symfony/polyfill-php85": "^1.33",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0"
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "For handling output formats in XML",
|
||||
@@ -494,7 +494,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.93.1"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -502,7 +502,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-28T23:50:50+00:00"
|
||||
"time": "2026-02-11T16:44:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -1185,29 +1185,29 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "7.0.0",
|
||||
"version": "8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f"
|
||||
"reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a2b6d09d7729ee87d605a439469f9dcc39be5ea3",
|
||||
"reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3"
|
||||
"php": ">=8.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^12.0",
|
||||
"phpunit/phpunit": "^13.0",
|
||||
"symfony/process": "^7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "7.0-dev"
|
||||
"dev-main": "8.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1240,15 +1240,27 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/8.0.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/diff",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-07T04:55:46+00:00"
|
||||
"time": "2026-02-06T04:42:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
|
||||
BIN
.github/assets/img/testmu.png
vendored
Normal file
BIN
.github/assets/img/testmu.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
7
.github/mergify.yml
vendored
7
.github/mergify.yml
vendored
@@ -1,11 +1,4 @@
|
||||
pull_request_rules:
|
||||
- name: Make sure PR are up to date before merging
|
||||
description: This automatically updates PRs when they are out-of-date with the
|
||||
base branch to avoid semantic conflicts (next step is using a merge
|
||||
queue).
|
||||
conditions: []
|
||||
actions:
|
||||
update:
|
||||
- name: Close all on main
|
||||
conditions:
|
||||
- base=main
|
||||
|
||||
@@ -167,7 +167,7 @@ class BasicController extends Controller
|
||||
],
|
||||
];
|
||||
$newIncomes = [
|
||||
$primary->id => [
|
||||
$primary->id => [
|
||||
'currency_id' => $primary->id,
|
||||
'currency_code' => $primary->code,
|
||||
'currency_symbol' => $primary->symbol,
|
||||
@@ -176,7 +176,7 @@ class BasicController extends Controller
|
||||
],
|
||||
];
|
||||
$sums = [
|
||||
$primary->id => [
|
||||
$primary->id => [
|
||||
'currency_id' => $primary->id,
|
||||
'currency_code' => $primary->code,
|
||||
'currency_symbol' => $primary->symbol,
|
||||
@@ -244,7 +244,7 @@ class BasicController extends Controller
|
||||
// create objects for big array.
|
||||
$return[] = [
|
||||
'key' => sprintf('balance-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => $sums[$currencyId]['sum'] ?? '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -258,7 +258,7 @@ class BasicController extends Controller
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('spent-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => $expenses[$currencyId]['sum'] ?? '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -270,7 +270,7 @@ class BasicController extends Controller
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('earned-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => $incomes[$currencyId]['sum'] ?? '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -286,7 +286,7 @@ class BasicController extends Controller
|
||||
// create objects for big array.
|
||||
$return[] = [
|
||||
'key' => sprintf('balance-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -298,7 +298,7 @@ class BasicController extends Controller
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('spent-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -310,7 +310,7 @@ class BasicController extends Controller
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('earned-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -345,7 +345,7 @@ class BasicController extends Controller
|
||||
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
|
||||
$return[$currencyId] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $currencies[$currencyId]->code),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currencies[$currencyId]->symbol]),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currencies[$currencyId]->symbol]),
|
||||
'no_available_budgets' => false,
|
||||
'monetary_value' => $availableBudget,
|
||||
'currency_id' => (string) $currencies[$currencyId]->id,
|
||||
@@ -386,7 +386,7 @@ class BasicController extends Controller
|
||||
|
||||
$return[$currencyId] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
|
||||
'no_available_budgets' => false,
|
||||
'monetary_value' => $leftToSpend,
|
||||
'currency_id' => (string) $row['currency_id'],
|
||||
@@ -493,7 +493,7 @@ class BasicController extends Controller
|
||||
// return stuff
|
||||
$return[] = [
|
||||
'key' => sprintf('net-worth-in-%s', $data['currency_code']),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $data['currency_symbol']]),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $data['currency_symbol']]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => (string) $data['currency_id'],
|
||||
'currency_code' => $data['currency_code'],
|
||||
@@ -507,7 +507,7 @@ class BasicController extends Controller
|
||||
if (0 === count($return)) {
|
||||
$return[] = [
|
||||
'key' => sprintf('net-worth-in-%s', $this->primaryCurrency->code),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $this->primaryCurrency->symbol]),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $this->primaryCurrency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $this->primaryCurrency->id,
|
||||
'currency_code' => $this->primaryCurrency->code,
|
||||
@@ -533,7 +533,7 @@ class BasicController extends Controller
|
||||
*/
|
||||
$paidAmount = $this->billRepository->sumPaidInRange($start, $end);
|
||||
$unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end);
|
||||
$currencies = [$this->primaryCurrency->id => $this->primaryCurrency];
|
||||
$currencies = [$this->primaryCurrency->id => $this->primaryCurrency];
|
||||
|
||||
if ($this->convertToPrimary) {
|
||||
$converter = new ExchangeRateConverter();
|
||||
@@ -598,7 +598,7 @@ class BasicController extends Controller
|
||||
$amount = bcmul((string) $info['sum'], '-1');
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-paid-in-%s', $info['code']),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $info['symbol']]),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $info['symbol']]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => (string) $info['id'],
|
||||
'currency_code' => $info['code'],
|
||||
@@ -617,7 +617,7 @@ class BasicController extends Controller
|
||||
$amount = bcmul((string) $info['sum'], '-1');
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-unpaid-in-%s', $info['code']),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $info['symbol']]),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $info['symbol']]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => (string) $info['id'],
|
||||
'currency_code' => $info['code'],
|
||||
@@ -636,7 +636,7 @@ class BasicController extends Controller
|
||||
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-paid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
@@ -648,7 +648,7 @@ class BasicController extends Controller
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-unpaid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
|
||||
@@ -113,7 +113,7 @@ class UpdateRequest extends FormRequest
|
||||
];
|
||||
$this->booleanFields = ['reconciled'];
|
||||
$this->arrayFields = ['tags'];
|
||||
$data = ['batch_submission' => false];
|
||||
$data = ['batch_submission' => false];
|
||||
if ($this->has('transactions')) {
|
||||
$data['transactions'] = $this->getTransactionData();
|
||||
}
|
||||
|
||||
@@ -63,6 +63,9 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $this->route()->parameter('currency_code');
|
||||
if (is_string($currency)) {
|
||||
$currency = TransactionCurrency::whereCode($currency)->first();
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => sprintf('min:1|max:255|unique:transaction_currencies,name,%d', $currency->id),
|
||||
|
||||
@@ -68,7 +68,7 @@ class CorrectsMetaDataFields extends Command
|
||||
|
||||
private function rename(string $original, string $update): void
|
||||
{
|
||||
$total = DB::table('journal_meta')->where('name', '=', $original)->update(['name' => $update]);
|
||||
$total = DB::table('journal_meta')->where('name', '=', $original)->update(['name' => $update]);
|
||||
$this->count += $total;
|
||||
}
|
||||
}
|
||||
|
||||
90
app/Console/Commands/Correction/RollbacksSingleMigration.php
Normal file
90
app/Console/Commands/Correction/RollbacksSingleMigration.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* RollbackSingleMigration.php
|
||||
* Copyright (c) 2026 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 Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RollbacksSingleMigration extends Command
|
||||
{
|
||||
use ShowsFriendlyMessages;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'correction:rollback-single-migration {--force}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Removes the last entry from the migration table. ';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$entry = DB::table('migrations')->orderBy('id', 'DESC')->first();
|
||||
|
||||
if (null === $entry) {
|
||||
$this->friendlyError('There are no more database migrations to rollback.');
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
$this->friendlyLine(sprintf('This command will remove the database migration entry called "%s" from your database.', $entry->migration));
|
||||
$this->friendlyLine('This does not change the database in anyway. It makes Firefly III forget it made the changes in this particular migration.');
|
||||
$this->friendlyLine('');
|
||||
$this->friendlyLine('If you run "php artisan migrate" after doing this, Firefly III will try to run the database migration again.');
|
||||
$this->friendlyLine('Missing tables or indices will be created.');
|
||||
$this->friendlyLine('This may not work, or give you warnings, but if you have a botched database it may restore it again.');
|
||||
$this->friendlyLine('');
|
||||
$this->friendlyLine('If this doesn\'t work, run the command a few times to remove more rows and try "php artisan migrate" again.');
|
||||
$this->friendlyLine('');
|
||||
$res = true;
|
||||
if (!$this->option('force')) {
|
||||
$this->friendlyWarning('Use this command at your own risk.');
|
||||
$res = $this->confirm('Are you sure you want to continue?');
|
||||
}
|
||||
|
||||
if ($res) {
|
||||
DB::table('migrations')->where('id', (int) $entry->id)->delete();
|
||||
$this->friendlyInfo(sprintf('Database migration #%d ("%s") is deleted.', $entry->id, $entry->migration));
|
||||
$this->friendlyLine('');
|
||||
$this->friendlyLine('Try running "php artisan migrate" now.');
|
||||
$this->friendlyLine('');
|
||||
}
|
||||
if (!$res) {
|
||||
$this->friendlyError('User cancelled, will not delete anything.');
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ValidatesFilePermissions extends Command
|
||||
{
|
||||
@@ -50,26 +51,39 @@ class ValidatesFilePermissions extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
Log::debug(sprintf('Start of %s', $this->signature));
|
||||
$directories = [storage_path('upload')];
|
||||
$errors = false;
|
||||
|
||||
/** @var string $directory */
|
||||
foreach ($directories as $directory) {
|
||||
Log::debug(sprintf('Processing directory: %s', $directory));
|
||||
if (!is_dir($directory)) {
|
||||
$this->friendlyError(sprintf('Directory "%s" cannot found. It is necessary to allow files to be uploaded.', $directory));
|
||||
$errors = true;
|
||||
$message = sprintf('Directory "%s" cannot found. It is necessary to allow files to be uploaded.', $directory);
|
||||
Log::error($message);
|
||||
$this->friendlyError($message);
|
||||
$errors = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
Log::debug('It is a directory!');
|
||||
if (!is_writable($directory)) {
|
||||
$this->friendlyError(sprintf('Directory "%s" is not writeable. Uploading attachments may fail silently.', $directory));
|
||||
$errors = true;
|
||||
$message = sprintf('Directory "%s" is not writeable. Uploading attachments may fail silently.', $directory);
|
||||
$this->friendlyError($message);
|
||||
Log::error($message);
|
||||
$errors = true;
|
||||
}
|
||||
Log::debug('It is writeable!');
|
||||
Log::debug(sprintf('Done processing %s', $directory));
|
||||
}
|
||||
Log::debug('Done with loop.');
|
||||
if (false === $errors) {
|
||||
Log::debug('No errors.');
|
||||
$this->friendlyInfo('All necessary file paths seem to exist, and are writeable.');
|
||||
}
|
||||
|
||||
Log::debug(sprintf('End of %s', $this->signature));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Console\Commands\System;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Console\Commands\Tools\VerifiesDatabaseConnectionTrait;
|
||||
use Illuminate\Console\Command;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
@@ -32,6 +33,7 @@ use PDOException;
|
||||
class CreatesDatabase extends Command
|
||||
{
|
||||
use ShowsFriendlyMessages;
|
||||
use VerifiesDatabaseConnectionTrait;
|
||||
|
||||
protected $description = 'Tries to create the database if it doesn\'t exist yet.';
|
||||
|
||||
@@ -39,21 +41,27 @@ class CreatesDatabase extends Command
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
if ('mysql' !== env('DB_CONNECTION')) { // @phpstan-ignore larastan.noEnvCallsOutsideOfConfig */
|
||||
$this->friendlyInfo(sprintf('CreateDB does not apply to "%s", skipped.', env('DB_CONNECTION')));
|
||||
$connected = $this->verifyDatabaseConnection();
|
||||
if (!$connected) {
|
||||
$this->friendlyError('Failed to connect to the database. Is it up?');
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
if ('mysql' !== config('database.default')) { // @phpstan-ignore larastan.noEnvCallsOutsideOfConfig */
|
||||
$this->friendlyInfo(sprintf('CreateDB does not apply to "%s", skipped.', config('database.default')));
|
||||
|
||||
return 0;
|
||||
}
|
||||
// try to set up a raw connection:
|
||||
$exists = false;
|
||||
$dsn = sprintf('mysql:host=%s;port=%d;charset=utf8mb4', env('DB_HOST'), env('DB_PORT'));
|
||||
$exists = false;
|
||||
$dsn = sprintf('mysql:host=%s;port=%d;charset=utf8mb4', env('DB_HOST'), env('DB_PORT'));
|
||||
|
||||
if ('' !== (string) env('DB_SOCKET')) {
|
||||
$dsn = sprintf('mysql:unix_socket=%s;charset=utf8mb4', env('DB_SOCKET'));
|
||||
}
|
||||
$this->friendlyLine(sprintf('DSN is %s', $dsn));
|
||||
|
||||
$options = [
|
||||
$options = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
@@ -71,7 +79,7 @@ class CreatesDatabase extends Command
|
||||
// only continue when no error.
|
||||
// with PDO, try to list DB's (
|
||||
/** @var array $stmt */
|
||||
$stmt = $pdo->query('SHOW DATABASES;');
|
||||
$stmt = $pdo->query('SHOW DATABASES;');
|
||||
// slightly more complex but less error-prone.
|
||||
foreach ($stmt as $row) {
|
||||
$name = $row['Database'] ?? false;
|
||||
|
||||
64
app/Console/Commands/Tools/VerifiesDatabaseConnection.php
Normal file
64
app/Console/Commands/Tools/VerifiesDatabaseConnection.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* VerifiesDatabaseConnection.php
|
||||
* Copyright (c) 2026 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\Tools;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class VerifiesDatabaseConnection extends Command
|
||||
{
|
||||
use ShowsFriendlyMessages;
|
||||
use VerifiesDatabaseConnectionTrait;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:verify-database-connection';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This command tries to connect to the database.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$connected = $this->verifyDatabaseConnection();
|
||||
if ($connected) {
|
||||
$this->friendlyPositive('Connected to the database.');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
$this->friendlyError('Failed to connect to the database. Is it up?');
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* VerifiesDatabaseConnectionTrait.php
|
||||
* Copyright (c) 2026 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\Tools;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
trait VerifiesDatabaseConnectionTrait
|
||||
{
|
||||
protected function verifyDatabaseConnection(): bool
|
||||
{
|
||||
$loops = 30;
|
||||
$loop = 0;
|
||||
$queries = ['pgsql' => 'SELECT * FROM pg_catalog.pg_tables;', 'sqlite' => 'SELECT name FROM sqlite_schema;', 'mysql' => 'SHOW TABLES;'];
|
||||
$default = config('database.default');
|
||||
if (!array_key_exists($default, $queries)) {
|
||||
$this->friendlyWarning(sprintf('Cannot validate database connection for "%s"', $default));
|
||||
|
||||
return true;
|
||||
}
|
||||
$query = $queries[$default];
|
||||
$connected = false;
|
||||
Log::debug(sprintf('Connecting to database "%s"...', config('database.default')));
|
||||
while (!$connected && $loop < $loops) {
|
||||
try {
|
||||
DB::select($query);
|
||||
$connected = true;
|
||||
} catch (QueryException $e) {
|
||||
Log::error(sprintf('Loop #%d: connection failed: %s', $loop, $e->getMessage()));
|
||||
$this->friendlyWarning(sprintf('Database connection attempt #%d failed. Sleep for 10 seconds...', $loop + 1));
|
||||
sleep(10);
|
||||
} catch (Exception $e) {
|
||||
Log::error(sprintf('Loop #%d: not connected yet because of a %s: %s', $loop, get_class($e), $e->getMessage()));
|
||||
$this->friendlyWarning(sprintf('Database connection attempt #%d failed. Sleep for 10 seconds...', $loop + 1));
|
||||
sleep(10);
|
||||
}
|
||||
++$loop;
|
||||
}
|
||||
|
||||
return $connected;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class UpgradesBillsToRules extends Command
|
||||
'active' => true,
|
||||
'strict' => false,
|
||||
'stop_processing' => false, // field is no longer used.
|
||||
'title' => (string) trans('firefly.rule_for_bill_title', ['name' => $bill->name], $languageString),
|
||||
'title' => (string) trans('firefly.rule_for_bill_title', ['name' => $bill->name], $languageString),
|
||||
'description' => (string) trans('firefly.rule_for_bill_description', ['name' => $bill->name], $languageString),
|
||||
'trigger' => 'store-journal',
|
||||
'triggers' => [['type' => 'description_contains', 'value' => $match]],
|
||||
|
||||
@@ -94,6 +94,7 @@ class UpgradesDatabase extends Command
|
||||
|
||||
private function callInitialCommands(): void
|
||||
{
|
||||
$this->call('firefly-iii:verify-database-connection');
|
||||
$this->call('migrate', ['--seed' => true, '--force' => true, '--no-interaction' => true]);
|
||||
$this->call('upgrade:600-pgsql-sequences');
|
||||
$this->call('upgrade:480-decrypt-all');
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Kernel.php
|
||||
* Copyright (c) 2020 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/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* File to make sure commands work.
|
||||
*/
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*/
|
||||
#[Override]
|
||||
protected function commands(): void
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*/
|
||||
#[Override]
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
$schedule->call(static function (): void {
|
||||
Log::error('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions at https://docs.firefly-iii.org/');
|
||||
echo "\n";
|
||||
echo '------------';
|
||||
echo "\n";
|
||||
echo wordwrap('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions here:');
|
||||
echo "\n";
|
||||
echo 'https://docs.firefly-iii.org/';
|
||||
echo "\n\n";
|
||||
echo 'Disable this cron job!';
|
||||
echo "\n";
|
||||
echo '------------';
|
||||
echo "\n";
|
||||
})->daily();
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ class UpdatedExistingAccount extends Event
|
||||
* Create a new event instance.
|
||||
*/
|
||||
public function __construct(
|
||||
public Account $account
|
||||
public Account $account,
|
||||
public array $oldData
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* api-noauth.php
|
||||
* Copyright (c) 2021 james@firefly-iii.org
|
||||
* UpdatedExistingBill.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,20 +22,21 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace FireflyIII\Events\Model\Bill;
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
// Cron job API routes:
|
||||
use FireflyIII\Http\Middleware\AcceptHeaders;
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\Models\Bill;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
Route::group(
|
||||
[
|
||||
'namespace' => 'FireflyIII\Api\V1\Controllers\System',
|
||||
'prefix' => '',
|
||||
'as' => 'api.v1.cron.',
|
||||
'middleware' => [AcceptHeaders::class],
|
||||
],
|
||||
static function (): void {
|
||||
Route::get('{cliToken}', ['uses' => 'CronController@cron', 'as' => 'index']);
|
||||
}
|
||||
);
|
||||
class UpdatedExistingBill extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*/
|
||||
public function __construct(
|
||||
public Bill $bill,
|
||||
public array $oldData
|
||||
) {}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ class Handler extends ExceptionHandler
|
||||
|
||||
return response()->json([
|
||||
'message' => sprintf('Validation exception: %s', $e->getMessage()),
|
||||
'errors' => ['field' => 'Field is invalid'],
|
||||
'errors' => ['field' => 'Field is invalid'],
|
||||
], $errorCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,13 +36,13 @@ class ConvertsAmountToPrimaryAmount
|
||||
$primaryAmountField = $params->primaryAmountField;
|
||||
|
||||
if (!Amount::convertToPrimary($params->user)) {
|
||||
Log::debug(sprintf(
|
||||
'User does not want to do conversion, no need to convert "%s" and store it in field "%s" for %s #%d.',
|
||||
$params->amountField,
|
||||
$params->primaryAmountField,
|
||||
get_class($params->model),
|
||||
$params->model->id
|
||||
));
|
||||
// Log::debug(sprintf(
|
||||
// 'User does not want to do conversion, no need to convert "%s" and store it in field "%s" for %s #%d.',
|
||||
// $params->amountField,
|
||||
// $params->primaryAmountField,
|
||||
// get_class($params->model),
|
||||
// $params->model->id
|
||||
// ));
|
||||
$params->model->{$primaryAmountField} = null;
|
||||
$params->model->saveQuietly();
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
*/
|
||||
public function getGroups(): Collection
|
||||
{
|
||||
Log::debug('Now in getGroups()');
|
||||
// Log::debug('Now in getGroups()');
|
||||
if ($this->expandGroupSearch) {
|
||||
// get group ID's for the query:
|
||||
$groupIds = $this->getCollectedGroupIds();
|
||||
@@ -556,7 +556,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
if (0 !== count($journalIds)) {
|
||||
// make all integers.
|
||||
$integerIDs = array_map(intval(...), $journalIds);
|
||||
Log::debug(sprintf('GroupCollector: setJournalIds: %s', implode(', ', $integerIDs)));
|
||||
// Log::debug(sprintf('GroupCollector: setJournalIds: %s', implode(', ', $integerIDs)));
|
||||
|
||||
$this->query->whereIn('transaction_journals.id', $integerIDs);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class DeleteController extends Controller
|
||||
}
|
||||
|
||||
$typeName = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));
|
||||
$subTitle = (string) trans(sprintf('firefly.delete_%s_account', $typeName), ['name' => $account->name]);
|
||||
$subTitle = (string) trans(sprintf('firefly.delete_%s_account', $typeName), ['name' => $account->name]);
|
||||
$accountList = app('expandedform')->makeSelectListWithEmpty($this->repository->getAccountsByType([$account->accountType->type]));
|
||||
$objectType = $typeName;
|
||||
unset($accountList[$account->id]);
|
||||
|
||||
@@ -86,7 +86,7 @@ class EditController extends Controller
|
||||
}
|
||||
|
||||
$objectType = config('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||
$subTitle = (string) trans(sprintf('firefly.edit_%s_account', $objectType), ['name' => $account->name]);
|
||||
$subTitle = (string) trans(sprintf('firefly.edit_%s_account', $objectType), ['name' => $account->name]);
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType));
|
||||
$roles = $this->getRoles();
|
||||
$liabilityTypes = $this->getLiabilityTypes();
|
||||
|
||||
@@ -137,7 +137,7 @@ class ReconcileController extends Controller
|
||||
);
|
||||
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
|
||||
$subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]);
|
||||
$subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]);
|
||||
|
||||
// various links
|
||||
$transactionsUrl = route('accounts.reconcile.transactions', [$account->id, '%start%', '%end%']);
|
||||
|
||||
@@ -219,7 +219,7 @@ class ShowController extends Controller
|
||||
$page = (int) $request->get('page');
|
||||
$pageSize = (int) Preferences::get('listPageSize', 50)->data;
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? $this->primaryCurrency;
|
||||
$subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]);
|
||||
$subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]);
|
||||
$periods = new Collection();
|
||||
|
||||
$end->endOfDay();
|
||||
|
||||
@@ -115,6 +115,7 @@ class ConfigurationController extends Controller
|
||||
FireflyConfig::set('enable_external_map', $data['enable_external_map']);
|
||||
FireflyConfig::set('enable_external_rates', $data['enable_external_rates']);
|
||||
FireflyConfig::set('allow_webhooks', $data['allow_webhooks']);
|
||||
FireflyConfig::set('enable_batch_processing', $data['enable_batch_processing']);
|
||||
|
||||
FireflyConfig::set('valid_url_protocols', $data['valid_url_protocols']);
|
||||
FireflyConfig::set('is_demo_site', $data['is_demo_site']);
|
||||
|
||||
@@ -94,7 +94,7 @@ class LinkController extends Controller
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User wants to delete link type #%d', $linkType->id));
|
||||
$subTitle = (string) trans('firefly.delete_link_type', ['name' => $linkType->name]);
|
||||
$subTitle = (string) trans('firefly.delete_link_type', ['name' => $linkType->name]);
|
||||
$otherTypes = $this->repository->get();
|
||||
$count = $this->repository->countJournals($linkType);
|
||||
$moveTo = [];
|
||||
@@ -141,7 +141,7 @@ class LinkController extends Controller
|
||||
|
||||
return redirect(route('settings.links.index'));
|
||||
}
|
||||
$subTitle = (string) trans('firefly.edit_link_type', ['name' => $linkType->name]);
|
||||
$subTitle = (string) trans('firefly.edit_link_type', ['name' => $linkType->name]);
|
||||
$subTitleIcon = 'fa-link';
|
||||
|
||||
Log::channel('audit')->info(sprintf('User wants to edit link type #%d', $linkType->id));
|
||||
@@ -181,7 +181,7 @@ class LinkController extends Controller
|
||||
*/
|
||||
public function show(LinkType $linkType): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.overview_for_link', ['name' => $linkType->name]);
|
||||
$subTitle = (string) trans('firefly.overview_for_link', ['name' => $linkType->name]);
|
||||
$subTitleIcon = 'fa-link';
|
||||
$links = $this->repository->getJournalLinks($linkType);
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class UserController extends Controller
|
||||
}
|
||||
session()->forget('users.edit.fromUpdate');
|
||||
|
||||
$subTitle = (string) trans('firefly.edit_user', ['email' => $user->email]);
|
||||
$subTitle = (string) trans('firefly.edit_user', ['email' => $user->email]);
|
||||
$subTitleIcon = 'fa-user-o';
|
||||
$currentUser = auth()->user();
|
||||
$isAdmin = $this->repository->hasRole($user, 'owner');
|
||||
@@ -216,7 +216,7 @@ class UserController extends Controller
|
||||
{
|
||||
$title = (string) trans('firefly.system_settings');
|
||||
$mainTitleIcon = 'fa-hand-spock-o';
|
||||
$subTitle = (string) trans('firefly.single_user_administration', ['email' => $user->email]);
|
||||
$subTitle = (string) trans('firefly.single_user_administration', ['email' => $user->email]);
|
||||
$subTitleIcon = 'fa-user';
|
||||
$information = $this->repository->getUserData($user);
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ class AttachmentController extends Controller
|
||||
public function edit(Request $request, Attachment $attachment): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
$subTitle = (string) trans('firefly.edit_attachment', ['name' => $attachment->filename]);
|
||||
$subTitle = (string) trans('firefly.edit_attachment', ['name' => $attachment->filename]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('attachments.edit.fromUpdate')) {
|
||||
|
||||
@@ -190,6 +190,14 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function showLoginForm(Request $request): Factory|Redirector|RedirectResponse|View
|
||||
{
|
||||
if ('remote_user_guard' === config('auth.defaults.guard')) {
|
||||
$message = sprintf(
|
||||
'Firefly III is configured to use the "remote user guard", but was unable to link you to a user. Are you sure the "%s" header is in place?',
|
||||
config('auth.guard_header')
|
||||
);
|
||||
|
||||
return view('errors.error', ['message' => $message]);
|
||||
}
|
||||
Log::channel('audit')->info('Show login form (1.1).');
|
||||
|
||||
$count = DB::table('users')->count();
|
||||
@@ -251,7 +259,7 @@ class LoginController extends Controller
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request): void
|
||||
{
|
||||
$exception = ValidationException::withMessages([$this->username() => [trans('auth.failed')]]);
|
||||
$exception = ValidationException::withMessages([$this->username() => [trans('auth.failed')]]);
|
||||
$exception->redirectTo = route('login');
|
||||
|
||||
throw $exception;
|
||||
|
||||
@@ -74,15 +74,15 @@ class IndexController extends Controller
|
||||
$this->cleanupObjectGroups();
|
||||
$this->repository->correctOrder();
|
||||
$this->repository->correctTransfers();
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
$start = session('start')->clone();
|
||||
$end = session('end')->clone();
|
||||
$viewRange = Preferences::get('viewRange', '1M')->data;
|
||||
|
||||
// give the end some extra space when the user has last7, last30 or last90.
|
||||
if ('last7' === $viewRange || 'last30' === $viewRange) {
|
||||
$end->addDays(30);
|
||||
}
|
||||
if ('last90') {
|
||||
if ('last90' === $viewRange) {
|
||||
$end->addDays(90);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ class EditController extends Controller
|
||||
*/
|
||||
public function edit(Request $request, Budget $budget): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.edit_budget', ['name' => $budget->name]);
|
||||
$subTitle = (string) trans('firefly.edit_budget', ['name' => $budget->name]);
|
||||
$autoBudget = $this->repository->getAutoBudget($budget);
|
||||
|
||||
// auto budget types
|
||||
|
||||
@@ -73,7 +73,7 @@ class BillController extends Controller
|
||||
*/
|
||||
foreach ($paid as $info) {
|
||||
$amount = $info['sum'];
|
||||
$label = (string) trans('firefly.paid_in_currency', ['currency' => $info['name']]);
|
||||
$label = (string) trans('firefly.paid_in_currency', ['currency' => $info['name']]);
|
||||
$chartData[$label] = ['amount' => $amount, 'currency_symbol' => $info['symbol'], 'currency_code' => $info['code']];
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ class BillController extends Controller
|
||||
*/
|
||||
foreach ($unpaid as $info) {
|
||||
$amount = $info['sum'];
|
||||
$label = (string) trans('firefly.unpaid_in_currency', ['currency' => $info['name']]);
|
||||
$label = (string) trans('firefly.unpaid_in_currency', ['currency' => $info['name']]);
|
||||
$chartData[$label] = ['amount' => $amount, 'currency_symbol' => $info['symbol'], 'currency_code' => $info['code']];
|
||||
}
|
||||
|
||||
|
||||
@@ -505,14 +505,14 @@ class BudgetController extends Controller
|
||||
$preferredRange = Navigation::preferredRangeFormat($start, $end);
|
||||
$chartData = [
|
||||
[
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency->name]),
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency->name]),
|
||||
'type' => 'bar',
|
||||
'entries' => [],
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_code' => $currency->code,
|
||||
],
|
||||
[
|
||||
'label' => (string) trans('firefly.box_budgeted_in_currency', ['currency' => $currency->name]),
|
||||
'label' => (string) trans('firefly.box_budgeted_in_currency', ['currency' => $currency->name]),
|
||||
'type' => 'bar',
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_code' => $currency->code,
|
||||
|
||||
@@ -171,7 +171,7 @@ class BudgetReportController extends Controller
|
||||
$chartData[$spentKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.spent_in_specific_budget', ['budget' => $budget->name]),
|
||||
(string) trans('firefly.spent_in_specific_budget', ['budget' => $budget->name]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'type' => 'bar',
|
||||
|
||||
@@ -216,7 +216,7 @@ class CategoryReportController extends Controller
|
||||
$chartData[$spentKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.spent_in_specific_category', ['category' => $category->name]),
|
||||
(string) trans('firefly.spent_in_specific_category', ['category' => $category->name]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'type' => 'bar',
|
||||
@@ -243,7 +243,7 @@ class CategoryReportController extends Controller
|
||||
$chartData[$spentKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.earned_in_specific_category', ['category' => $category->name]),
|
||||
(string) trans('firefly.earned_in_specific_category', ['category' => $category->name]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'type' => 'bar',
|
||||
|
||||
@@ -162,11 +162,7 @@ class DoubleReportController extends Controller
|
||||
$name = $this->getCounterpartName($accounts, $account->id, $account->name, $account->iban);
|
||||
|
||||
$chartData[$spentKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.spent_in_specific_double', ['account' => $name]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'label' => sprintf('%s (%s)', (string) trans('firefly.spent_in_specific_double', ['account' => $name]), $currency['currency_name']),
|
||||
'type' => 'bar',
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_code' => $currency['currency_code'],
|
||||
@@ -188,11 +184,7 @@ class DoubleReportController extends Controller
|
||||
$name = $this->getCounterpartName($accounts, $account->id, $account->name, $account->iban);
|
||||
|
||||
$chartData[$earnedKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.earned_in_specific_double', ['account' => $name]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'label' => sprintf('%s (%s)', (string) trans('firefly.earned_in_specific_double', ['account' => $name]), $currency['currency_name']),
|
||||
'type' => 'bar',
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_code' => $currency['currency_code'],
|
||||
|
||||
@@ -212,7 +212,7 @@ class ReportController extends Controller
|
||||
foreach ($data as $currency) {
|
||||
Log::debug(sprintf('Now processing currency "%s"', $currency['currency_name']));
|
||||
$income = [
|
||||
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'type' => 'bar',
|
||||
'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
|
||||
'currency_id' => $currency['currency_id'],
|
||||
@@ -221,7 +221,7 @@ class ReportController extends Controller
|
||||
'entries' => [],
|
||||
];
|
||||
$expense = [
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'type' => 'bar',
|
||||
'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red
|
||||
'currency_id' => $currency['currency_id'],
|
||||
|
||||
@@ -220,11 +220,7 @@ class TagReportController extends Controller
|
||||
// add things to chart Data for each currency:
|
||||
$spentKey = sprintf('%d-spent', $currency['currency_id']);
|
||||
$chartData[$spentKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.spent_in_specific_tag', ['tag' => $tag->tag]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'label' => sprintf('%s (%s)', (string) trans('firefly.spent_in_specific_tag', ['tag' => $tag->tag]), $currency['currency_name']),
|
||||
'type' => 'bar',
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_code' => $currency['currency_code'],
|
||||
@@ -247,11 +243,7 @@ class TagReportController extends Controller
|
||||
// add things to chart Data for each currency:
|
||||
$spentKey = sprintf('%d-earned', $currency['currency_id']);
|
||||
$chartData[$spentKey] ??= [
|
||||
'label' => sprintf(
|
||||
'%s (%s)',
|
||||
(string) trans('firefly.earned_in_specific_tag', ['tag' => $tag->tag]),
|
||||
$currency['currency_name']
|
||||
),
|
||||
'label' => sprintf('%s (%s)', (string) trans('firefly.earned_in_specific_tag', ['tag' => $tag->tag]), $currency['currency_name']),
|
||||
'type' => 'bar',
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_code' => $currency['currency_code'],
|
||||
|
||||
@@ -80,6 +80,14 @@ abstract class Controller extends BaseController
|
||||
View::share('FF_VERSION', config('firefly.version'));
|
||||
View::share('FF_BUILD_TIME', config('firefly.build_time'));
|
||||
|
||||
// this breaks when running < php 8.5 and is totally intentional.
|
||||
// $input = ' James is cool';
|
||||
// $output = $input
|
||||
// |> trim(...)
|
||||
// |> (fn (string $string) => str_replace(' ', '-', $string))
|
||||
// |> (fn (string $string) => str_replace(['.', '/', '…'], '', $string))
|
||||
// |> strtolower(...);
|
||||
|
||||
// is webhooks enabled?
|
||||
View::share(
|
||||
'featuringWebhooks',
|
||||
|
||||
@@ -183,11 +183,11 @@ class RecurrenceController extends Controller
|
||||
$result = [
|
||||
'daily' => ['label' => (string) trans('firefly.recurring_daily'), 'selected' => str_starts_with($preSelected, 'daily')],
|
||||
$weekly => [
|
||||
'label' => (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]),
|
||||
'label' => (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]),
|
||||
'selected' => str_starts_with($preSelected, 'weekly'),
|
||||
],
|
||||
$monthly => [
|
||||
'label' => (string) trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]),
|
||||
'label' => (string) trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]),
|
||||
'selected' => str_starts_with($preSelected, 'monthly'),
|
||||
],
|
||||
$ndom => [
|
||||
@@ -195,7 +195,7 @@ class RecurrenceController extends Controller
|
||||
'selected' => str_starts_with($preSelected, 'ndom'),
|
||||
],
|
||||
$yearly => [
|
||||
'label' => (string) trans('firefly.recurring_yearly', ['date' => $yearlyDate]),
|
||||
'label' => (string) trans('firefly.recurring_yearly', ['date' => $yearlyDate]),
|
||||
'selected' => str_starts_with($preSelected, 'yearly'),
|
||||
],
|
||||
];
|
||||
|
||||
@@ -61,7 +61,7 @@ class DeleteController extends Controller
|
||||
*/
|
||||
public function delete(ObjectGroup $objectGroup): Factory|View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.delete_object_group', ['title' => $objectGroup->title]);
|
||||
$subTitle = (string) trans('firefly.delete_object_group', ['title' => $objectGroup->title]);
|
||||
$piggyBanks = $objectGroup->piggyBanks()->count();
|
||||
|
||||
// put previous url in session
|
||||
|
||||
@@ -64,7 +64,7 @@ class EditController extends Controller
|
||||
*/
|
||||
public function edit(ObjectGroup $objectGroup): Factory|View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.edit_object_group', ['title' => $objectGroup->title]);
|
||||
$subTitle = (string) trans('firefly.edit_object_group', ['title' => $objectGroup->title]);
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
|
||||
if (true !== session('object-groups.edit.fromUpdate')) {
|
||||
|
||||
@@ -70,7 +70,7 @@ class EditController extends Controller
|
||||
*/
|
||||
public function edit(PiggyBank $piggyBank): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
|
||||
$subTitle = (string) trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
$note = $piggyBank->notes()->first();
|
||||
// Flash some data to fill the form.
|
||||
|
||||
@@ -80,7 +80,7 @@ class CreateController extends Controller
|
||||
public function create(Request $request, ?RuleGroup $ruleGroup = null): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$this->createDefaultRuleGroup();
|
||||
$preFilled = ['strict' => true];
|
||||
$preFilled = ['strict' => true];
|
||||
$oldTriggers = [];
|
||||
$oldActions = [];
|
||||
|
||||
@@ -159,7 +159,7 @@ class CreateController extends Controller
|
||||
$this->createDefaultRuleGroup();
|
||||
$preFilled = [
|
||||
'strict' => true,
|
||||
'title' => (string) trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]),
|
||||
'title' => (string) trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]),
|
||||
'description' => (string) trans('firefly.new_rule_for_bill_description', ['name' => $bill->name]),
|
||||
];
|
||||
|
||||
@@ -221,7 +221,7 @@ class CreateController extends Controller
|
||||
// collect pre-filled information:
|
||||
$preFilled = [
|
||||
'strict' => true,
|
||||
'title' => (string) trans('firefly.new_rule_for_journal_title', ['description' => $journal->description]),
|
||||
'title' => (string) trans('firefly.new_rule_for_journal_title', ['description' => $journal->description]),
|
||||
'description' => (string) trans('firefly.new_rule_for_journal_description', ['description' => $journal->description]),
|
||||
];
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class EditController extends Controller
|
||||
$subTitle = (string) trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]);
|
||||
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
$preFilled = ['active' => $hasOldInput ? (bool) $request->old('active') : $ruleGroup->active];
|
||||
$preFilled = ['active' => $hasOldInput ? (bool) $request->old('active') : $ruleGroup->active];
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('rule-groups.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUrl('rule-groups.edit.url');
|
||||
|
||||
@@ -87,7 +87,7 @@ class SearchController extends Controller
|
||||
$excludedWords = $searcher->getExcludedWords();
|
||||
$operators = $searcher->getOperators();
|
||||
$invalidOperators = $searcher->getInvalidOperators();
|
||||
$subTitle = (string) trans('breadcrumbs.search_result', ['query' => $fullQuery]);
|
||||
$subTitle = (string) trans('breadcrumbs.search_result', ['query' => $fullQuery]);
|
||||
|
||||
return view('search.index', [
|
||||
'words' => $words,
|
||||
|
||||
@@ -61,7 +61,7 @@ class InstallController extends Controller
|
||||
'migrate' => ['--seed' => true, '--force' => true],
|
||||
'generate-keys' => [], // an exception :(
|
||||
'firefly-iii:upgrade-database' => [],
|
||||
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
|
||||
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
|
||||
'firefly-iii:verify-security-alerts' => [],
|
||||
];
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ class TagController extends Controller
|
||||
*/
|
||||
public function edit(Tag $tag): Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.edit_tag', ['tag' => $tag->tag]);
|
||||
$subTitle = (string) trans('firefly.edit_tag', ['tag' => $tag->tag]);
|
||||
$subTitleIcon = 'fa-tag';
|
||||
|
||||
$location = $this->repository->getLocation($tag);
|
||||
@@ -289,7 +289,7 @@ class TagController extends Controller
|
||||
$page = (int) $request->get('page');
|
||||
$pageSize = (int) Preferences::get('listPageSize', 50)->data;
|
||||
$periods = [];
|
||||
$subTitle = (string) trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]);
|
||||
$subTitle = (string) trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]);
|
||||
$start = $this->repository->firstUseDate($tag) ?? today(config('app.timezone'));
|
||||
$end = $this->repository->lastUseDate($tag) ?? today(config('app.timezone'));
|
||||
$attachments = $this->repository->getAttachments($tag);
|
||||
|
||||
@@ -103,7 +103,7 @@ class ConvertController extends Controller
|
||||
|
||||
$groupTitle = $group->title ?? $first->description;
|
||||
$groupArray = $transformer->transformObject($group);
|
||||
$subTitle = (string) trans('firefly.convert_to_'.$destinationType->type, ['description' => $groupTitle]);
|
||||
$subTitle = (string) trans('firefly.convert_to_'.$destinationType->type, ['description' => $groupTitle]);
|
||||
$subTitleIcon = 'fa-exchange';
|
||||
|
||||
// get a list of asset accounts and liabilities and stuff, in various combinations:
|
||||
|
||||
@@ -77,7 +77,7 @@ class DeleteController extends Controller
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$objectType = strtolower($journal->transaction_type_type ?? $journal->transactionType->type);
|
||||
$subTitle = (string) trans('firefly.delete_'.$objectType, ['description' => $group->title ?? $journal->description]);
|
||||
$subTitle = (string) trans('firefly.delete_'.$objectType, ['description' => $group->title ?? $journal->description]);
|
||||
$previous = Steam::getSafePreviousUrl();
|
||||
// put previous url in session
|
||||
Log::debug('Will try to remember previous URL');
|
||||
|
||||
@@ -91,7 +91,7 @@ class EditController extends Controller
|
||||
$title = $transactionGroup->transactionJournals()->count() > 1
|
||||
? $transactionGroup->title
|
||||
: $transactionGroup->transactionJournals()->first()->description;
|
||||
$subTitle = (string) trans('firefly.edit_transaction_title', ['description' => $title]);
|
||||
$subTitle = (string) trans('firefly.edit_transaction_title', ['description' => $title]);
|
||||
$subTitleIcon = 'fa-plus';
|
||||
$cash = $repository->getCashAccount();
|
||||
$previousUrl = $this->rememberPreviousUrl('transactions.edit.url');
|
||||
|
||||
@@ -103,10 +103,11 @@ class IndexController extends Controller
|
||||
$firstJournal = $this->repository->firstNull();
|
||||
$startPeriod = $firstJournal instanceof TransactionJournal ? $firstJournal->date : new Carbon();
|
||||
$endPeriod = clone $end;
|
||||
|
||||
// limit to 3 years for the time being.
|
||||
if (now()->diffInYears($startPeriod, true) > 3) {
|
||||
$startPeriod = now()->subYears(3);
|
||||
$endPeriod->endOfDay();
|
||||
// limit to 6 years for the time being.
|
||||
$max = 6;
|
||||
if (now()->diffInYears($startPeriod, true) > $max) {
|
||||
$startPeriod = now()->subYears($max);
|
||||
}
|
||||
|
||||
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
|
||||
|
||||
@@ -78,7 +78,7 @@ class EditController extends Controller
|
||||
}
|
||||
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
$subTitle = (string) trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
|
||||
$subTitle = (string) trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
|
||||
$currency->symbol = htmlentities($currency->symbol);
|
||||
|
||||
// is currently enabled (for this user?)
|
||||
@@ -91,7 +91,7 @@ class EditController extends Controller
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
$preFilled = ['enabled' => $hasOldInput ? (bool) $request->old('enabled') : $enabled];
|
||||
$preFilled = ['enabled' => $hasOldInput ? (bool) $request->old('enabled') : $enabled];
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
Log::channel('audit')->info('Edit currency.', $currency->toArray());
|
||||
|
||||
@@ -39,7 +39,7 @@ class EditController extends Controller
|
||||
public function edit(UserGroup $userGroup)
|
||||
{
|
||||
$title = (string) trans('firefly.administrations_page_title');
|
||||
$subTitle = (string) trans('firefly.administrations_page_edit_sub_title', ['title' => $userGroup->title]);
|
||||
$subTitle = (string) trans('firefly.administrations_page_edit_sub_title', ['title' => $userGroup->title]);
|
||||
$mainTitleIcon = 'fa-book';
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Kernel.php
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http;
|
||||
|
||||
use FireflyIII\Http\Middleware\Authenticate;
|
||||
use FireflyIII\Http\Middleware\Binder;
|
||||
use FireflyIII\Http\Middleware\InstallationId;
|
||||
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\TrimStrings;
|
||||
use FireflyIII\Http\Middleware\TrustProxies;
|
||||
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
|
||||
use Illuminate\Auth\Middleware\Authorize;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode;
|
||||
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
|
||||
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
|
||||
/**
|
||||
* Class Kernel
|
||||
*/
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
protected $middleware = [
|
||||
// SecureHeaders::class,
|
||||
CheckForMaintenanceMode::class,
|
||||
ValidatePostSize::class,
|
||||
TrimStrings::class,
|
||||
ConvertEmptyStringsToNull::class,
|
||||
TrustProxies::class,
|
||||
InstallationId::class,
|
||||
];
|
||||
protected $middlewareAliases = [
|
||||
'auth' => Authenticate::class,
|
||||
'auth.basic' => AuthenticateWithBasicAuth::class,
|
||||
'bindings' => Binder::class,
|
||||
'can' => Authorize::class,
|
||||
'guest' => RedirectIfAuthenticated::class,
|
||||
'throttle' => ThrottleRequests::class,
|
||||
];
|
||||
protected $middlewarePriority = [StartFireflySession::class, ShareErrorsFromSession::class, Authenticate::class, Binder::class, Authorize::class];
|
||||
}
|
||||
@@ -82,22 +82,25 @@ class Authenticate
|
||||
protected function authenticate($request, array $guards)
|
||||
{
|
||||
if (0 === count($guards)) {
|
||||
// go for default guard:
|
||||
// @noinspection PhpUndefinedMethodInspection
|
||||
if ($this->auth->check()) {
|
||||
// do an extra check on user object.
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->auth->authenticate();
|
||||
Log::debug('in Authenticate::authenticate() with zero guards.');
|
||||
// There are no guards defined, go for the default guard:
|
||||
if (auth()->check()) {
|
||||
Log::debug('User is authenticated.');
|
||||
$user = auth()->user();
|
||||
$this->validateBlockedUser($user, $guards);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// @noinspection PhpUndefinedMethodInspection
|
||||
return $this->auth->authenticate();
|
||||
$this->auth->authenticate();
|
||||
if (!$this->auth->check()) {
|
||||
throw new AuthenticationException('The user is not logged in but must be.', $guards);
|
||||
}
|
||||
}
|
||||
|
||||
exit('five');
|
||||
foreach ($guards as $guard) {
|
||||
exit('six');
|
||||
if ('api' !== $guard) {
|
||||
$this->auth->guard($guard)->authenticate();
|
||||
}
|
||||
@@ -111,6 +114,7 @@ class Authenticate
|
||||
}
|
||||
}
|
||||
|
||||
exit('seven');
|
||||
// this is a massive hack, but if the handler has the oauth exception
|
||||
// at this point we can report its error instead of a generic one.
|
||||
$message = 'Unauthenticated.';
|
||||
@@ -143,5 +147,6 @@ class Authenticate
|
||||
// @phpstan-ignore-line (thinks function is undefined)
|
||||
throw new AuthenticationException('Blocked account.', $guards);
|
||||
}
|
||||
Log::debug(sprintf('User #%d is not blocked.', $user->id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ use Override;
|
||||
/**
|
||||
* Class StartFireflySession.
|
||||
*/
|
||||
class StartFireflySession extends StartSession
|
||||
class StartFireflyIIISession extends StartSession
|
||||
{
|
||||
/**
|
||||
* Store the current URL for the request if necessary.
|
||||
@@ -167,7 +167,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
|
||||
|
||||
/** @var BudgetLimitRepositoryInterface $repository */
|
||||
$repository = app(BudgetLimitRepositoryInterface::class);
|
||||
$repository->setUserGroup($autoBudget->budget->user->userGroup);
|
||||
$repository->setUser($autoBudget->budget->user);
|
||||
|
||||
$budgetLimit = $repository->store([
|
||||
'currency_id' => $autoBudget->transaction_currency_id,
|
||||
|
||||
@@ -29,7 +29,11 @@ use FireflyIII\Events\Model\Account\UpdatedExistingAccount;
|
||||
use FireflyIII\Handlers\ExchangeRate\ConversionParameters;
|
||||
use FireflyIII\Handlers\ExchangeRate\ConvertsAmountToPrimaryAmount;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -40,6 +44,89 @@ class UpdatesAccountInformation implements ShouldQueue
|
||||
{
|
||||
$this->recalculateCredit($event->account);
|
||||
$this->updateVirtualBalance($event->account);
|
||||
if ($event instanceof UpdatedExistingAccount) {
|
||||
$this->renameRules($event->account, $event->oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private function correctRuleActions(Account $account, array $oldData, Rule $rule): void
|
||||
{
|
||||
$fields = ['set_source_account', 'set_destination_account'];
|
||||
|
||||
Log::debug(sprintf('Check if rule #%d actions reference account #%d "%s"', $rule->id, $account->id, $account->name));
|
||||
$fixed = 0;
|
||||
|
||||
/** @var RuleAction $action */
|
||||
foreach ($rule->ruleActions as $action) {
|
||||
// fix name:
|
||||
if ($oldData['name'] === $action->action_value && in_array($action->action_type, $fields, true)) {
|
||||
Log::debug(sprintf('Rule action #%d "%s" has old account name, replace with new.', $action->id, $action->action_type));
|
||||
$action->action_value = $account->name;
|
||||
$action->save();
|
||||
++$fixed;
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Corrected %d action(s) for rule #%d', $fixed, $rule->id));
|
||||
}
|
||||
|
||||
private function correctRuleTriggers(Account $account, array $oldData, Rule $rule): void
|
||||
{
|
||||
$nameFields = [
|
||||
'source_account_is',
|
||||
'source_account_contains',
|
||||
'source_account_ends',
|
||||
'source_account_starts',
|
||||
'destination_account_is',
|
||||
'destination_account_contains',
|
||||
'destination_account_ends',
|
||||
'destination_account_starts',
|
||||
'account_is',
|
||||
'account_contains',
|
||||
'account_ends',
|
||||
'account_starts',
|
||||
];
|
||||
$numberFields = [
|
||||
'source_account_nr_is',
|
||||
'source_account_nr_contains',
|
||||
'source_account_nr_ends',
|
||||
'source_account_nr_starts',
|
||||
'destination_account_nr_is',
|
||||
'destination_account_nr_contains',
|
||||
'destination_account_nr_starts',
|
||||
'account_nr_is',
|
||||
'account_nr_contains',
|
||||
'account_nr_ends',
|
||||
'account_nr_starts',
|
||||
];
|
||||
|
||||
Log::debug(sprintf('Check if rule #%d triggers reference account #%d "%s"', $rule->id, $account->id, $account->name));
|
||||
$fixed = 0;
|
||||
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
// fix name:
|
||||
if ($oldData['name'] === $trigger->trigger_value && in_array($trigger->trigger_type, $nameFields, true)) {
|
||||
Log::debug(sprintf('Rule trigger #%d "%s" has old account name, replace with new.', $trigger->id, $trigger->trigger_type));
|
||||
$trigger->trigger_value = $account->name;
|
||||
$trigger->save();
|
||||
++$fixed;
|
||||
}
|
||||
// fix IBAN:
|
||||
if ($oldData['iban'] === $trigger->trigger_value && in_array($trigger->trigger_type, $numberFields, true)) {
|
||||
Log::debug(sprintf('Rule trigger #%d "%s" has old account IBAN, replace with new.', $trigger->id, $trigger->trigger_type));
|
||||
$trigger->trigger_value = $account->iban;
|
||||
$trigger->save();
|
||||
++$fixed;
|
||||
}
|
||||
// fix account number: // account_number
|
||||
if ($oldData['account_number'] === $trigger->trigger_value && in_array($trigger->trigger_type, $numberFields, true)) {
|
||||
Log::debug(sprintf('Rule trigger #%d "%s" has old account account_number, replace with new.', $trigger->id, $trigger->trigger_type));
|
||||
$trigger->trigger_value = $account->iban;
|
||||
$trigger->save();
|
||||
++$fixed;
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Corrected %d trigger(s) for rule #%d', $fixed, $rule->id));
|
||||
}
|
||||
|
||||
private function recalculateCredit(Account $account): void
|
||||
@@ -52,6 +139,20 @@ class UpdatesAccountInformation implements ShouldQueue
|
||||
$object->recalculate();
|
||||
}
|
||||
|
||||
private function renameRules(Account $account, array $oldData): void
|
||||
{
|
||||
Log::debug('Updated account, will now correct rules.');
|
||||
$repository = app(RuleRepositoryInterface::class);
|
||||
$repository->setUser($account->user);
|
||||
$rules = $repository->getAll();
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$this->correctRuleTriggers($account, $oldData, $rule);
|
||||
$this->correctRuleActions($account, $oldData, $rule);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateVirtualBalance(Account $account): void
|
||||
{
|
||||
Log::debug('Will updateVirtualBalance');
|
||||
|
||||
81
app/Listeners/Model/Bill/UpdatesRulesForChangedBill.php
Normal file
81
app/Listeners/Model/Bill/UpdatesRulesForChangedBill.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* UpdatesRulesForChangedBill.php
|
||||
* Copyright (c) 2026 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\Listeners\Model\Bill;
|
||||
|
||||
use FireflyIII\Events\Model\Bill\UpdatedExistingBill;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdatesRulesForChangedBill implements ShouldQueue
|
||||
{
|
||||
public function handle(UpdatedExistingBill $event): void
|
||||
{
|
||||
// update rule actions.
|
||||
if ($event->bill->name !== $event->oldData['name']) {
|
||||
$this->updateBillTriggersAndActions($event->bill, $event->oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateBillTriggersAndActions(Bill $bill, array $oldData): void
|
||||
{
|
||||
Log::debug(sprintf('Now in updateBillTriggersAndActions(#%d)', $bill->id));
|
||||
$repository = app(RuleRepositoryInterface::class);
|
||||
$repository->setUser($bill->user);
|
||||
$rules = $repository->getAll();
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$this->updateRule($bill, $rule, $oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateRule(Bill $bill, Rule $rule, array $oldData): void
|
||||
{
|
||||
$triggers = ['bill_is', 'bill_ends', 'bill_starts', 'bill_contains'];
|
||||
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if (in_array($trigger->trigger_type, $triggers, true) && $trigger->trigger_value === $oldData['name']) {
|
||||
Log::debug(sprintf('Updated trigger #%d in rule #%d to new subscription name', $trigger->id, $rule->id));
|
||||
$trigger->trigger_value = $bill->name;
|
||||
$trigger->save();
|
||||
}
|
||||
}
|
||||
|
||||
/** @var RuleAction $action */
|
||||
foreach ($rule->ruleActions as $action) {
|
||||
if ('link_to_bill' === $action->action_type && $action->action_value === $oldData['name']) {
|
||||
Log::debug(sprintf('Updated action #%d in rule #%d to new subscription name', $action->id, $rule->id));
|
||||
$action->action_value = $bill->name;
|
||||
$action->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ trait SupportsGroupProcessingTrait
|
||||
$first = $set->first();
|
||||
$journalIds = implode(',', $array);
|
||||
$user = $first->user;
|
||||
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||
// Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||
|
||||
// collect rules:
|
||||
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||
@@ -104,7 +104,9 @@ trait SupportsGroupProcessingTrait
|
||||
$repository->deleteStatisticsForType(Category::class, $objects->categories, $dates);
|
||||
$repository->deleteStatisticsForType(Tag::class, $objects->tags, $dates);
|
||||
|
||||
// remove if no stuff present:
|
||||
// remove generic statistics:
|
||||
$repository->deleteStatisticsForPrefix('all_', $dates);
|
||||
|
||||
// remove for no tag, no cat, etc.
|
||||
if (0 === $objects->budgets->count()) {
|
||||
Log::debug('No budgets, delete "no_category" stats.');
|
||||
|
||||
@@ -149,12 +149,10 @@ class RecalculatesPrimaryCurrencyAmounts
|
||||
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.user_group_id', $userGroup->id)
|
||||
->where(static function (Builder $q): void {
|
||||
$q
|
||||
->whereNotNull('native_amount')
|
||||
->orWhereNotNull('native_foreign_amount')
|
||||
->orWhere('native_amount', '!=', '')
|
||||
->orWhere('native_foreign_amount', '!=', '')
|
||||
;
|
||||
$q->whereNotNull('native_amount')->orWhereNotNull('native_foreign_amount');
|
||||
if ('pgsql' !== config('database.default')) {
|
||||
$q->orWhere('native_amount', '!=', '')->orWhere('native_foreign_amount', '!=', '');
|
||||
}
|
||||
})
|
||||
->update(['native_amount' => null, 'native_foreign_amount' => null])
|
||||
;
|
||||
|
||||
@@ -56,7 +56,7 @@ class MFABackupFewLeftNotification extends Notification
|
||||
*/
|
||||
public function toMail(User $notifiable): MailMessage
|
||||
{
|
||||
$subject = (string) trans('email.mfa_few_backups_left_subject', ['count' => $this->count]);
|
||||
$subject = (string) trans('email.mfa_few_backups_left_subject', ['count' => $this->count]);
|
||||
$ip = Request::ip();
|
||||
$host = Steam::getHostName($ip);
|
||||
$userAgent = Request::userAgent();
|
||||
|
||||
@@ -53,7 +53,7 @@ class MFAManyFailedAttemptsNotification extends Notification
|
||||
*/
|
||||
public function toMail(User $notifiable): MailMessage
|
||||
{
|
||||
$subject = (string) trans('email.mfa_many_failed_subject', ['count' => $this->count]);
|
||||
$subject = (string) trans('email.mfa_many_failed_subject', ['count' => $this->count]);
|
||||
$ip = Request::ip();
|
||||
$host = Steam::getHostName($ip);
|
||||
$userAgent = Request::userAgent();
|
||||
|
||||
@@ -58,7 +58,7 @@ class SubscriptionsOverdueReminder extends Notification
|
||||
$info = [];
|
||||
$count = 0;
|
||||
foreach ($this->overdue as $item) {
|
||||
$current = ['bill' => $item['bill']];
|
||||
$current = ['bill' => $item['bill']];
|
||||
$current['pay_dates'] = array_map(static fn (string $date): string => new Carbon($date)->isoFormat((string) trans(
|
||||
'config.month_and_day_moment_js'
|
||||
)), $item['dates']['pay_dates']);
|
||||
|
||||
@@ -34,10 +34,6 @@ use Laravel\Passport\Passport;
|
||||
*/
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
protected $policies = [
|
||||
// 'FireflyIII\Model' => 'FireflyIII\Policies\ModelPolicy',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
*
|
||||
|
||||
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\StartFireflyIIISession;
|
||||
use Illuminate\Session\SessionManager;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Override;
|
||||
@@ -43,7 +43,7 @@ class FireflySessionProvider extends ServiceProvider
|
||||
|
||||
$this->registerSessionDriver();
|
||||
|
||||
$this->app->singleton(StartFireflySession::class);
|
||||
$this->app->singleton(StartFireflyIIISession::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,20 +42,18 @@ class RouteServiceProvider extends ServiceProvider
|
||||
#[Override]
|
||||
public function boot(): void
|
||||
{
|
||||
$this->routes(function (): void {
|
||||
Route::prefix('api')
|
||||
->middleware('api')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api.php'))
|
||||
;
|
||||
|
||||
Route::prefix('api/v1/cron')
|
||||
->middleware('api_basic')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api-noauth.php'))
|
||||
;
|
||||
|
||||
Route::middleware('web')->namespace($this->namespace)->group(base_path('routes/web.php'));
|
||||
});
|
||||
// $this->routes(function (): void {
|
||||
// Route::prefix('api')
|
||||
// ->middleware('api')
|
||||
// ->namespace($this->namespace)
|
||||
// ->group(base_path('routes/api.php'))
|
||||
// ;
|
||||
// Route::prefix('api/v1/cron')
|
||||
// ->middleware('api_basic')
|
||||
// ->namespace($this->namespace)
|
||||
// ->group(base_path('routes/api-noauth.php'))
|
||||
// ;
|
||||
// Route::middleware('web')->namespace($this->namespace)->group(base_path('routes/web.php'));
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\StartFireflyIIISession;
|
||||
use Illuminate\Session\SessionServiceProvider as BaseSessionServiceProvider;
|
||||
use Override;
|
||||
|
||||
@@ -42,6 +42,6 @@ class SessionServiceProvider extends BaseSessionServiceProvider
|
||||
|
||||
$this->registerSessionDriver();
|
||||
|
||||
$this->app->singleton(StartFireflySession::class);
|
||||
$this->app->singleton(StartFireflyIIISession::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ class AccountTasker implements AccountTaskerInterface, UserGroupInterface
|
||||
|
||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$currencies = [$primaryCurrency->id => $primaryCurrency];
|
||||
$currencies = [$primaryCurrency->id => $primaryCurrency];
|
||||
$report = ['accounts' => [], 'sums' => []];
|
||||
|
||||
/** @var array $journal */
|
||||
@@ -232,7 +232,7 @@ class AccountTasker implements AccountTaskerInterface, UserGroupInterface
|
||||
|
||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$currencies = [$primaryCurrency->id => $primaryCurrency];
|
||||
$currencies = [$primaryCurrency->id => $primaryCurrency];
|
||||
$report = ['accounts' => [], 'sums' => []];
|
||||
|
||||
/** @var array $journal */
|
||||
|
||||
@@ -96,7 +96,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
foreach ($set as $bill) {
|
||||
if ($bill->order !== $current) {
|
||||
$bill->order = $current;
|
||||
$bill->save();
|
||||
$bill->saveQuietly();
|
||||
}
|
||||
++$current;
|
||||
}
|
||||
@@ -613,7 +613,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function setOrder(Bill $bill, int $order): void
|
||||
{
|
||||
$bill->order = $order;
|
||||
$bill->save();
|
||||
$bill->saveQuietly();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,7 +85,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
?Collection $budgets = null,
|
||||
?TransactionCurrency $currency = null
|
||||
): array {
|
||||
Log::debug(sprintf('Start of %s(%s, %s, array, array, "%s").', __METHOD__, $start->toW3cString(), $end->toW3cString(), $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.
|
||||
@@ -204,7 +204,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
$currencySymbol = $primaryCurrency->symbol;
|
||||
$currencyDecimalPlaces = $primaryCurrency->decimal_places;
|
||||
$converter = new ExchangeRateConverter();
|
||||
$currencies = [$currencyId => $primaryCurrency];
|
||||
$currencies = [$currencyId => $primaryCurrency];
|
||||
|
||||
foreach ($journals as $journal) {
|
||||
$amount = Steam::negative($journal['amount']);
|
||||
@@ -275,7 +275,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
TransactionCurrency $transactionCurrency,
|
||||
bool $convertToPrimary = false
|
||||
): array {
|
||||
Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
// Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
$summarizer = new TransactionSummarizer($this->user);
|
||||
$summarizer->setConvertToPrimary($convertToPrimary);
|
||||
|
||||
@@ -290,7 +290,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
|
||||
public function sumCollectedExpensesByBudget(array $expenses, Budget $budget, bool $convertToPrimary = false): array
|
||||
{
|
||||
Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
// Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
$summarizer = new TransactionSummarizer($this->user);
|
||||
$summarizer->setConvertToPrimary($convertToPrimary);
|
||||
|
||||
@@ -311,7 +311,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
?TransactionCurrency $currency = null,
|
||||
bool $convertToPrimary = false
|
||||
): array {
|
||||
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", %s).', __METHOD__, $currency?->code, var_export($convertToPrimary, true)));
|
||||
// Log::debug(sprintf('Start of %s(date, date, array, array, "%s", %s).', __METHOD__, $currency?->code, var_export($convertToPrimary, true)));
|
||||
// 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.
|
||||
|
||||
@@ -372,7 +372,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
|
||||
public function sumCollectedTransactionsByCategory(array $expenses, Category $category, string $method, bool $convertToPrimary = false): array
|
||||
{
|
||||
Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
// Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
$summarizer = new TransactionSummarizer($this->user);
|
||||
$summarizer->setConvertToPrimary($convertToPrimary);
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ class PeriodStatisticRepository implements PeriodStatisticRepositoryInterface, U
|
||||
#[Override]
|
||||
public function allInRangeForPrefix(string $prefix, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
Log::debug(sprintf('Collect all statistics where type starts with "%s"', $prefix));
|
||||
Log::debug(sprintf('Between %s and %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
|
||||
return $this->userGroup
|
||||
->periodStatistics()
|
||||
->where('type', 'LIKE', sprintf('%s%%', $prefix))
|
||||
@@ -156,6 +159,7 @@ class PeriodStatisticRepository implements PeriodStatisticRepositoryInterface, U
|
||||
int $count,
|
||||
string $amount
|
||||
): PeriodStatistic {
|
||||
Log::debug(sprintf('Store as type "%s"', sprintf('%s_%s', $prefix, $type)));
|
||||
$stat = new PeriodStatistic();
|
||||
$stat->transaction_currency_id = $currencyId;
|
||||
$stat->user_group_id = $this->getUserGroup()->id;
|
||||
|
||||
@@ -102,7 +102,7 @@ class RuleRepository implements RuleRepositoryInterface, UserGroupInterface
|
||||
{
|
||||
return $this->user
|
||||
->rules()
|
||||
->with(['ruleGroup'])
|
||||
->with(['ruleGroup', 'ruleTriggers', 'ruleActions'])
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
@@ -195,21 +195,21 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
|
||||
if (null === $filter) {
|
||||
return $groups;
|
||||
}
|
||||
Log::debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter));
|
||||
// Log::debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter));
|
||||
|
||||
return $groups->map(static function (RuleGroup $group) use ($filter): RuleGroup { // @phpstan-ignore-line
|
||||
Log::debug(sprintf('Now filtering group #%d', $group->id));
|
||||
// Log::debug(sprintf('Now filtering group #%d', $group->id));
|
||||
// filter the rules in the rule group:
|
||||
$group->rules = $group->rules->filter(static function (Rule $rule) use ($filter, $group): bool {
|
||||
Log::debug(sprintf('Now filtering rule #%d', $rule->id));
|
||||
$group->rules = $group->rules->filter(static function (Rule $rule) use ($filter): bool {
|
||||
// Log::debug(sprintf('Now filtering rule #%d', $rule->id));
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if ('user_action' === $trigger->trigger_type && $filter === $trigger->trigger_value) {
|
||||
Log::debug(sprintf('Rule #%d triggers on %s, include it in rule group #%d.', $rule->id, $filter, $group->id));
|
||||
// Log::debug(sprintf('Rule #%d triggers on %s, include it in rule group #%d.', $rule->id, $filter, $group->id));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Rule #%d does not trigger on %s, do not include it.', $rule->id, $filter));
|
||||
// Log::debug(sprintf('Rule #%d does not trigger on %s, do not include it.', $rule->id, $filter));
|
||||
|
||||
return false;
|
||||
});
|
||||
@@ -251,18 +251,18 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
|
||||
Log::debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter));
|
||||
|
||||
return $groups->map(static function (RuleGroup $group) use ($filter): RuleGroup { // @phpstan-ignore-line
|
||||
Log::debug(sprintf('Now filtering group #%d', $group->id));
|
||||
// Log::debug(sprintf('Now filtering group #%d', $group->id));
|
||||
// filter the rules in the rule group:
|
||||
$group->rules = $group->rules->filter(static function (Rule $rule) use ($filter, $group): bool {
|
||||
Log::debug(sprintf('Now filtering rule #%d', $rule->id));
|
||||
$group->rules = $group->rules->filter(static function (Rule $rule) use ($filter): bool {
|
||||
// Log::debug(sprintf('Now filtering rule #%d', $rule->id));
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if ('user_action' === $trigger->trigger_type && $filter === $trigger->trigger_value) {
|
||||
Log::debug(sprintf('Rule #%d triggers on %s, include it in rule group #%d.', $rule->id, $filter, $group->id));
|
||||
// Log::debug(sprintf('Rule #%d triggers on %s, include it in rule group #%d.', $rule->id, $filter, $group->id));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Rule #%d does not trigger on %s, do not include it.', $rule->id, $filter));
|
||||
// Log::debug(sprintf('Rule #%d does not trigger on %s, do not include it.', $rule->id, $filter));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -62,8 +62,8 @@ trait AccountServiceTrait
|
||||
if (null === $iban) {
|
||||
return null;
|
||||
}
|
||||
$data = ['iban' => $iban];
|
||||
$rules = ['iban' => 'required|iban'];
|
||||
$data = ['iban' => $iban];
|
||||
$rules = ['iban' => 'required|iban'];
|
||||
$validator = Validator::make($data, $rules);
|
||||
if ($validator->fails()) {
|
||||
Log::info(sprintf('Detected invalid IBAN ("%s"). Return NULL instead.', $iban));
|
||||
@@ -228,7 +228,7 @@ trait AccountServiceTrait
|
||||
$sourceId = $account->id;
|
||||
$sourceName = null;
|
||||
$destId = null;
|
||||
$destName = trans('firefly.liability_credit_description', ['account' => $account->name], $language);
|
||||
$destName = trans('firefly.liability_credit_description', ['account' => $account->name], $language);
|
||||
}
|
||||
|
||||
// amount must be positive for the transaction to work.
|
||||
@@ -257,7 +257,7 @@ trait AccountServiceTrait
|
||||
'order' => 0,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => null,
|
||||
'description' => trans('firefly.liability_credit_description', ['account' => $account->name]),
|
||||
'description' => trans('firefly.liability_credit_description', ['account' => $account->name]),
|
||||
'budget_id' => null,
|
||||
'budget_name' => null,
|
||||
'category_id' => null,
|
||||
@@ -352,7 +352,7 @@ trait AccountServiceTrait
|
||||
'order' => 0,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => null,
|
||||
'description' => trans('firefly.initial_balance_description', ['account' => $account->name]),
|
||||
'description' => trans('firefly.initial_balance_description', ['account' => $account->name]),
|
||||
'budget_id' => null,
|
||||
'budget_name' => null,
|
||||
'category_id' => null,
|
||||
@@ -444,7 +444,7 @@ trait AccountServiceTrait
|
||||
'order' => 0,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => null,
|
||||
'description' => trans('firefly.initial_balance_description', ['account' => $account->name]),
|
||||
'description' => trans('firefly.initial_balance_description', ['account' => $account->name]),
|
||||
'budget_id' => null,
|
||||
'budget_name' => null,
|
||||
'category_id' => null,
|
||||
|
||||
@@ -37,6 +37,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Rules\UniqueIban;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Safe\Exceptions\JsonException;
|
||||
|
||||
@@ -227,7 +228,12 @@ trait JournalServiceTrait
|
||||
$set = array_unique($set);
|
||||
Log::debug('End of loop.');
|
||||
Log::debug(sprintf('Total nr. of tags: %d', count($tags)), $tags);
|
||||
$journal->tags()->sync($set);
|
||||
|
||||
try {
|
||||
$journal->tags()->sync($set);
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
Log::error(sprintf('Firefly III could not sync tags: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,9 +78,11 @@ class AccountUpdateService
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$this->accountRepository->setUser($account->user);
|
||||
$this->user = $account->user;
|
||||
$account = $this->updateAccount($account, $data);
|
||||
$account = $this->updateAccountOrder($account, $data);
|
||||
$this->user = $account->user;
|
||||
$oldData = $account->toArray();
|
||||
$oldData['account_number'] = $this->accountRepository->getMetaValue($account, 'account_number');
|
||||
$account = $this->updateAccount($account, $data);
|
||||
$account = $this->updateAccountOrder($account, $data);
|
||||
|
||||
// find currency, or use default currency instead.
|
||||
if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) {
|
||||
@@ -109,7 +111,7 @@ class AccountUpdateService
|
||||
// update preferences if inactive:
|
||||
$this->updatePreferences($account);
|
||||
|
||||
event(new UpdatedExistingAccount($account));
|
||||
event(new UpdatedExistingAccount($account, $oldData));
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Events\Model\Bill\UpdatedExistingBill;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Services\Internal\Support\BillServiceTrait;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
@@ -50,6 +50,7 @@ class BillUpdateService
|
||||
public function update(Bill $bill, array $data): Bill
|
||||
{
|
||||
$this->user = $bill->user;
|
||||
$oldData = $bill->toArray();
|
||||
|
||||
if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) {
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
@@ -68,13 +69,6 @@ class BillUpdateService
|
||||
$bill = $this->updateBillProperties($bill, $data);
|
||||
$bill->save();
|
||||
$bill->refresh();
|
||||
// old values
|
||||
$oldData = [
|
||||
'name' => $bill->name,
|
||||
'amount_min' => $bill->amount_min,
|
||||
'amount_max' => $bill->amount_max,
|
||||
'transaction_currency_name' => $bill->transactionCurrency->name,
|
||||
];
|
||||
// update note:
|
||||
if (array_key_exists('notes', $data)) {
|
||||
$this->updateNote($bill, (string) $data['notes']);
|
||||
@@ -90,12 +84,6 @@ class BillUpdateService
|
||||
}
|
||||
}
|
||||
|
||||
// update rule actions.
|
||||
if (array_key_exists('name', $data)) {
|
||||
$this->updateBillActions($bill, $oldData['name'], $data['name']);
|
||||
$this->updateBillTriggers($bill, $oldData, $data);
|
||||
}
|
||||
|
||||
// update using name:
|
||||
if (array_key_exists('object_group_title', $data)) {
|
||||
$objectGroupTitle = $data['object_group_title'] ?? '';
|
||||
@@ -127,6 +115,7 @@ class BillUpdateService
|
||||
$bill->objectGroups()->sync([]);
|
||||
$bill->save();
|
||||
}
|
||||
event(new UpdatedExistingBill($bill, $oldData));
|
||||
|
||||
return $bill;
|
||||
}
|
||||
@@ -181,39 +170,6 @@ class BillUpdateService
|
||||
return $bill;
|
||||
}
|
||||
|
||||
private function updateBillTriggers(Bill $bill, array $oldData, array $newData): void
|
||||
{
|
||||
Log::debug(sprintf('Now in updateBillTriggers(%d, "%s")', $bill->id, $bill->name));
|
||||
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser($bill->user);
|
||||
$rules = $repository->getRulesForBill($bill);
|
||||
if (0 === $rules->count()) {
|
||||
Log::debug('Found no rules.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug(sprintf('Found %d rules', $rules->count()));
|
||||
$fields = [
|
||||
'name' => 'description_contains',
|
||||
'amount_min' => 'amount_more',
|
||||
'amount_max' => 'amount_less',
|
||||
'transaction_currency_name' => 'currency_is',
|
||||
];
|
||||
foreach ($fields as $field => $ruleTriggerKey) {
|
||||
if (!array_key_exists($field, $newData)) {
|
||||
continue;
|
||||
}
|
||||
if ($oldData[$field] === $newData[$field]) {
|
||||
Log::debug(sprintf('Field %s is unchanged ("%s"), continue.', $field, $oldData[$field]));
|
||||
|
||||
continue;
|
||||
}
|
||||
$this->updateRules($rules, $ruleTriggerKey, $oldData[$field], $newData[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void
|
||||
{
|
||||
if ($newOrder > $oldOrder) {
|
||||
|
||||
@@ -551,7 +551,7 @@ class JournalUpdateService
|
||||
event(
|
||||
new TransactionGroupRequestsAuditLogEntry(
|
||||
$group->user,
|
||||
$group,
|
||||
$this->transactionJournal,
|
||||
'update_amount',
|
||||
[
|
||||
'currency_symbol' => $recordCurrency->symbol,
|
||||
@@ -767,7 +767,7 @@ class JournalUpdateService
|
||||
event(
|
||||
new TransactionGroupRequestsAuditLogEntry(
|
||||
$group->user,
|
||||
$group,
|
||||
$this->transactionJournal,
|
||||
'update_foreign_amount',
|
||||
[
|
||||
'currency_symbol' => $recordCurrency->symbol,
|
||||
|
||||
@@ -31,6 +31,7 @@ use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,7 @@ class RemoteUserGuard implements Guard
|
||||
{
|
||||
protected Application $application;
|
||||
protected ?User $user = null;
|
||||
private $tried = false;
|
||||
|
||||
/**
|
||||
* Create a new authentication guard.
|
||||
@@ -49,13 +51,19 @@ class RemoteUserGuard implements Guard
|
||||
Application $app
|
||||
) {
|
||||
$app->get('request');
|
||||
// Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
|
||||
Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $app->get('request')?->getMethod(), $app->get('request')?->getRequestUri()));
|
||||
$this->application = $app;
|
||||
}
|
||||
|
||||
public function authenticate(): void
|
||||
{
|
||||
// Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
$this->tried = true;
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
if (App::runningInConsole()) {
|
||||
Log::debug('Running in console, will not authenticate.');
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->user instanceof User) {
|
||||
Log::debug(sprintf('%s is found: #%d, "%s".', $this->user::class, $this->user->id, $this->user->email));
|
||||
|
||||
@@ -70,10 +78,14 @@ class RemoteUserGuard implements Guard
|
||||
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null;
|
||||
}
|
||||
|
||||
// test value for development
|
||||
// $userID = 'james@firefly';
|
||||
|
||||
if (null === $userID || '' === $userID) {
|
||||
Log::error(sprintf('No user in header "%s".', $header));
|
||||
|
||||
throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
|
||||
// throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
|
||||
return;
|
||||
}
|
||||
|
||||
Log::debug(sprintf('User ID found in header is "%s"', $userID));
|
||||
@@ -145,8 +157,18 @@ class RemoteUserGuard implements Guard
|
||||
|
||||
public function user(): ?User
|
||||
{
|
||||
if (App::runningInConsole()) {
|
||||
Log::debug('Running in console, will not authenticate.');
|
||||
|
||||
return null;
|
||||
}
|
||||
if (false === $this->tried) {
|
||||
Log::debug('Have not tried authentication, do it now.');
|
||||
$this->authenticate();
|
||||
}
|
||||
// Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
$user = $this->user;
|
||||
|
||||
if (!$user instanceof User) {
|
||||
Log::debug('User is NULL');
|
||||
|
||||
|
||||
@@ -35,12 +35,8 @@ class Calculator
|
||||
{
|
||||
public const int DEFAULT_INTERVAL = 1;
|
||||
|
||||
private static ?SplObjectStorage $intervalMap = null; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private static array $intervals = [];
|
||||
private static ?SplObjectStorage $intervalMap = null;
|
||||
private static array $intervals = [];
|
||||
|
||||
public function isAvailablePeriodicity(Periodicity $periodicity): bool
|
||||
{
|
||||
|
||||
@@ -81,14 +81,14 @@ class WholePeriodChartGenerator
|
||||
$code = $currency['currency_code'];
|
||||
$name = $currency['currency_name'];
|
||||
$chartData[sprintf('spent-in-%s', $code)] = [
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $name]),
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $name]),
|
||||
'entries' => [],
|
||||
'type' => 'bar',
|
||||
'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red
|
||||
];
|
||||
|
||||
$chartData[sprintf('earned-in-%s', $code)] = [
|
||||
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $name]),
|
||||
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $name]),
|
||||
'entries' => [],
|
||||
'type' => 'bar',
|
||||
'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
|
||||
|
||||
@@ -98,6 +98,54 @@ class ExportDataGenerator
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->accounts = new Collection();
|
||||
|
||||
@@ -49,7 +49,7 @@ class PiggyBankForm
|
||||
$piggyBanks = $repository->getPiggyBanksWithAmount();
|
||||
$title = (string) trans('firefly.default_group_title_name');
|
||||
$array = [];
|
||||
$subList = [0 => ['group' => ['title' => $title], 'piggies' => [(string) trans('firefly.none_in_select_list')]]];
|
||||
$subList = [0 => ['group' => ['title' => $title], 'piggies' => [(string) trans('firefly.none_in_select_list')]]];
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggyBanks as $piggy) {
|
||||
@@ -60,7 +60,7 @@ class PiggyBankForm
|
||||
$groupTitle = $group->title;
|
||||
$groupOrder = $group->order;
|
||||
}
|
||||
$subList[$groupOrder] ??= ['group' => ['title' => $groupTitle], 'piggies' => []];
|
||||
$subList[$groupOrder] ??= ['group' => ['title' => $groupTitle], 'piggies' => []];
|
||||
$subList[$groupOrder]['piggies'][$piggy->id] = $piggy->name;
|
||||
}
|
||||
ksort($subList);
|
||||
|
||||
@@ -170,7 +170,7 @@ class AccountBalanceGrouped
|
||||
{
|
||||
$this->primary = $primary;
|
||||
$primaryCurrencyId = $primary->id;
|
||||
$this->currencies = [$primary->id => $primary]; // currency cache
|
||||
$this->currencies = [$primary->id => $primary]; // currency cache
|
||||
$this->data[$primaryCurrencyId] = [
|
||||
'currency_id' => (string) $primaryCurrencyId,
|
||||
'currency_symbol' => $primary->symbol,
|
||||
|
||||
@@ -157,7 +157,7 @@ trait GetConfigurationData
|
||||
|
||||
// previous year:
|
||||
$yearBegin = today(config('app.timezone'))->subYear()->startOfYear();
|
||||
$index = (string) trans('firefly.previous_year', ['year' => $yearBegin->year]);
|
||||
$index = (string) trans('firefly.previous_year', ['year' => $yearBegin->year]);
|
||||
$ranges[$index] = [$yearBegin, $yearBegin->clone()->endOfYear()];
|
||||
|
||||
// everything
|
||||
|
||||
@@ -37,7 +37,6 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
@@ -80,20 +79,8 @@ trait PeriodOverview
|
||||
protected TagRepositoryInterface $tagRepository;
|
||||
protected JournalRepositoryInterface $journalRepos;
|
||||
protected PeriodStatisticRepositoryInterface $periodStatisticRepo;
|
||||
private Collection $statistics; // temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
private array $transactions; // temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
private Collection $statistics;
|
||||
private array $transactions;
|
||||
|
||||
/**
|
||||
* This method returns "period entries", so nov-2015, dec-2015, etc. (this depends on the users session range)
|
||||
@@ -154,6 +141,34 @@ trait PeriodOverview
|
||||
return $entries;
|
||||
}
|
||||
|
||||
protected function getGenericPeriod(string $type, string $period, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$return = [
|
||||
'title' => Navigation::periodShow($start, $period),
|
||||
'route' => route('transactions.index', [$type, $start->format('Y-m-d'), $end->format('Y-m-d')]),
|
||||
'total_transactions' => 0,
|
||||
];
|
||||
$setTypes = [
|
||||
'withdrawal' => 'spent',
|
||||
'expenses' => 'spent',
|
||||
'deposit' => 'earned',
|
||||
'revenue' => 'earned',
|
||||
'transfer' => 'transferred',
|
||||
'transfers' => 'transferred',
|
||||
];
|
||||
if (!array_key_exists($type, $setTypes)) {
|
||||
throw new FireflyException(sprintf('[c] Cannot deal with type "%s"', $type));
|
||||
}
|
||||
$setType = $setTypes[$type];
|
||||
|
||||
$this->transactions = [];
|
||||
$set = $this->getSingleGenericPeriodByType($start, $end, $type);
|
||||
$return['total_transactions'] += $set['count'];
|
||||
$return[$setType] = $set;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above, but for lists that involve transactions without a budget.
|
||||
*
|
||||
@@ -239,60 +254,18 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$range = Navigation::getViewRange(true);
|
||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('transactions-period-entries');
|
||||
$cache->addProperty($transactionType);
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
$this->periodStatisticRepo = app(PeriodStatisticRepositoryInterface::class);
|
||||
$range = Navigation::getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = Navigation::blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$spent = [];
|
||||
$earned = [];
|
||||
$transferred = [];
|
||||
// collect all journals in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes($types)->setRange($start, $end);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$loops = 0;
|
||||
$dates = Navigation::blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$this->statistics = $this->periodStatisticRepo->allInRangeForPrefix('all_', $start, $end);
|
||||
Log::debug(sprintf('Collected %d statistics', $this->statistics->count()));
|
||||
|
||||
foreach ($dates as $currentDate) {
|
||||
$title = Navigation::periodShow($currentDate['end'], $currentDate['period']);
|
||||
|
||||
if ($loops < 10) {
|
||||
// set to correct array
|
||||
if ('expenses' === $transactionType || 'withdrawal' === $transactionType) {
|
||||
$spent = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
if ('revenue' === $transactionType || 'deposit' === $transactionType) {
|
||||
$earned = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
if ('transfer' === $transactionType || 'transfers' === $transactionType) {
|
||||
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
}
|
||||
$entries[] = [
|
||||
'title' => $title,
|
||||
'route' => route('transactions.index', [
|
||||
$transactionType,
|
||||
$currentDate['start']->format('Y-m-d'),
|
||||
$currentDate['end']->format('Y-m-d'),
|
||||
]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
++$loops;
|
||||
$entries[] = $this->getGenericPeriod($transactionType, $currentDate['period'], $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
|
||||
return $entries;
|
||||
@@ -339,10 +312,11 @@ trait PeriodOverview
|
||||
|
||||
return new Collection();
|
||||
}
|
||||
Log::debug(sprintf('Now in filterStatistics("%s")', $type));
|
||||
|
||||
return $this->statistics->filter(
|
||||
static fn (PeriodStatistic $statistic): bool => $statistic->start->eq($start) && $statistic->end->eq($end) && $statistic->type === $type
|
||||
);
|
||||
return $this->statistics->filter(static function (PeriodStatistic $statistic) use ($start, $end, $type): bool {
|
||||
return $statistic->start->isSameSecond($start) && $statistic->end->isSameSecond($end) && $statistic->type === $type;
|
||||
});
|
||||
}
|
||||
|
||||
private function filterTransactionsByType(TransactionTypeEnum $type, Carbon $start, Carbon $end): array
|
||||
@@ -404,21 +378,63 @@ trait PeriodOverview
|
||||
return [$start, $end];
|
||||
}
|
||||
|
||||
private function getSingleGenericPeriodByType(Carbon $start, Carbon $end, string $type): array
|
||||
{
|
||||
$filterType = sprintf('all_%s', $type);
|
||||
$statistics = $this->filterStatistics($start, $end, $filterType);
|
||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $type));
|
||||
// nothing found, regenerate them.
|
||||
if (0 === $statistics->count()) {
|
||||
if (0 === count($this->transactions)) {
|
||||
// get collection!
|
||||
// collect all journals in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes($types)->setRange($start, $end);
|
||||
$this->transactions = $collector->getExtractedJournals();
|
||||
Log::debug(sprintf('Going to group %d found journal(s)', count($types)));
|
||||
}
|
||||
|
||||
$grouped = $this->groupByCurrency($this->filterJournalsByDate($this->transactions, $start, $end));
|
||||
$this->saveGroupedForPrefix('all', $start, $end, $type, $grouped);
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
$grouped = ['count' => 0];
|
||||
|
||||
/** @var PeriodStatistic $statistic */
|
||||
foreach ($statistics as $statistic) {
|
||||
$id = (int) $statistic->transaction_currency_id;
|
||||
$currency = Amount::getTransactionCurrencyById($id);
|
||||
$grouped[$id] = [
|
||||
'amount' => (string) $statistic->amount,
|
||||
'count' => (int) $statistic->count,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
];
|
||||
$grouped['count'] += (int) $statistic->count;
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
private function getSingleModelPeriodByType(Model $model, Carbon $start, Carbon $end, string $type): array
|
||||
{
|
||||
Log::debug(sprintf(
|
||||
'Now in getSingleModelPeriodByType(%s #%d, %s %s, %s)',
|
||||
$model::class,
|
||||
$model->id,
|
||||
$start->format('Y-m-d'),
|
||||
$end->format('Y-m-d'),
|
||||
$start->format('Y-m-d H:i:s.u'),
|
||||
$end->format('Y-m-d H:i:s.u'),
|
||||
$type
|
||||
));
|
||||
$statistics = $this->filterStatistics($start, $end, $type);
|
||||
|
||||
// nothing found, regenerate them.
|
||||
if (0 === $statistics->count()) {
|
||||
Log::debug(sprintf('Found nothing in this period for type "%s"', $type));
|
||||
Log::debug(sprintf('Found nothing between %s and %s for type "%s"', $start->format('Y-m-d H:i:s.u'), $end->format('Y-m-d H:i:s.u'), $type));
|
||||
if (0 === count($this->transactions)) {
|
||||
switch ($model::class) {
|
||||
default:
|
||||
@@ -443,7 +459,7 @@ trait PeriodOverview
|
||||
|
||||
switch ($type) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot deal with category period type %s', $type));
|
||||
throw new FireflyException(sprintf('Cannot deal with type %s', $type));
|
||||
|
||||
case 'spent':
|
||||
$result = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $start, $end);
|
||||
@@ -505,7 +521,7 @@ trait PeriodOverview
|
||||
|
||||
switch ($model) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot deal with model of type "%s"', $model));
|
||||
throw new FireflyException(sprintf('[b] Cannot deal with model of type "%s"', $model));
|
||||
|
||||
case 'budget':
|
||||
// get all expenses without a budget.
|
||||
|
||||
@@ -92,7 +92,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
*/
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
Log::debug(sprintf('Now doing account enrichment for %d account(s)', $collection->count()));
|
||||
// Log::debug(sprintf('Now doing account enrichment for %d account(s)', $collection->count()));
|
||||
|
||||
// prep local fields
|
||||
$this->collection = $collection;
|
||||
|
||||
@@ -45,11 +45,59 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private readonly bool $convertToPrimary; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $currencies = [];
|
||||
private array $currencyIds = [];
|
||||
private array $ids = [];
|
||||
|
||||
@@ -45,6 +45,30 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $currencies = [];
|
||||
private array $currencyIds = [];
|
||||
private Carbon $end;
|
||||
|
||||
@@ -63,7 +63,7 @@ class CategoryEnrichment implements EnrichmentInterface
|
||||
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
// Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
$collection = $this->enrich($collection);
|
||||
|
||||
|
||||
@@ -47,11 +47,59 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $accounts = []; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $amounts = [];
|
||||
private Collection $collection;
|
||||
private array $currencies = [];
|
||||
|
||||
@@ -42,11 +42,59 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $accountIds = []; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private Collection $collection;
|
||||
private array $currencies = [];
|
||||
private array $groupIds = [];
|
||||
|
||||
@@ -51,6 +51,30 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private readonly bool $convertToPrimary;
|
||||
private ?Carbon $end = null;
|
||||
private array $mappedObjects = [];
|
||||
|
||||
@@ -63,6 +63,54 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->dateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
@@ -72,7 +120,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
#[Override]
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
Log::debug(sprintf('Now doing account enrichment for %d transaction group(s)', $collection->count()));
|
||||
// Log::debug(sprintf('Now doing account enrichment for %d transaction group(s)', $collection->count()));
|
||||
// prep local fields
|
||||
$this->collection = $collection;
|
||||
$this->collectJournalIds();
|
||||
|
||||
@@ -47,11 +47,59 @@ class WebhookEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $ids = []; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $responses = [];
|
||||
private array $triggers = [];
|
||||
private array $webhookDeliveries = [];
|
||||
|
||||
@@ -78,7 +78,7 @@ class AccountBalanceCalculator
|
||||
]);
|
||||
|
||||
if (null === $first) {
|
||||
Log::debug(sprintf('Found no transactions for currency #%d and account #%d, return 0.', $currencyId, $accountId));
|
||||
// Log::debug(sprintf('Found no transactions for currency #%d and account #%d, return 0.', $currencyId, $accountId));
|
||||
|
||||
return '0';
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class TransactionSummarizer
|
||||
|
||||
public function groupByCurrencyId(array $journals, string $method = 'negative', bool $includeForeign = true): array
|
||||
{
|
||||
Log::debug(sprintf('Now in groupByCurrencyId([%d journals], "%s", %s)', count($journals), $method, var_export($includeForeign, true)));
|
||||
// Log::debug(sprintf('Now in groupByCurrencyId([%d journals], "%s", %s)', count($journals), $method, var_export($includeForeign, true)));
|
||||
$array = [];
|
||||
foreach ($journals as $journal) {
|
||||
$field = 'amount';
|
||||
@@ -146,7 +146,7 @@ class TransactionSummarizer
|
||||
// $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], \FireflyIII\Support\Facades\Steam::{$method}($amount));
|
||||
// Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount));
|
||||
}
|
||||
Log::debug('End of sumExpenses.', $array);
|
||||
// Log::debug('End of sumExpenses.', $array);
|
||||
|
||||
return $array;
|
||||
}
|
||||
@@ -234,7 +234,7 @@ class TransactionSummarizer
|
||||
|
||||
public function setConvertToPrimary(bool $convertToPrimary): void
|
||||
{
|
||||
Log::debug(sprintf('Overrule convertToPrimary to become %s', var_export($convertToPrimary, true)));
|
||||
// Log::debug(sprintf('Overrule convertToPrimary to become %s', var_export($convertToPrimary, true)));
|
||||
$this->convertToPrimary = $convertToPrimary;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user