mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-25 12:41:20 +00:00
Compare commits
44 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da0b41e45c | ||
|
|
d03960e379 | ||
|
|
16d3984ffc | ||
|
|
856a194988 | ||
|
|
1bff966bfe | ||
|
|
1948b6118b | ||
|
|
20c25d3ca2 | ||
|
|
a153735ac3 | ||
|
|
62509f7c18 | ||
|
|
9b48b67158 | ||
|
|
cbd50634a4 | ||
|
|
f475393bc1 | ||
|
|
abcddb09bf | ||
|
|
cf71a0fc55 | ||
|
|
78253f9e1e | ||
|
|
ebd0848c7f | ||
|
|
c8461eb0b5 | ||
|
|
a4cbdeaeac | ||
|
|
3e1ce69d52 | ||
|
|
08a26b976e | ||
|
|
5fc55381a2 | ||
|
|
dbf3d24ae7 | ||
|
|
cc7c6e02c5 | ||
|
|
b45aa85853 | ||
|
|
e7526ac5e3 | ||
|
|
441ada70b8 | ||
|
|
dedc06a46b | ||
|
|
b0adf1b277 | ||
|
|
28f65e9f44 | ||
|
|
a013af5f0d | ||
|
|
9552701662 | ||
|
|
ef52f0aad1 | ||
|
|
0b6f04905a | ||
|
|
cdb36357d4 | ||
|
|
8938622bd9 | ||
|
|
b210294aa9 | ||
|
|
5b02f20775 | ||
|
|
fac382a5df | ||
|
|
88d88bebc9 | ||
|
|
755fb9c29b | ||
|
|
51a835ab51 | ||
|
|
c9895ab182 | ||
|
|
e71d46a4e5 | ||
|
|
8d1d5f37c1 |
70
.ci/php-cs-fixer/composer.lock
generated
70
.ci/php-cs-fixer/composer.lock
generated
@@ -151,24 +151,24 @@
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/semver.git",
|
||||
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6"
|
||||
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6",
|
||||
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
|
||||
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"symfony/phpunit-bridge": "^4.2 || ^5"
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"symfony/phpunit-bridge": "^3 || ^7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -212,7 +212,7 @@
|
||||
"support": {
|
||||
"irc": "ircs://irc.libera.chat:6697/composer",
|
||||
"issues": "https://github.com/composer/semver/issues",
|
||||
"source": "https://github.com/composer/semver/tree/3.4.2"
|
||||
"source": "https://github.com/composer/semver/tree/3.4.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -228,7 +228,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-12T11:35:52+00:00"
|
||||
"time": "2024-09-19T14:15:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/xdebug-handler",
|
||||
@@ -1259,16 +1259,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.1.4",
|
||||
"version": "v7.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111"
|
||||
"reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111",
|
||||
"reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee",
|
||||
"reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1332,7 +1332,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.1.4"
|
||||
"source": "https://github.com/symfony/console/tree/v7.1.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1348,7 +1348,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-15T22:48:53+00:00"
|
||||
"time": "2024-09-20T08:28:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -1575,16 +1575,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v7.1.2",
|
||||
"version": "v7.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "92a91985250c251de9b947a14bb2c9390b1a562c"
|
||||
"reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c",
|
||||
"reference": "92a91985250c251de9b947a14bb2c9390b1a562c",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/61fe0566189bf32e8cfee78335d8776f64a66f5a",
|
||||
"reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1621,7 +1621,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.1.2"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.1.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1637,7 +1637,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-28T10:03:55+00:00"
|
||||
"time": "2024-09-17T09:16:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
@@ -2246,16 +2246,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v7.1.3",
|
||||
"version": "v7.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca"
|
||||
"reference": "5c03ee6369281177f07f7c68252a280beccba847"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca",
|
||||
"reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847",
|
||||
"reference": "5c03ee6369281177f07f7c68252a280beccba847",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2287,7 +2287,7 @@
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v7.1.3"
|
||||
"source": "https://github.com/symfony/process/tree/v7.1.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2303,7 +2303,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-26T12:44:47+00:00"
|
||||
"time": "2024-09-19T21:48:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@@ -2452,16 +2452,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v7.1.4",
|
||||
"version": "v7.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b"
|
||||
"reference": "d66f9c343fa894ec2037cc928381df90a7ad4306"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b",
|
||||
"reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306",
|
||||
"reference": "d66f9c343fa894ec2037cc928381df90a7ad4306",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2519,7 +2519,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v7.1.4"
|
||||
"source": "https://github.com/symfony/string/tree/v7.1.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2535,16 +2535,16 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-12T09:59:40+00:00"
|
||||
"time": "2024-09-20T08:28:38+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform": {},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
@@ -176,6 +176,7 @@ MAILGUN_ENDPOINT=api.mailgun.net
|
||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||
MANDRILL_SECRET=
|
||||
SPARKPOST_SECRET=
|
||||
MAILERSEND_API_KEY=
|
||||
|
||||
# Firefly III can send you the following messages.
|
||||
SEND_ERROR_MESSAGE=true
|
||||
@@ -312,6 +313,12 @@ PUSHER_ID=
|
||||
DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
|
||||
#
|
||||
# Disable or enable the running balance column data
|
||||
# Please disable this. It's a very experimental feature.
|
||||
#
|
||||
USE_RUNNING_BALANCE=false
|
||||
|
||||
#
|
||||
# The v2 layout is very experimental. If it breaks you get to keep both parts.
|
||||
# Be wary of data loss.
|
||||
|
||||
@@ -79,12 +79,12 @@ class StoreRequest extends FormRequest
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'date' => 'date|required',
|
||||
'end_date' => 'date|after:date',
|
||||
'extension_date' => 'date|after:date',
|
||||
'end_date' => 'nullable|date|after:date',
|
||||
'extension_date' => 'nullable|date|after:date',
|
||||
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly|required',
|
||||
'skip' => 'min:0|max:31|numeric',
|
||||
'active' => [new IsBoolean()],
|
||||
'notes' => 'min:1|max:32768',
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -84,10 +84,6 @@ class BalanceController extends Controller
|
||||
$queryParameters = $request->getParameters();
|
||||
$accounts = $this->getAccountList($queryParameters);
|
||||
|
||||
// move date to end of day
|
||||
$queryParameters['start']->startOfDay();
|
||||
$queryParameters['end']->endOfDay();
|
||||
|
||||
// prepare for currency conversion and data collection:
|
||||
/** @var TransactionCurrency $default */
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
|
||||
@@ -53,10 +53,10 @@ class ChartRequest extends FormRequest
|
||||
$queryParameters = QueryParameters::cast($this->all());
|
||||
|
||||
return [
|
||||
'start' => $this->dateOrToday($queryParameters, 'start'),
|
||||
'end' => $this->dateOrToday($queryParameters, 'end'),
|
||||
'start' => $this->dateOrToday($queryParameters, 'start')->startOfDay(),
|
||||
'end' => $this->dateOrToday($queryParameters, 'end')->endOfDay(),
|
||||
'preselected' => $this->stringFromQueryParams($queryParameters, 'preselected', 'empty'),
|
||||
'period' => $this->stringFromQueryParams($queryParameters, 'period', '1M'),
|
||||
'period' => $this->stringFromFilterParams($queryParameters, 'period', '1M'),
|
||||
'accounts' => $this->arrayOfStrings($queryParameters, 'accounts'),
|
||||
// preselected heeft maar een paar toegestane waardes, dat moet ook goed gaan.
|
||||
// 'query' => $this->arrayOfStrings($queryParameters, 'query'),
|
||||
@@ -80,12 +80,14 @@ class ChartRequest extends FormRequest
|
||||
return [
|
||||
'fields' => JsonApiRule::notSupported(),
|
||||
'filter' => ['nullable', 'array',
|
||||
new IsValidFilter(['start', 'end', 'preselected', 'accounts']),
|
||||
new IsValidFilter(['start', 'end', 'preselected', 'accounts', 'period']),
|
||||
new IsFilterValueIn('preselected', config('firefly.preselected_accounts')),
|
||||
],
|
||||
'include' => JsonApiRule::notSupported(),
|
||||
'page' => JsonApiRule::notSupported(),
|
||||
'sort' => JsonApiRule::notSupported(),
|
||||
// 'start' => 'required|date|after:1900-01-01|before:2099-12-31',
|
||||
// 'end' => 'required|date|after_or_equal:start|before:2099-12-31|after:1900-01-01',
|
||||
];
|
||||
|
||||
// return [
|
||||
|
||||
@@ -717,7 +717,7 @@ trait MetaCollection
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
$this->query->where('journal_meta.name', '=', 'internal_reference');
|
||||
$this->query->where('journal_meta.data', '=', $internalReference);
|
||||
$this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($internalReference)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,8 @@ class PopupReport implements PopupReportInterface
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($attributes['accounts'])
|
||||
$collector
|
||||
->setAccounts($attributes['accounts'])
|
||||
->withAccountInformation()
|
||||
->withBudgetInformation()
|
||||
->withCategoryInformation()
|
||||
@@ -113,11 +114,10 @@ class PopupReport implements PopupReportInterface
|
||||
if (null !== $currency) {
|
||||
$collector->setCurrency($currency);
|
||||
}
|
||||
|
||||
if (null === $budget->id) {
|
||||
if (null === $budget->id || 0 === $budget->id) {
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL])->withoutBudget();
|
||||
}
|
||||
if (null !== $budget->id) {
|
||||
if (null !== $budget->id && 0 !== $budget->id) {
|
||||
$collector->setBudget($budget);
|
||||
}
|
||||
|
||||
|
||||
@@ -362,11 +362,9 @@ class CreateRecurringTransactions implements ShouldQueue
|
||||
$groupTitle = null;
|
||||
$count = $recurrence->recurrenceTransactions->count();
|
||||
// #8844, if there is one recurrence transaction, use the first title as the title.
|
||||
if (1 === $count) {
|
||||
/** @var RecurrenceTransaction $first */
|
||||
$first = $recurrence->recurrenceTransactions()->first();
|
||||
$groupTitle = $first->description;
|
||||
}
|
||||
// #9305, if there is one recurrence transaction, group title must be NULL.
|
||||
$groupTitle = null;
|
||||
|
||||
// #8844, if there are more, use the recurrence transaction itself.
|
||||
if ($count > 1) {
|
||||
$groupTitle = $recurrence->title;
|
||||
|
||||
@@ -327,15 +327,17 @@ class CreditRecalculateService
|
||||
|
||||
if ($isSameAccount && $isDebit && $this->isTransferIn($usedAmount, $type)) { // case 9
|
||||
$usedAmount = app('steam')->positive($usedAmount);
|
||||
$result = bcadd($leftOfDebt, $usedAmount);
|
||||
app('log')->debug(sprintf('Case 9 (transfer into debit liability, means you owe more): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2)));
|
||||
$result = bcsub($leftOfDebt, $usedAmount);
|
||||
// 2024-10-05, #9225 this used to say you would owe more, but a transfer INTO a debit from wherever means you owe LESS.
|
||||
app('log')->debug(sprintf('Case 9 (transfer into debit liability, means you owe LESS): %s - %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2)));
|
||||
|
||||
return $result;
|
||||
}
|
||||
if ($isSameAccount && $isDebit && $this->isTransferOut($usedAmount, $type)) { // case 10
|
||||
$usedAmount = app('steam')->positive($usedAmount);
|
||||
$result = bcsub($leftOfDebt, $usedAmount);
|
||||
app('log')->debug(sprintf('Case 5 (transfer out of debit liability, means you owe less): %s - %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2)));
|
||||
$result = bcadd($leftOfDebt, $usedAmount);
|
||||
// 2024-10-05, #9225 this used to say you would owe less, but a transfer OUT OF a debit from wherever means you owe MORE.
|
||||
app('log')->debug(sprintf('Case 10 (transfer out of debit liability, means you owe MORE): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2)));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ trait ParsesQueryFilters
|
||||
$date = today();
|
||||
|
||||
$value = $parameters->filter()?->value($field, date('Y-m-d'));
|
||||
|
||||
if (is_array($value)) {
|
||||
Log::error(sprintf('Multiple values for date field "%s". Using first value.', $field));
|
||||
$value = $value[0];
|
||||
@@ -65,4 +66,9 @@ trait ParsesQueryFilters
|
||||
{
|
||||
return (string) ($parameters->page()[$field] ?? $default);
|
||||
}
|
||||
|
||||
private function stringFromFilterParams(QueryParameters $parameters, string $field, string $default): string
|
||||
{
|
||||
return (string)$parameters->filter()?->value($field, $default) ?? $default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ trait RenderPartialViews
|
||||
|
||||
$budget = $budgetRepository->find((int)$attributes['budgetId']);
|
||||
if (null === $budget) {
|
||||
// transactions without a budget.
|
||||
$budget = new Budget();
|
||||
}
|
||||
$journals = $popupHelper->byBudget($budget, $attributes);
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountBalance;
|
||||
@@ -74,7 +75,35 @@ class AccountBalanceCalculator
|
||||
foreach ($transactionJournal->transactions as $transaction) {
|
||||
$accounts->push($transaction->account);
|
||||
}
|
||||
$object->optimizedCalculation($accounts);
|
||||
$object->optimizedCalculation($accounts, $transactionJournal->date);
|
||||
}
|
||||
|
||||
private function getLatestBalance(int $accountId, int $currencyId, ?Carbon $notBefore): string
|
||||
{
|
||||
if (null === $notBefore) {
|
||||
return '0';
|
||||
}
|
||||
Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d')));
|
||||
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->where('transaction_journals.transaction_currency_id', $currencyId)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
// this order is the same as GroupCollector
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->orderBy('transaction_journals.description', 'DESC')
|
||||
->orderBy('transactions.amount', 'DESC')
|
||||
->where('transactions.account_id', $accountId)
|
||||
;
|
||||
$notBefore->startOfDay();
|
||||
$query->where('transaction_journals.date', '<', $notBefore);
|
||||
|
||||
$first = $query->first(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount', 'transactions.balance_after']);
|
||||
$balance = $first->balance_after ?? '0';
|
||||
Log::debug(sprintf('getLatestBalance: found balance: %s in transaction #%d', $balance, $first->id ?? 0));
|
||||
|
||||
return $balance;
|
||||
}
|
||||
|
||||
private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance
|
||||
@@ -98,9 +127,15 @@ class AccountBalanceCalculator
|
||||
return $entry;
|
||||
}
|
||||
|
||||
private function optimizedCalculation(Collection $accounts): void
|
||||
private function optimizedCalculation(Collection $accounts, ?Carbon $notBefore = null): void
|
||||
{
|
||||
Log::debug('start of optimizedCalculation');
|
||||
if (false === config('firefly.feature_flags.running_balance_column')) {
|
||||
Log::debug('optimizedCalculation is disabled, return.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($accounts->count() > 0) {
|
||||
Log::debug(sprintf('Limited to %d account(s)', $accounts->count()));
|
||||
}
|
||||
@@ -120,6 +155,10 @@ class AccountBalanceCalculator
|
||||
if ($accounts->count() > 0) {
|
||||
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
||||
}
|
||||
if (null !== $notBefore) {
|
||||
$notBefore->startOfDay();
|
||||
$query->where('transaction_journals.date', '>=', $notBefore);
|
||||
}
|
||||
|
||||
$set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']);
|
||||
|
||||
@@ -127,7 +166,7 @@ class AccountBalanceCalculator
|
||||
foreach ($set as $entry) {
|
||||
// start with empty array:
|
||||
$balances[$entry->account_id] ??= [];
|
||||
$balances[$entry->account_id][$entry->transaction_currency_id] ??= '0';
|
||||
$balances[$entry->account_id][$entry->transaction_currency_id] ??= $this->getLatestBalance($entry->account_id, $entry->transaction_currency_id, $notBefore);
|
||||
|
||||
// before and after are easy:
|
||||
$before = $balances[$entry->account_id][$entry->transaction_currency_id];
|
||||
|
||||
@@ -29,7 +29,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||
use League\CommonMark\GithubFlavoredMarkdownConverter;
|
||||
use Route;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
@@ -63,12 +62,29 @@ class General extends AbstractExtension
|
||||
}
|
||||
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
$info = app('steam')->balanceByTransactions($account, $date, null);
|
||||
$date = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
$runningBalance = config('firefly.feature_flags.running_balance_column');
|
||||
$info = [];
|
||||
if (true === $runningBalance) {
|
||||
$info = app('steam')->balanceByTransactions($account, $date, null);
|
||||
}
|
||||
if (false === $runningBalance) {
|
||||
$info[] = app('steam')->balance($account, $date);
|
||||
}
|
||||
|
||||
$strings = [];
|
||||
$strings = [];
|
||||
foreach ($info as $currencyId => $balance) {
|
||||
$strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false);
|
||||
$balance = (string) $balance;
|
||||
if (0 === $currencyId) {
|
||||
// not good code but OK
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$currency = $accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency();
|
||||
$strings[] = app('amount')->formatAnything($currency, $balance, false);
|
||||
}
|
||||
if (0 !== $currencyId) {
|
||||
$strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $strings);
|
||||
@@ -198,7 +214,7 @@ class General extends AbstractExtension
|
||||
]
|
||||
);
|
||||
|
||||
return (string)$converter->convert($text);
|
||||
return (string) $converter->convert($text);
|
||||
},
|
||||
['is_safe' => ['html']]
|
||||
);
|
||||
@@ -212,8 +228,8 @@ class General extends AbstractExtension
|
||||
return new TwigFilter(
|
||||
'phphost',
|
||||
static function (string $string): string {
|
||||
$proto = (string)parse_url($string, PHP_URL_SCHEME);
|
||||
$host = (string)parse_url($string, PHP_URL_HOST);
|
||||
$proto = (string) parse_url($string, PHP_URL_SCHEME);
|
||||
$host = (string) parse_url($string, PHP_URL_HOST);
|
||||
|
||||
return e(sprintf('%s://%s', $proto, $host));
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class AccountValidator
|
||||
app('log')->debug('AccountValidator source is set to NULL');
|
||||
}
|
||||
if (null !== $account) {
|
||||
app('log')->debug(sprintf('AccountValidator source is set to #%d: "%s" (%s)', $account->id, $account->name, $account->accountType->type));
|
||||
app('log')->debug(sprintf('AccountValidator source is set to #%d: "%s" (%s)', $account->id, $account->name, $account->accountType?->type));
|
||||
}
|
||||
$this->source = $account;
|
||||
}
|
||||
|
||||
63
changelog.md
63
changelog.md
@@ -3,6 +3,69 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 6.1.21 - 2024-09-30
|
||||
|
||||
### Added
|
||||
|
||||
- Enabled the expression engine built by @michaelhthomas. Read more about it in [the documentation](https://docs.firefly-iii.org/references/firefly-iii/rule-expressions/).
|
||||
- Add running balance data, see if it can be used in the layout in the future.
|
||||
- [PR 9160](https://github.com/firefly-iii/firefly-iii/pull/9160) (add test cases for api/v1/autocomplete/CategoryController) reported by @tasnim0tantawi
|
||||
- [PR 9178](https://github.com/firefly-iii/firefly-iii/pull/9178) (Add test cases for Api\V1\Controllers\Autocomplete\BillController & BudgetController) reported by @tasnim0tantawi
|
||||
- [PR 9171](https://github.com/firefly-iii/firefly-iii/pull/9171) (Add about test) reported by @mzhubail
|
||||
|
||||
### Changed
|
||||
|
||||
- [PR 9096](https://github.com/firefly-iii/firefly-iii/pull/9096) (chore: fix some comments) reported by @withbest
|
||||
|
||||
### Fixed
|
||||
|
||||
- [Issue 9078](https://github.com/firefly-iii/firefly-iii/issues/9078) (bcadd exception while using POST transactions) reported by @dbtdsilva
|
||||
- [Discussion 9080](https://github.com/orgs/firefly-iii/discussions/9080) (Incorrect sorting on expense accounts) started by @pc-zookeeper
|
||||
- [Issue 9084](https://github.com/firefly-iii/firefly-iii/issues/9084) (API Call for bills/nextExpectedMatch does not update) reported by @marcelweikum
|
||||
- [Issue 9103](https://github.com/firefly-iii/firefly-iii/issues/9103) (Default Currency does not apply to Accounts.) reported by @chrisgriff1512
|
||||
- [Issue 9140](https://github.com/firefly-iii/firefly-iii/issues/9140) (Dashboard 'Today' option chooses 1st of month (not current date)) reported by @PAS-BC
|
||||
- [PR 9179](https://github.com/firefly-iii/firefly-iii/pull/9179) (fix Navigation.php MTD logic to make tests pass.) reported by @tasnim0tantawi
|
||||
- [PR 9239](https://github.com/firefly-iii/firefly-iii/pull/9239) (Fix webhook index page when Firefly is not served at root) reported by @jfpedroza
|
||||
- [Issue 9168](https://github.com/firefly-iii/firefly-iii/issues/9168) (Custom logout URL doesn't work.) reported by @JC5
|
||||
- [Issue 9155](https://github.com/firefly-iii/firefly-iii/issues/9155) (internal_reference_is does not correctly match numeric internal references) reported by @Lrns123
|
||||
- [Issue 9275](https://github.com/firefly-iii/firefly-iii/issues/9275) (Long wait when editing a transaction) reported by @JC5
|
||||
- [Issue 9278](https://github.com/firefly-iii/firefly-iii/issues/9278) (Update to v6.1.20 changed Balance of Account) reported by @JeuJeus
|
||||
- [Issue 9281](https://github.com/firefly-iii/firefly-iii/issues/9281) (Update to v6.1.20 leads to a type error) reported by @krakonos1602
|
||||
|
||||
### API
|
||||
|
||||
- Expand v2 API
|
||||
|
||||
## 6.1.20 - 2024-09-29
|
||||
|
||||
### Added
|
||||
|
||||
- Enabled the expression engine built by @michaelhthomas. Read more about it in [the documentation](https://docs.firefly-iii.org/references/firefly-iii/rule-expressions/).
|
||||
- Add running balance data, see if it can be used in the layout in the future.
|
||||
- [PR 9160](https://github.com/firefly-iii/firefly-iii/pull/9160) (add test cases for api/v1/autocomplete/CategoryController) reported by @tasnim0tantawi
|
||||
- [PR 9178](https://github.com/firefly-iii/firefly-iii/pull/9178) (Add test cases for Api\V1\Controllers\Autocomplete\BillController & BudgetController) reported by @tasnim0tantawi
|
||||
- [PR 9171](https://github.com/firefly-iii/firefly-iii/pull/9171) (Add about test) reported by @mzhubail
|
||||
|
||||
### Changed
|
||||
|
||||
- [PR 9096](https://github.com/firefly-iii/firefly-iii/pull/9096) (chore: fix some comments) reported by @withbest
|
||||
|
||||
### Fixed
|
||||
|
||||
- [Issue 9078](https://github.com/firefly-iii/firefly-iii/issues/9078) (bcadd exception while using POST transactions) reported by @dbtdsilva
|
||||
- [Discussion 9080](https://github.com/orgs/firefly-iii/discussions/9080) (Incorrect sorting on expense accounts) started by @pc-zookeeper
|
||||
- [Issue 9084](https://github.com/firefly-iii/firefly-iii/issues/9084) (API Call for bills/nextExpectedMatch does not update) reported by @marcelweikum
|
||||
- [Issue 9103](https://github.com/firefly-iii/firefly-iii/issues/9103) (Default Currency does not apply to Accounts.) reported by @chrisgriff1512
|
||||
- [Issue 9140](https://github.com/firefly-iii/firefly-iii/issues/9140) (Dashboard 'Today' option chooses 1st of month (not current date)) reported by @PAS-BC
|
||||
- [PR 9179](https://github.com/firefly-iii/firefly-iii/pull/9179) (fix Navigation.php MTD logic to make tests pass.) reported by @tasnim0tantawi
|
||||
- [PR 9239](https://github.com/firefly-iii/firefly-iii/pull/9239) (Fix webhook index page when Firefly is not served at root) reported by @jfpedroza
|
||||
- [Issue 9168](https://github.com/firefly-iii/firefly-iii/issues/9168) (Custom logout URL doesn't work.) reported by @JC5
|
||||
- [Issue 9155](https://github.com/firefly-iii/firefly-iii/issues/9155) (internal_reference_is does not correctly match numeric internal references) reported by @Lrns123
|
||||
|
||||
### API
|
||||
|
||||
- Expand v2 API
|
||||
|
||||
## 6.1.19 - 2024-07-20
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"league/commonmark": "2.*",
|
||||
"league/csv": "^9.10",
|
||||
"league/fractal": "0.*",
|
||||
"mailersend/laravel-driver": "^2.7",
|
||||
"nunomaduro/collision": "^8",
|
||||
"pragmarx/google2fa": "^8.0",
|
||||
"predis/predis": "^2.2",
|
||||
@@ -123,7 +124,7 @@
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1",
|
||||
"phpstan/phpstan-strict-rules": "^1.4",
|
||||
"phpstan/phpstan-strict-rules": "^1.6",
|
||||
"phpunit/phpunit": "^10",
|
||||
"thecodingmachine/phpstan-strict-rules": "^1.0"
|
||||
},
|
||||
@@ -194,7 +195,8 @@
|
||||
"optimize-autoloader": true,
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"phpstan/extension-installer": true
|
||||
"phpstan/extension-installer": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1124
composer.lock
generated
1124
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -65,10 +65,6 @@ use FireflyIII\Support\Binder\UserGroupAccount;
|
||||
use FireflyIII\Support\Binder\UserGroupBill;
|
||||
use FireflyIII\Support\Binder\UserGroupTransaction;
|
||||
use FireflyIII\TransactionRules\Actions\AddTag;
|
||||
use FireflyIII\TransactionRules\Actions\AppendDescription;
|
||||
use FireflyIII\TransactionRules\Actions\AppendDescriptionToNotes;
|
||||
use FireflyIII\TransactionRules\Actions\AppendNotes;
|
||||
use FireflyIII\TransactionRules\Actions\AppendNotesToDescription;
|
||||
use FireflyIII\TransactionRules\Actions\ClearBudget;
|
||||
use FireflyIII\TransactionRules\Actions\ClearCategory;
|
||||
use FireflyIII\TransactionRules\Actions\ClearNotes;
|
||||
@@ -77,10 +73,6 @@ use FireflyIII\TransactionRules\Actions\ConvertToTransfer;
|
||||
use FireflyIII\TransactionRules\Actions\ConvertToWithdrawal;
|
||||
use FireflyIII\TransactionRules\Actions\DeleteTransaction;
|
||||
use FireflyIII\TransactionRules\Actions\LinkToBill;
|
||||
use FireflyIII\TransactionRules\Actions\MoveDescriptionToNotes;
|
||||
use FireflyIII\TransactionRules\Actions\MoveNotesToDescription;
|
||||
use FireflyIII\TransactionRules\Actions\PrependDescription;
|
||||
use FireflyIII\TransactionRules\Actions\PrependNotes;
|
||||
use FireflyIII\TransactionRules\Actions\RemoveAllTags;
|
||||
use FireflyIII\TransactionRules\Actions\RemoveTag;
|
||||
use FireflyIII\TransactionRules\Actions\SetAmount;
|
||||
@@ -110,14 +102,15 @@ return [
|
||||
],
|
||||
// some feature flags:
|
||||
'feature_flags' => [
|
||||
'export' => true,
|
||||
'telemetry' => false,
|
||||
'webhooks' => true,
|
||||
'handle_debts' => true,
|
||||
'expression_engine' => true,
|
||||
'export' => true,
|
||||
'telemetry' => false,
|
||||
'webhooks' => true,
|
||||
'handle_debts' => true,
|
||||
'expression_engine' => true,
|
||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2024-09-16',
|
||||
'version' => 'develop/2024-10-07',
|
||||
'api_version' => '2.1.0',
|
||||
'db_version' => 24,
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ return [
|
||||
'default' => envNonEmpty('MAIL_MAILER', 'log'),
|
||||
|
||||
'mailers' => [
|
||||
'smtp' => [
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'host' => envNonEmpty('MAIL_HOST', 'smtp.mailtrap.io'),
|
||||
'port' => (int)env('MAIL_PORT', 2525),
|
||||
@@ -45,39 +45,41 @@ return [
|
||||
'timeout' => null,
|
||||
'verify_peer' => null !== env('MAIL_ENCRYPTION'),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'mailersend' => [
|
||||
'transport' => 'mailersend',
|
||||
],
|
||||
'ses' => [
|
||||
'transport' => 'ses',
|
||||
],
|
||||
|
||||
'mailgun' => [
|
||||
'mailgun' => [
|
||||
'transport' => 'mailgun',
|
||||
],
|
||||
|
||||
'mandrill' => [
|
||||
'mandrill' => [
|
||||
'transport' => 'mandrill',
|
||||
],
|
||||
|
||||
'postmark' => [
|
||||
'postmark' => [
|
||||
'transport' => 'postmark',
|
||||
],
|
||||
|
||||
'sendmail' => [
|
||||
'sendmail' => [
|
||||
'transport' => 'sendmail',
|
||||
'path' => envNonEmpty('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs'),
|
||||
],
|
||||
'log' => [
|
||||
'log' => [
|
||||
'transport' => 'log',
|
||||
'channel' => env('MAIL_LOG_CHANNEL', 'stack'),
|
||||
'level' => 'info',
|
||||
],
|
||||
'null' => [
|
||||
'null' => [
|
||||
'transport' => 'log',
|
||||
'channel' => env('MAIL_LOG_CHANNEL', 'stack'),
|
||||
'level' => 'notice',
|
||||
],
|
||||
|
||||
'array' => [
|
||||
'array' => [
|
||||
'transport' => 'array',
|
||||
],
|
||||
],
|
||||
|
||||
1414
package-lock.json
generated
1414
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,5 +5,8 @@
|
||||
"workspaces": [
|
||||
"resources/assets/v1",
|
||||
"resources/assets/v2"
|
||||
]
|
||||
],
|
||||
"devDependencies": {
|
||||
"postcss": "^8.4.47"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ function formatLabel(str, maxwidth) {
|
||||
}
|
||||
|
||||
var defaultChartOptions = {
|
||||
|
||||
elements: {
|
||||
line: {
|
||||
cubicInterpolationMode: 'monotone'
|
||||
@@ -158,4 +159,4 @@ var neutralDefaultPieOptions = {
|
||||
},
|
||||
maintainAspectRatio: true,
|
||||
responsive: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -337,6 +337,13 @@ function updateTriggerInput(selectList) {
|
||||
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
|
||||
createAutoComplete(inputResult, 'api/v1/autocomplete/tags');
|
||||
break;
|
||||
case 'bill_contains':
|
||||
case 'bill_ends':
|
||||
case 'bill_is':
|
||||
case 'bill_starts':
|
||||
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
|
||||
createAutoComplete(inputResult, 'api/v1/autocomplete/bills');
|
||||
break;
|
||||
case 'budget_is':
|
||||
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
|
||||
createAutoComplete(inputResult, 'api/v1/autocomplete/budgets');
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"prod": "mix --production"
|
||||
},
|
||||
"dependencies": {
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns": "^4.0.0",
|
||||
"stream-browserify": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -22,7 +22,7 @@
|
||||
"font-awesome": "^4.7.0",
|
||||
"jquery": "^3",
|
||||
"laravel-mix": "^6.0",
|
||||
"postcss": ">=8.4.45",
|
||||
"postcss": "^8.4.47",
|
||||
"uiv": "^1.4",
|
||||
"vue": "^2.7",
|
||||
"vue-i18n": "^8",
|
||||
|
||||
@@ -887,6 +887,7 @@ export default {
|
||||
|
||||
deleteTransaction: function (index, event) {
|
||||
event.preventDefault();
|
||||
console.log('Remove transaction.');
|
||||
this.transactions.splice(index, 1);
|
||||
},
|
||||
limitSourceType: function (type) {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"chart.js": "^4.4.0",
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"chartjs-chart-sankey": "^0.12.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns": "^4.0.0",
|
||||
"i18next": "^23.11.2",
|
||||
"i18next-chained-backend": "^4.6.2",
|
||||
"i18next-http-backend": "^2.4.2",
|
||||
|
||||
@@ -67,6 +67,18 @@
|
||||
{% endif %}
|
||||
{% if accounts.count() == 0 and page == 1 %}
|
||||
{% include 'partials.empty' with {objectType: objectType, type: 'accounts',route: route('accounts.create', [objectType])} %}
|
||||
|
||||
{% if inactiveCount > 0 %}
|
||||
<p class="text-center"><small>
|
||||
<em>
|
||||
<a href="{{ route('accounts.inactive.index', objectType) }}" class="text-muted">
|
||||
{{ trans_choice('firefly.inactive_account_link', inactiveCount) }}
|
||||
</a>
|
||||
</em>
|
||||
</small>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -85,12 +85,12 @@
|
||||
</a>
|
||||
</li>
|
||||
{% if true == featuringWebhooks %}
|
||||
<li class="{{ activeRoutePartial('webhooks') }}">
|
||||
<a href="{{ route('webhooks.index') }}">
|
||||
<span class="fa fa-angle-right fa-fw"></span>
|
||||
<span>{{ 'webhooks'|_ }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ activeRoutePartial('webhooks') }}">
|
||||
<a href="{{ route('webhooks.index') }}">
|
||||
<span class="fa fa-angle-right fa-fw"></span>
|
||||
<span>{{ 'webhooks'|_ }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="">
|
||||
<a href="#">
|
||||
@@ -230,10 +230,18 @@
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
{% if 'remote_user_guard' != authGuard or '' != logoutUri %}
|
||||
{% if 'web' == authGuard %}
|
||||
<li>
|
||||
<a href="{{ route('logout') }}" class="logout-link">
|
||||
<em class="fa fa-sign-out fa-fw"></em>
|
||||
<span>{{ 'logout'|_ }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'remote_user_guard' == authGuard and '' != logoutUrl %}
|
||||
<li>
|
||||
<a href="{{ logoutUrl }}">
|
||||
<em class="fa fa-sign-out fa-fw"></em>
|
||||
<span>{{ 'logout'|_ }}</span>
|
||||
</a>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<td class="hidden-xs">
|
||||
{% if budget_limit.spent != 0 %}
|
||||
<span class="fa fa-fw text-muted fa-info-circle firefly-info-button"
|
||||
data-location="budget-spent-amount" data-currency-id="{{ budget_limit.currency_id }}" data-budget-id="{{ budget.budget_id }}"></span>
|
||||
data-location="budget-spent-amount" data-currency-id="{{ budget_limit.currency_id }}" data-budget-id="{% if '' == budget.budget_id %}0{% else %}{{ budget.budget_id }}{% endif %}"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user