Compare commits

..

32 Commits

Author SHA1 Message Date
github-actions
bf04ca12c1 Auto commit for release 'develop' on 2025-02-22 2025-02-22 08:18:27 +01:00
James Cole
a4637debe9 Update changelog, fix log reference. 2025-02-22 08:07:52 +01:00
James Cole
48c1b525be Fix #9874 2025-02-22 08:03:42 +01:00
github-actions
56470bfbba Auto commit for release 'develop' on 2025-02-21 2025-02-21 08:32:55 +01:00
James Cole
0f732ca874 Merge pull request #9880 from josegonzalez/patch-1
fix: ignore the Procfile when building the docker image
2025-02-21 08:06:04 +01:00
James Cole
e452ba938d Update changelog. 2025-02-21 06:20:17 +01:00
James Cole
9921c5a925 Fix #9882 2025-02-21 06:18:11 +01:00
Jose Diaz-Gonzalez
58fab75681 fix: ignore the Procfile when building the docker image
The Procfile is heroku-specific, causing issues on platforms which respect it when specifying processes to run for docker image or dockerfile based deploys.

Closes #9833

Signed-off-by: Jose Diaz-Gonzalez <email@josediazgonzalez.com>
2025-02-20 14:51:04 -05:00
Sander Dorigo
54990308f6 fix type error 2025-02-20 12:58:38 +01:00
github-actions
f95758ff47 Auto commit for release 'develop' on 2025-02-20 2025-02-20 08:11:36 +01:00
James Cole
8d830e178f Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-02-20 08:08:18 +01:00
James Cole
334a521ca1 Better fix for nullpointer. 2025-02-20 08:08:07 +01:00
github-actions
12629a1955 Auto commit for release 'develop' on 2025-02-20 2025-02-20 08:00:12 +01:00
James Cole
2e3669a32f Fix #9871 2025-02-20 07:43:32 +01:00
James Cole
ea337607c4 Fix #9868 2025-02-20 07:30:30 +01:00
James Cole
f7f317a3b2 Fix #9863 2025-02-20 07:28:24 +01:00
James Cole
adbf6defe5 Catch nullpointer. 2025-02-20 06:21:29 +01:00
github-actions
e0709f2975 Auto commit for release 'develop' on 2025-02-19 2025-02-19 09:14:18 +01:00
James Cole
30007b05cb Fix #9861 2025-02-19 06:37:40 +01:00
James Cole
13fc7f0d8d Fix #9862 2025-02-19 06:21:27 +01:00
github-actions
7c85138115 Auto commit for release 'v6.2.7' on 2025-02-18 2025-02-18 19:52:25 +01:00
James Cole
2c25f65f7f Expand changelog. 2025-02-18 19:46:01 +01:00
github-actions
7eaba962e8 Auto commit for release 'develop' on 2025-02-18 2025-02-18 15:17:06 +01:00
Sander Dorigo
7c38393cde merge 2025-02-18 15:12:42 +01:00
Sander Dorigo
153fd2ae74 fix missing var 2025-02-18 15:06:51 +01:00
github-actions
c0204c810c Auto commit for release 'develop' on 2025-02-18 2025-02-18 10:31:05 +01:00
Sander Dorigo
944c107e26 Add enrichment 2025-02-18 10:26:36 +01:00
Sander Dorigo
18e05c06fd Catch nullpointer 2025-02-18 10:24:23 +01:00
Sander Dorigo
fb79dbf17c Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-02-18 10:22:42 +01:00
github-actions
31a8163c61 Auto commit for release 'develop' on 2025-02-17 2025-02-17 16:52:58 +01:00
Sander Dorigo
8bcd729250 remove unused script 2025-02-17 16:49:00 +01:00
Sander Dorigo
80c4e69528 Fix #9848 2025-02-17 13:43:43 +01:00
30 changed files with 385 additions and 319 deletions

View File

@@ -406,16 +406,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.69.0",
"version": "v3.69.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "630a59448c00729bc235d5e95cfedefeaca37523"
"reference": "13b0c0eede38c11cd674b080f2b485d0f14ffa9f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/630a59448c00729bc235d5e95cfedefeaca37523",
"reference": "630a59448c00729bc235d5e95cfedefeaca37523",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/13b0c0eede38c11cd674b080f2b485d0f14ffa9f",
"reference": "13b0c0eede38c11cd674b080f2b485d0f14ffa9f",
"shasum": ""
},
"require": {
@@ -497,7 +497,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.69.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.69.1"
},
"funding": [
{
@@ -505,7 +505,7 @@
"type": "github"
}
],
"time": "2025-02-14T16:19:23+00:00"
"time": "2025-02-18T23:57:43+00:00"
},
{
"name": "psr/container",

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
Procfile

9
.gitignore vendored
View File

@@ -14,7 +14,16 @@ public/build
# ignore v1 build files
resources/assets/v1/node_modules
resources/assets/v1/build
public/v1/js/app.js*
public/v1/js/app_vue.js*
public/v1/js/create*
public/v1/js/edit*
public/v1/js/profile*
public/v1/js/administrations
public/v1/js/exchange-rates
public/v1/js/webhooks
# ignore v2 build files
resources/assets/v2/node_modules
resources/assets/v2/build
public/v2/i18n

View File

@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2025
- Jose Diaz-Gonzalez
- SoftBrix
## 2024

View File

@@ -90,6 +90,7 @@ class StoreController extends Controller
$data['user'] = auth()->user();
$data['user_group'] = $this->userGroup;
Log::channel('audit')->info('Store new transaction over API.', $data);
try {

View File

@@ -65,25 +65,6 @@ class StoreRequest extends FormRequest
return $data;
}
private function parseAccounts(mixed $array): array
{
if (!is_array($array)) {
return [];
}
$return = [];
foreach ($array as $entry) {
if (!is_array($entry)) {
continue;
}
$return[] = [
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
];
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/

View File

@@ -25,8 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Rules\IsAssetAccountId;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
use FireflyIII\Rules\LessThanPiggyTarget;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -45,20 +45,23 @@ class UpdateRequest extends FormRequest
*/
public function getAll(): array
{
$fields = [
'name' => ['name', 'convertString'],
'account_id' => ['account_id', 'convertInteger'],
'targetamount' => ['target_amount', 'convertString'],
'current_amount' => ['current_amount', 'convertString'],
'startdate' => ['start_date', 'convertDateTime'],
'targetdate' => ['target_date', 'convertDateTime'],
'notes' => ['notes', 'stringWithNewlines'],
'order' => ['order', 'convertInteger'],
'object_group_title' => ['object_group_title', 'convertString'],
'object_group_id' => ['object_group_id', 'convertInteger'],
$fields = [
'name' => ['name', 'convertString'],
'target_amount' => ['target_amount', 'convertString'],
'start_date' => ['start_date', 'convertDateTime'],
'target_date' => ['target_date', 'convertDateTime'],
'notes' => ['notes', 'stringWithNewlines'],
'order' => ['order', 'convertInteger'],
'object_group_title' => ['object_group_title', 'convertString'],
'object_group_id' => ['object_group_id', 'convertInteger'],
'transaction_currency_code' => ['transaction_currency_code', 'convertString'],
'transaction_currency_id' => ['transaction_currency_id', 'convertInteger'],
];
return $this->getAllData($fields);
$result = $this->getAllData($fields);
$result['accounts'] = $this->parseAccounts($this->get('accounts'));
return $result;
}
/**
@@ -70,13 +73,20 @@ class UpdateRequest extends FormRequest
$piggyBank = $this->route()->parameter('piggyBank');
return [
'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id,
'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()],
'target_amount' => ['nullable', new IsValidPositiveAmount()],
'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
'account_id' => ['belongsToUser:accounts', new IsAssetAccountId()],
'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id,
'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()],
'target_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
'accounts' => 'required',
'accounts.*' => 'array|required',
'accounts.*.account_id' => ['required', 'numeric', 'belongsToUser:accounts,id'],
'accounts.*.current_amount' => ['numeric', new IsValidZeroOrMoreAmount()],
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
'object_group_title' => ['min:1', 'max:255'],
'transaction_currency_id' => 'exists:transaction_currencies,id|nullable',
'transaction_currency_code' => 'exists:transaction_currencies,code|nullable',
];
}
}

View File

@@ -73,6 +73,7 @@ class StoreController extends Controller
$userGroup = $request->getUserGroup();
$data['user_group'] = $userGroup;
// overrule user group and see where we end up.
// what happens when we refer to a budget that is not in this user group?

View File

@@ -106,7 +106,7 @@ class ExportsData extends Command
$exporter->setExportTags($options['export']['tags']);
$exporter->setExportRecurring($options['export']['recurring']);
$exporter->setExportRules($options['export']['rules']);
$exporter->setExportBills($options['export']['subscriptions']);
$exporter->setExportBills($options['export']['bills']);
$exporter->setExportPiggies($options['export']['piggies']);
$data = $exporter->export();
if (0 === count($data)) {

View File

@@ -238,7 +238,8 @@ class UpgradesToGroups extends Command
return [
'type' => strtolower($journal->transactionType->type),
'date' => $journal->date,
'user' => $journal->user_id,
'user' => $journal->user,
'user_group' => $journal->user->userGroup,
'currency_id' => $transaction->transaction_currency_id,
'foreign_currency_id' => $transaction->foreign_currency_id,
'amount' => $transaction->amount,

View File

@@ -229,7 +229,8 @@ class ReconcileController extends Controller
'group_title' => null,
'transactions' => [
[
'user' => auth()->user()->id,
'user' => auth()->user(),
'user_group' => auth()->user()->userGroup,
'type' => strtolower(TransactionTypeEnum::RECONCILIATION->value),
'date' => $end,
'order' => 0,

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use Illuminate\Contracts\View\Factory;
@@ -81,25 +82,25 @@ class IndexController extends Controller
{
$this->cleanupObjectGroups();
$this->piggyRepos->resetOrder();
$collection = $this->piggyRepos->getPiggyBanks();
$collection = $this->piggyRepos->getPiggyBanks();
/** @var Carbon $end */
$end = session('end', today(config('app.timezone'))->endOfMonth());
$end = session('end', today(config('app.timezone'))->endOfMonth());
// transform piggies using the transformer:
$parameters = new ParameterBag();
$parameters->set('end', $end);
// $parameters = new ParameterBag();
// $parameters->set('end', $end);
/** @var AccountTransformer $accountTransformer */
$accountTransformer = app(AccountTransformer::class);
$accountTransformer->setParameters($parameters);
// /** @var AccountTransformer $accountTransformer */
// $accountTransformer = app(AccountTransformer::class);
// $accountTransformer->setParameters($parameters);
// data
$piggyBanks = $this->groupPiggyBanks($collection);
$accounts = $this->collectAccounts($collection);
$accounts = $this->mergeAccountsAndPiggies($piggyBanks, $accounts);
$piggyBanks = $this->makeSums($piggyBanks);
$piggyBanks = $this->groupPiggyBanks($collection);
$accounts = $this->collectAccounts($collection);
$accounts = $this->mergeAccountsAndPiggies($piggyBanks, $accounts);
$piggyBanks = $this->makeSums($piggyBanks);
ksort($piggyBanks);
@@ -144,6 +145,11 @@ class IndexController extends Controller
$accountTransformer = app(AccountTransformer::class);
$accountTransformer->setParameters($parameters);
// enrich each account.
$enrichment = new AccountEnrichment();
$enrichment->setUser(auth()->user());
$enrichment->setConvertToNative($this->convertToNative);
$enrichment->setNative($this->defaultCurrency);
$return = [];
/** @var PiggyBank $piggy */
@@ -152,6 +158,7 @@ class IndexController extends Controller
/** @var Account $account */
foreach ($accounts as $account) {
$account = $enrichment->enrichSingle($account);
$array = $accountTransformer->transform($account);
$accountId = (int) $array['id'];
if (!array_key_exists($accountId, $return)) {

View File

@@ -103,7 +103,7 @@ class ShowController extends Controller
foreach (array_keys($groupArray['transactions']) as $index) {
$groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects(
$groupArray['transactions'][$index]['transaction_journal_id']
(int) $groupArray['transactions'][$index]['transaction_journal_id']
);
}

View File

@@ -498,6 +498,8 @@ class AccountRepository implements AccountRepositoryInterface
}
$query->orderBy('accounts.active', 'DESC');
$query->orderBy('accounts.name', 'ASC');
$query->orderBy('accounts.account_type_id', 'ASC');
$query->orderBy('accounts.id', 'ASC');
}
return $query->get(['accounts.*']);

View File

@@ -222,7 +222,8 @@ trait ModifiesPiggyBanks
// update the accounts
$factory = new PiggyBankFactory();
$factory->user = $this->user;
$factory->linkToAccountIds($piggyBank, $data['accounts']);
$factory->linkToAccountIds($piggyBank, $data['accounts'] ?? []);
// if the piggy bank is now smaller than the sum of the money saved,
@@ -233,8 +234,8 @@ trait ModifiesPiggyBanks
$difference = bcsub($piggyBank->target_amount, $currentAmount);
// an amount will be removed, create "negative" event:
Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
event(new ChangedAmount($piggyBank, $difference, null, null));
// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
// event(new ChangedAmount($piggyBank, $difference, null, null));
// question is, from which account(s) to remove the difference?
// solution: just start from the top until there is no more money left to remove.

View File

@@ -361,6 +361,8 @@ class AccountRepository implements AccountRepositoryInterface
}
$query->orderBy('accounts.order', 'ASC');
$query->orderBy('accounts.name', 'ASC');
$query->orderBy('accounts.account_type_id', 'ASC');
$query->orderBy('accounts.id', 'ASC');
}
return $query->get(['accounts.*']);

View File

@@ -31,6 +31,7 @@ use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
/**
* Class RemoteUserGuard
@@ -48,7 +49,7 @@ class RemoteUserGuard implements Guard
{
/** @var null|Request $request */
$request = $app->get('request');
app('log')->debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
$this->application = $app;
$this->provider = $provider;
$this->user = null;
@@ -56,9 +57,9 @@ class RemoteUserGuard implements Guard
public function authenticate(): void
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
if (null !== $this->user) {
app('log')->debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email));
Log::debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email));
return;
}
@@ -67,17 +68,17 @@ class RemoteUserGuard implements Guard
$userID = request()->server($header) ?? null;
if (function_exists('apache_request_headers')) {
app('log')->debug('Use apache_request_headers to find user ID.');
Log::debug('Use apache_request_headers to find user ID.');
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null;
}
if (null === $userID || '' === $userID) {
app('log')->error(sprintf('No user in header "%s".', $header));
Log::error(sprintf('No user in header "%s".', $header));
throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
}
app('log')->debug(sprintf('User ID found in header is "%s"', $userID));
Log::debug(sprintf('User ID found in header is "%s"', $userID));
/** @var User $retrievedUser */
$retrievedUser = $this->provider->retrieveById($userID);
@@ -98,30 +99,30 @@ class RemoteUserGuard implements Guard
}
}
app('log')->debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email));
Log::debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email));
$this->user = $retrievedUser;
}
public function guest(): bool
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
return !$this->check();
}
public function check(): bool
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
return null !== $this->user();
}
public function user(): ?User
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
$user = $this->user;
if (null === $user) {
app('log')->debug('User is NULL');
Log::debug('User is NULL');
return null;
}
@@ -131,7 +132,7 @@ class RemoteUserGuard implements Guard
public function hasUser(): bool
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
throw new FireflyException('Did not implement RemoteUserGuard::hasUser()');
}
@@ -141,20 +142,20 @@ class RemoteUserGuard implements Guard
*/
public function id(): null|int|string
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
return $this->user?->id;
}
public function setUser(null|Authenticatable|User $user): void // @phpstan-ignore-line
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
if ($user instanceof User) {
$this->user = $user;
return;
}
app('log')->error(sprintf('Did not set user at %s', __METHOD__));
Log::error(sprintf('Did not set user at %s', __METHOD__));
}
/**
@@ -164,14 +165,14 @@ class RemoteUserGuard implements Guard
*/
public function validate(array $credentials = []): bool
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
throw new FireflyException('Did not implement RemoteUserGuard::validate()');
}
public function viaRemember(): bool
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
Log::debug(sprintf('Now at %s', __METHOD__));
return false;
}

View File

@@ -117,30 +117,6 @@ class AccountEnrichment implements EnrichmentInterface
$this->collectNotes();
$this->collectLocations();
$this->collectOpeningBalances();
// $this->default = app('amount')->getNativeCurrency();
// $this->currencies = [];
// $this->balances = [];
// $this->objectGroups = [];
// $this->grouped = [];
//
// // do everything here:
// $this->getLastActivity();
// $this->collectAccountTypes();
// $this->collectMetaData();
// $this->getMetaBalances();
// $this->getObjectGroups();
// $this->collection->transform(function (Account $account) {
// $account->user_array = ['id' => 1, 'bla bla' => 'bla'];
// $account->balances = collect([
// ['balance_id' => 1, 'balance' => 5],
// ['balance_id' => 2, 'balance' => 5],
// ['balance_id' => 3, 'balance' => 5],
// ]);
//
// return $account;
// });
$this->appendCollectedData();
return $this->collection;
@@ -258,7 +234,7 @@ class AccountEnrichment implements EnrichmentInterface
private function collectMetaData(): void
{
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
->whereIn('account_id', $this->accountIds)
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray()
;
@@ -270,10 +246,11 @@ class AccountEnrichment implements EnrichmentInterface
$this->currencies[(int) $entry['data']] = true;
}
}
$currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get();
$currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get();
foreach ($currencies as $currency) {
$this->currencies[(int) $currency->id] = $currency;
}
$this->currencies[0] = $this->native;
foreach ($this->currencies as $id => $currency) {
if (true === $currency) {
throw new FireflyException(sprintf('Currency #%d not found.', $id));

View File

@@ -72,20 +72,32 @@ class Preferences
public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference
{
Log::debug(sprintf('getForUser(#%d, "%s")', $user->id, $name));
// don't care about user group ID, except for some specific preferences.
$userGroupId = $this->getUserGroupId($user, $name);
$preference = Preference::where('user_group_id', $userGroupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']);
$query = Preference::where('user_id', $user->id)->where('name', $name);
if (null !== $userGroupId) {
Log::debug('Include user group ID in query');
$query->where('user_group_id', $userGroupId);
}
$preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']);
if (null !== $preference && null === $preference->data) {
$preference->delete();
$preference = null;
Log::debug('Removed empty preference.');
}
if (null !== $preference) {
Log::debug(sprintf('Found preference #%d for user #%d: %s', $preference->id, $user->id, $name));
return $preference;
}
// no preference found and default is null:
if (null === $default) {
Log::debug('Return NULL, create no preference.');
// return NULL
return null;
}
@@ -124,35 +136,40 @@ class Preferences
public function setForUser(User $user, string $name, null|array|bool|int|string $value): Preference
{
$fullName = sprintf('preference%s%s', $user->id, $name);
$groupId = $this->getUserGroupId($user, $name);
$groupId = 0 === (int) $groupId ? null : (int) $groupId;
$fullName = sprintf('preference%s%s', $user->id, $name);
$userGroupId = $this->getUserGroupId($user, $name);
$userGroupId = 0 === (int) $userGroupId ? null : (int) $userGroupId;
Cache::forget($fullName);
/** @var null|Preference $pref */
$pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']);
$query = Preference::where('user_id', $user->id)->where('name', $name);
if (null !== $userGroupId) {
Log::debug('Include user group ID in query');
$query->where('user_group_id', $userGroupId);
}
if (null !== $pref && null === $value) {
$pref->delete();
$preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']);
if (null !== $preference && null === $value) {
$preference->delete();
return new Preference();
}
if (null === $value) {
return new Preference();
}
if (null === $pref) {
$pref = new Preference();
$pref->user_id = (int) $user->id;
$pref->user_group_id = $groupId;
$pref->name = $name;
if (null === $preference) {
$preference = new Preference();
$preference->user_id = (int) $user->id;
$preference->user_group_id = $userGroupId;
$preference->name = $name;
}
$pref->data = $value;
$pref->save();
Cache::forever($fullName, $pref);
$preference->data = $value;
$preference->save();
Cache::forever($fullName, $preference);
return $pref;
return $preference;
}
public function beginsWith(User $user, string $search): Collection

View File

@@ -390,6 +390,25 @@ trait ConvertsDataTypes
return (int) $string;
}
protected function parseAccounts(mixed $array): array
{
if (!is_array($array)) {
return [];
}
$return = [];
foreach ($array as $entry) {
if (!is_array($entry)) {
continue;
}
$return[] = [
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
];
}
return $return;
}
protected function floatFromValue(?string $string): ?float
{
if (null === $string) {

View File

@@ -62,6 +62,10 @@ class AccountTransformer extends AbstractTransformer
*/
public function transform(Account $account): array
{
if (null === $account->meta) {
$account->meta = [];
}
// get account type:
$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $account->full_account_type));
$liabilityType = (string) config(sprintf('firefly.shortLiabilityNameByFullName.%s', $account->full_account_type));
@@ -88,7 +92,7 @@ class AccountTransformer extends AbstractTransformer
$decimalPlaces = (int) $account->meta['currency']?->decimal_places;
$decimalPlaces = 0 === $decimalPlaces ? 2 : $decimalPlaces;
$openingBalance = Steam::bcround($openingBalance, $decimalPlaces);
$includeNetWorth = '0' !== ($account->meta['include_net_worth'] ?? null);
$includeNetWorth = 1 === (int) ($account->meta['include_net_worth'] ?? 0);
$longitude = $account->meta['location']['longitude'] ?? null;
$latitude = $account->meta['location']['latitude'] ?? null;
$zoomLevel = $account->meta['location']['zoom_level'] ?? null;

View File

@@ -131,7 +131,7 @@ class TransactionGroupTransformer extends AbstractTransformer
return [
'user' => (string) $transaction['user_id'],
'transaction_journal_id' => $transaction['transaction_journal_id'],
'transaction_journal_id' => (string) $transaction['transaction_journal_id'],
'type' => strtolower($type),
'date' => $transaction['date']->toAtomString(),
'order' => $transaction['order'],
@@ -320,17 +320,17 @@ class TransactionGroupTransformer extends AbstractTransformer
return [
'user' => $journal->user_id,
'transaction_journal_id' => $journal->id,
'transaction_journal_id' => (string) $journal->id,
'type' => strtolower($type),
'date' => $journal->date->toAtomString(),
'order' => $journal->order,
'currency_id' => $currency->id,
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'foreign_currency_id' => $foreignCurrency['id'],
'foreign_currency_id' => (string) $foreignCurrency['id'],
'foreign_currency_code' => $foreignCurrency['code'],
'foreign_currency_symbol' => $foreignCurrency['symbol'],
'foreign_currency_decimal_places' => $foreignCurrency['decimal_places'],
@@ -340,23 +340,23 @@ class TransactionGroupTransformer extends AbstractTransformer
'description' => $journal->description,
'source_id' => $source->account_id,
'source_id' => (string) $source->account_id,
'source_name' => $source->account->name,
'source_iban' => $source->account->iban,
'source_type' => $source->account->accountType->type,
'destination_id' => $destination->account_id,
'destination_id' => (string) $destination->account_id,
'destination_name' => $destination->account->name,
'destination_iban' => $destination->account->iban,
'destination_type' => $destination->account->accountType->type,
'budget_id' => $budget['id'],
'budget_id' => (string) $budget['id'],
'budget_name' => $budget['name'],
'category_id' => $category['id'],
'category_id' => (string) $category['id'],
'category_name' => $category['name'],
'bill_id' => $bill['id'],
'bill_id' => (string) $bill['id'],
'bill_name' => $bill['name'],
'reconciled' => $source->reconciled,

View File

@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 6.2.8 - 2025-02-22
### Fixed
- [Issue 9861](https://github.com/firefly-iii/firefly-iii/issues/9861) (lower piggy amount when full creates double audit log entry) reported by @4e868df3
- [Issue 9862](https://github.com/firefly-iii/firefly-iii/issues/9862) (Can't retrieve all accounts with the same name via API) reported by @Toshik1978
- [Issue 9863](https://github.com/firefly-iii/firefly-iii/issues/9863) (User preferences reset after restart) reported by @mico28
- [Issue 9868](https://github.com/firefly-iii/firefly-iii/issues/9868) (API: `TransactionSplit` -> `transaction_journal_id` returns int, not String) reported by @dreautall
- [Issue 9871](https://github.com/firefly-iii/firefly-iii/issues/9871) (include net worth is ignored in the API - from PICO developer) reported by @fate8383
- [Issue 9882](https://github.com/firefly-iii/firefly-iii/issues/9882) (Reconciliation bug on Docker instance) reported by @benjaminteyssier
- [Issue 9884](https://github.com/firefly-iii/firefly-iii/issues/9884) (Data import, currency #0 not found) reported by @ragnarkarlsson
- [Issue 9887](https://github.com/firefly-iii/firefly-iii/issues/9887) (Creating a Liability Account Throws TypeError in TransactionJournalFactory::setUser()) reported by @mikeashi
## 6.2.7 - 2025-02-19
### Changed
- Optimised Account and Transaction API endpoints, should be a lot faster
- Optimized account deletion, should be a lot faster
### Fixed
- [Issue 9803](https://github.com/firefly-iii/firefly-iii/issues/9803) (Left to spend - All negativ after update.) reported by @nedsined
- [Issue 9835](https://github.com/firefly-iii/firefly-iii/issues/9835) (Failed to create transaction in recurring transactions on 6.2.6) reported by @hhl5350
- [Issue 9842](https://github.com/firefly-iii/firefly-iii/issues/9842) (Net worth on dashboard does not go up to the end of month for the current month) reported by @standingduck3
- [Issue 9848](https://github.com/firefly-iii/firefly-iii/issues/9848) (Failed to export accounts data) reported by @Jaeger87
- [Issue 9855](https://github.com/firefly-iii/firefly-iii/issues/9855) (Demo Website not working) reported by @xfarrow
## 6.2.6 - 2025-02-13
### Fixed

309
composer.lock generated
View File

@@ -1874,16 +1874,16 @@
},
{
"name": "laravel/framework",
"version": "v11.42.1",
"version": "v11.43.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "ff392f42f6c55cc774ce75553a11c6b031da67f8"
"reference": "99d1573698abc42222f04d25fcd5b213d0eedf21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/ff392f42f6c55cc774ce75553a11c6b031da67f8",
"reference": "ff392f42f6c55cc774ce75553a11c6b031da67f8",
"url": "https://api.github.com/repos/laravel/framework/zipball/99d1573698abc42222f04d25fcd5b213d0eedf21",
"reference": "99d1573698abc42222f04d25fcd5b213d0eedf21",
"shasum": ""
},
"require": {
@@ -2085,7 +2085,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-02-12T20:58:18+00:00"
"time": "2025-02-19T21:53:48+00:00"
},
{
"name": "laravel/passport",
@@ -3703,16 +3703,16 @@
},
{
"name": "nesbot/carbon",
"version": "3.8.5",
"version": "3.8.6",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
"reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4"
"reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/b1a53a27898639579a67de42e8ced5d5386aa9a4",
"reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd",
"reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd",
"shasum": ""
},
"require": {
@@ -3805,7 +3805,7 @@
"type": "tidelift"
}
],
"time": "2025-02-11T16:28:45+00:00"
"time": "2025-02-20T17:33:38+00:00"
},
{
"name": "nette/schema",
@@ -6113,16 +6113,16 @@
},
{
"name": "spatie/ignition",
"version": "1.15.0",
"version": "1.15.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/ignition.git",
"reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2"
"reference": "31f314153020aee5af3537e507fef892ffbf8c85"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/ignition/zipball/e3a68e137371e1eb9edc7f78ffa733f3b98991d2",
"reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2",
"url": "https://api.github.com/repos/spatie/ignition/zipball/31f314153020aee5af3537e507fef892ffbf8c85",
"reference": "31f314153020aee5af3537e507fef892ffbf8c85",
"shasum": ""
},
"require": {
@@ -6135,7 +6135,7 @@
"symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"require-dev": {
"illuminate/cache": "^9.52|^10.0|^11.0",
"illuminate/cache": "^9.52|^10.0|^11.0|^12.0",
"mockery/mockery": "^1.4",
"pestphp/pest": "^1.20|^2.0",
"phpstan/extension-installer": "^1.1",
@@ -6192,7 +6192,7 @@
"type": "github"
}
],
"time": "2024-06-12T14:55:22+00:00"
"time": "2025-02-21T14:31:39+00:00"
},
{
"name": "spatie/laravel-html",
@@ -6274,23 +6274,23 @@
},
{
"name": "spatie/laravel-ignition",
"version": "2.9.0",
"version": "2.9.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-ignition.git",
"reference": "62042df15314b829d0f26e02108f559018e2aad0"
"reference": "1baee07216d6748ebd3a65ba97381b051838707a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/62042df15314b829d0f26e02108f559018e2aad0",
"reference": "62042df15314b829d0f26e02108f559018e2aad0",
"url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1baee07216d6748ebd3a65ba97381b051838707a",
"reference": "1baee07216d6748ebd3a65ba97381b051838707a",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"illuminate/support": "^10.0|^11.0",
"illuminate/support": "^10.0|^11.0|^12.0",
"php": "^8.1",
"spatie/ignition": "^1.15",
"symfony/console": "^6.2.3|^7.0",
@@ -6299,12 +6299,12 @@
"require-dev": {
"livewire/livewire": "^2.11|^3.3.5",
"mockery/mockery": "^1.5.1",
"openai-php/client": "^0.8.1",
"orchestra/testbench": "8.22.3|^9.0",
"pestphp/pest": "^2.34",
"openai-php/client": "^0.8.1|^0.10",
"orchestra/testbench": "8.22.3|^9.0|^10.0",
"pestphp/pest": "^2.34|^3.7",
"phpstan/extension-installer": "^1.3.1",
"phpstan/phpstan-deprecation-rules": "^1.1.1",
"phpstan/phpstan-phpunit": "^1.3.16",
"phpstan/phpstan-deprecation-rules": "^1.1.1|^2.0",
"phpstan/phpstan-phpunit": "^1.3.16|^2.0",
"vlucas/phpdotenv": "^5.5"
},
"suggest": {
@@ -6361,7 +6361,7 @@
"type": "github"
}
],
"time": "2024-12-02T08:43:31+00:00"
"time": "2025-02-20T13:13:55+00:00"
},
{
"name": "spatie/laravel-package-tools",
@@ -10033,30 +10033,30 @@
"packages-dev": [
{
"name": "barryvdh/laravel-debugbar",
"version": "v3.14.10",
"version": "v3.15.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "56b9bd235e3fe62e250124804009ce5bab97cc63"
"reference": "77cca4a1162d45e1fe64e7a71b4a3031656b6c86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/56b9bd235e3fe62e250124804009ce5bab97cc63",
"reference": "56b9bd235e3fe62e250124804009ce5bab97cc63",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/77cca4a1162d45e1fe64e7a71b4a3031656b6c86",
"reference": "77cca4a1162d45e1fe64e7a71b4a3031656b6c86",
"shasum": ""
},
"require": {
"illuminate/routing": "^9|^10|^11",
"illuminate/session": "^9|^10|^11",
"illuminate/support": "^9|^10|^11",
"maximebf/debugbar": "~1.23.0",
"php": "^8.0",
"illuminate/routing": "^9|^10|^11|^12",
"illuminate/session": "^9|^10|^11|^12",
"illuminate/support": "^9|^10|^11|^12",
"php": "^8.1",
"php-debugbar/php-debugbar": "~2.1.1",
"symfony/finder": "^6|^7"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
"orchestra/testbench-dusk": "^5|^6|^7|^8|^9",
"phpunit/phpunit": "^9.6|^10.5",
"orchestra/testbench-dusk": "^7|^8|^9|^10",
"phpunit/phpunit": "^9.5.10|^10|^11",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
@@ -10070,7 +10070,7 @@
]
},
"branch-alias": {
"dev-master": "3.14-dev"
"dev-master": "3.15-dev"
}
},
"autoload": {
@@ -10095,13 +10095,14 @@
"keywords": [
"debug",
"debugbar",
"dev",
"laravel",
"profiler",
"webprofiler"
],
"support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.10"
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.15.0"
},
"funding": [
{
@@ -10113,40 +10114,40 @@
"type": "github"
}
],
"time": "2024-12-23T10:10:42+00:00"
"time": "2025-02-21T15:00:44+00:00"
},
{
"name": "barryvdh/laravel-ide-helper",
"version": "v3.5.4",
"version": "v3.5.5",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-ide-helper.git",
"reference": "980a87e250fc2a7558bc46e07f61c7594500ea53"
"reference": "8d441ec99f8612b942b55f5183151d91591b618a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/980a87e250fc2a7558bc46e07f61c7594500ea53",
"reference": "980a87e250fc2a7558bc46e07f61c7594500ea53",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/8d441ec99f8612b942b55f5183151d91591b618a",
"reference": "8d441ec99f8612b942b55f5183151d91591b618a",
"shasum": ""
},
"require": {
"barryvdh/reflection-docblock": "^2.3",
"composer/class-map-generator": "^1.0",
"ext-json": "*",
"illuminate/console": "^11.15",
"illuminate/database": "^11.15",
"illuminate/filesystem": "^11.15",
"illuminate/support": "^11.15",
"illuminate/console": "^11.15 || ^12",
"illuminate/database": "^11.15 || ^12",
"illuminate/filesystem": "^11.15 || ^12",
"illuminate/support": "^11.15 || ^12",
"php": "^8.2"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"friendsofphp/php-cs-fixer": "^3",
"illuminate/config": "^11.15",
"illuminate/view": "^11.15",
"illuminate/config": "^11.15 || ^12",
"illuminate/view": "^11.15 || ^12",
"mockery/mockery": "^1.4",
"orchestra/testbench": "^9.2",
"phpunit/phpunit": "^10.5",
"orchestra/testbench": "^9.2 || ^10",
"phpunit/phpunit": "^10.5 || ^11.5.3",
"spatie/phpunit-snapshot-assertions": "^4 || ^5",
"vimeo/psalm": "^5.4",
"vlucas/phpdotenv": "^5"
@@ -10195,7 +10196,7 @@
],
"support": {
"issues": "https://github.com/barryvdh/laravel-ide-helper/issues",
"source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.5.4"
"source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.5.5"
},
"funding": [
{
@@ -10207,7 +10208,7 @@
"type": "github"
}
],
"time": "2025-01-14T09:07:00+00:00"
"time": "2025-02-11T13:59:46+00:00"
},
{
"name": "barryvdh/reflection-docblock",
@@ -10587,40 +10588,40 @@
},
{
"name": "larastan/larastan",
"version": "v3.0.4",
"version": "v3.1.0",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
"reference": "b394eba5805727423071fac9b53ea50dd7e920f4"
"reference": "dbb2dc20e5c8e1ed3ff289054e1955f269187312"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/larastan/larastan/zipball/b394eba5805727423071fac9b53ea50dd7e920f4",
"reference": "b394eba5805727423071fac9b53ea50dd7e920f4",
"url": "https://api.github.com/repos/larastan/larastan/zipball/dbb2dc20e5c8e1ed3ff289054e1955f269187312",
"reference": "dbb2dc20e5c8e1ed3ff289054e1955f269187312",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/console": "^11.15.0",
"illuminate/container": "^11.15.0",
"illuminate/contracts": "^11.15.0",
"illuminate/database": "^11.15.0",
"illuminate/http": "^11.15.0",
"illuminate/pipeline": "^11.15.0",
"illuminate/support": "^11.15.0",
"illuminate/console": "^11.15.0 || ^12.0",
"illuminate/container": "^11.15.0 || ^12.0",
"illuminate/contracts": "^11.15.0 || ^12.0",
"illuminate/database": "^11.15.0 || ^12.0",
"illuminate/http": "^11.15.0 || ^12.0",
"illuminate/pipeline": "^11.15.0 || ^12.0",
"illuminate/support": "^11.15.0 || ^12.0",
"php": "^8.2",
"phpmyadmin/sql-parser": "^5.9.0",
"phpstan/phpstan": "^2.1.3"
},
"require-dev": {
"doctrine/coding-standard": "^12.0",
"laravel/framework": "^11.15.0",
"laravel/framework": "^11.15.0 || ^12.0",
"mockery/mockery": "^1.6",
"nikic/php-parser": "^5.3",
"orchestra/canvas": "^v9.1.3",
"orchestra/testbench-core": "^9.5.2",
"orchestra/canvas": "^v9.1.3 || ^10.0",
"orchestra/testbench-core": "^9.5.2 || ^10.0",
"phpstan/phpstan-deprecation-rules": "^2.0.0",
"phpunit/phpunit": "^10.5.16"
"phpunit/phpunit": "^10.5.35 || ^11.3.6"
},
"suggest": {
"orchestra/testbench": "Using Larastan for analysing a package needs Testbench"
@@ -10633,7 +10634,7 @@
]
},
"branch-alias": {
"dev-master": "2.0-dev"
"dev-master": "3.0-dev"
}
},
"autoload": {
@@ -10668,7 +10669,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
"source": "https://github.com/larastan/larastan/tree/v3.0.4"
"source": "https://github.com/larastan/larastan/tree/v3.1.0"
},
"funding": [
{
@@ -10676,7 +10677,7 @@
"type": "github"
}
],
"time": "2025-02-06T21:03:36+00:00"
"time": "2025-02-20T15:25:15+00:00"
},
{
"name": "laravel-json-api/testing",
@@ -10743,74 +10744,6 @@
},
"time": "2024-11-30T16:50:45+00:00"
},
{
"name": "maximebf/debugbar",
"version": "v1.23.6",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "4b3d5f1afe09a7db5a9d3282890f49f6176d6542"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/4b3d5f1afe09a7db5a9d3282890f49f6176d6542",
"reference": "4b3d5f1afe09a7db5a9d3282890f49f6176d6542",
"shasum": ""
},
"require": {
"php": "^7.2|^8",
"psr/log": "^1|^2|^3",
"symfony/var-dumper": "^4|^5|^6|^7"
},
"require-dev": {
"dbrekelmans/bdi": "^1",
"phpunit/phpunit": "^8|^9",
"symfony/panther": "^1|^2.1",
"twig/twig": "^1.38|^2.7|^3.0"
},
"suggest": {
"kriswallsmith/assetic": "The best way to manage assets",
"monolog/monolog": "Log using Monolog",
"predis/predis": "Redis storage"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.23-dev"
}
},
"autoload": {
"psr-4": {
"DebugBar\\": "src/DebugBar/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxime Bouroumeau-Fuseau",
"email": "maxime.bouroumeau@gmail.com",
"homepage": "http://maximebf.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Debug bar in the browser for php application",
"homepage": "https://github.com/maximebf/php-debugbar",
"keywords": [
"debug",
"debugbar"
],
"support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v1.23.6"
},
"time": "2025-02-13T12:22:36+00:00"
},
{
"name": "mockery/mockery",
"version": "1.6.12",
@@ -11130,6 +11063,76 @@
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "php-debugbar/php-debugbar",
"version": "v2.1.5",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "3f589bbbaed53039d9699702c2908148647c27a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/3f589bbbaed53039d9699702c2908148647c27a1",
"reference": "3f589bbbaed53039d9699702c2908148647c27a1",
"shasum": ""
},
"require": {
"php": "^8",
"psr/log": "^1|^2|^3",
"symfony/var-dumper": "^4|^5|^6|^7"
},
"require-dev": {
"dbrekelmans/bdi": "^1",
"phpunit/phpunit": "^8|^9",
"symfony/panther": "^1|^2.1",
"twig/twig": "^1.38|^2.7|^3.0"
},
"suggest": {
"kriswallsmith/assetic": "The best way to manage assets",
"monolog/monolog": "Log using Monolog",
"predis/predis": "Redis storage"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"DebugBar\\": "src/DebugBar/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxime Bouroumeau-Fuseau",
"email": "maxime.bouroumeau@gmail.com",
"homepage": "http://maximebf.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Debug bar in the browser for php application",
"homepage": "https://github.com/php-debugbar/php-debugbar",
"keywords": [
"debug",
"debug bar",
"debugbar",
"dev"
],
"support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v2.1.5"
},
"time": "2025-02-21T13:02:05+00:00"
},
{
"name": "phpmyadmin/sql-parser",
"version": "5.10.3",
@@ -11267,16 +11270,16 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.5",
"version": "2.1.6",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "451b17f9665481ee502adc39be987cb71067ece2"
"reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/451b17f9665481ee502adc39be987cb71067ece2",
"reference": "451b17f9665481ee502adc39be987cb71067ece2",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c",
"reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c",
"shasum": ""
},
"require": {
@@ -11321,7 +11324,7 @@
"type": "github"
}
],
"time": "2025-02-13T12:49:56+00:00"
"time": "2025-02-19T15:46:42+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -11743,16 +11746,16 @@
},
{
"name": "phpunit/phpunit",
"version": "11.5.7",
"version": "11.5.9",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "e1cb706f019e2547039ca2c839898cd5f557ee5d"
"reference": "c91c830e7108a81e5845aeb6ba8fe3c1a4351c0b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e1cb706f019e2547039ca2c839898cd5f557ee5d",
"reference": "e1cb706f019e2547039ca2c839898cd5f557ee5d",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c91c830e7108a81e5845aeb6ba8fe3c1a4351c0b",
"reference": "c91c830e7108a81e5845aeb6ba8fe3c1a4351c0b",
"shasum": ""
},
"require": {
@@ -11762,7 +11765,7 @@
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.12.1",
"myclabs/deep-copy": "^1.13.0",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
@@ -11824,7 +11827,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.7"
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.9"
},
"funding": [
{
@@ -11840,7 +11843,7 @@
"type": "tidelift"
}
],
"time": "2025-02-06T16:10:05+00:00"
"time": "2025-02-21T06:08:50+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -81,7 +81,7 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-02-17',
'version' => 'develop/2025-02-22',
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 25,

44
package-lock.json generated
View File

@@ -3147,9 +3147,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.13.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
"integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
"version": "22.13.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz",
"integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4510,9 +4510,9 @@
}
},
"node_modules/chart.js": {
"version": "4.4.7",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz",
"integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==",
"version": "4.4.8",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz",
"integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
@@ -5677,9 +5677,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.101",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz",
"integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==",
"version": "1.5.103",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz",
"integrity": "sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA==",
"dev": true,
"license": "ISC"
},
@@ -7778,9 +7778,9 @@
}
},
"node_modules/launch-editor": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz",
"integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==",
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.10.0.tgz",
"integrity": "sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8901,9 +8901,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.2",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz",
"integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==",
"version": "8.5.3",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"dev": true,
"funding": [
{
@@ -11344,14 +11344,14 @@
}
},
"node_modules/vite": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz",
"integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==",
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz",
"integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.24.2",
"postcss": "^8.5.1",
"postcss": "^8.5.2",
"rollup": "^4.30.1"
},
"bin": {
@@ -12174,9 +12174,9 @@
"license": "ISC"
},
"node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
"dev": true,
"license": "MIT",
"engines": {

View File

@@ -172,8 +172,8 @@
},
"list": {
"title": "Titolo",
"active": "Attivo",
"native_currency": "Native currency",
"active": "\u00c8 attivo?",
"native_currency": "Valuta nativa",
"trigger": "Trigger",
"response": "Risposta",
"delivery": "Consegna",

View File

@@ -3,7 +3,7 @@
"administrations_page_title": "Ustawienia finansowe",
"administrations_index_menu": "Ustawienia finansowe",
"temp_administrations_introduction": "Firefly III wkr\u00f3tce uzyska mo\u017cliwo\u015b\u0107 zarz\u0105dzania wieloma ustawieniami finansowymi. W tej chwili jest tylko jedno domy\u015blne ustawienie. Mo\u017cesz ustawi\u0107 jego tytu\u0142 i natywn\u0105 walut\u0119. To zast\u0119puje poprzednie ustawienia, w kt\u00f3rym mo\u017cna by\u0142o ustawi\u0107 \"domy\u015bln\u0105 walut\u0119\". Jest ona obecnie powi\u0105zana z wybranym ustawieniem finansowym i mo\u017ce by\u0107 zmienione w tej zak\u0142adce.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administration_currency_form_help": "Wczytywanie strony mo\u017ce zaj\u0105\u0107 du\u017co czasu, je\u015bli zmienisz natywn\u0105 walut\u0119, poniewa\u017c transakcja mo\u017ce wymaga\u0107 przewalutowania na (now\u0105) natywn\u0105 walut\u0119.",
"administrations_page_edit_sub_title_js": "Edytuj ustawienia finansowe \"{title}\"",
"table": "Tabela",
"welcome_back": "Co jest grane?",
@@ -11,11 +11,11 @@
"flash_warning": "Ostrze\u017cenie!",
"flash_success": "Sukces!",
"close": "Zamknij",
"select_dest_account": "Please select or type a valid destination account name",
"select_dest_account": "Wybierz lub wpisz prawid\u0142ow\u0105 nazw\u0119 konta docelowego",
"select_source_account": "Wybierz lub wpisz prawid\u0142ow\u0105 nazw\u0119 konta \u017ar\u00f3d\u0142owego",
"split_transaction_title": "Opis podzielonej transakcji",
"errors_submission": "Co\u015b posz\u0142o nie tak w czasie zapisu. Prosz\u0119, sprawd\u017a b\u0142\u0119dy poni\u017cej.",
"is_reconciled": "Is reconciled",
"is_reconciled": "Jest uzgodniona",
"split": "Podziel",
"single_split": "Podzia\u0142",
"not_enough_currencies": "Za ma\u0142o walut",
@@ -42,10 +42,10 @@
"submit": "Prze\u015blij",
"amount": "Kwota",
"date": "Data",
"is_reconciled_fields_dropped": "Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.",
"is_reconciled_fields_dropped": "Poniewa\u017c ta transakcja jest uzgodniona, nie b\u0119dziesz w stanie zaktualizowa\u0107 kont, ani kwot(y), chyba \u017ce usuniesz flag\u0119 uzgodnienia.",
"tags": "Tagi",
"no_budget": "(brak bud\u017cetu)",
"no_bill": "(no subscription)",
"no_bill": "(brak subskrypcji)",
"category": "Kategoria",
"attachments": "Za\u0142\u0105czniki",
"notes": "Notatki",
@@ -61,7 +61,7 @@
"destination_account_reconciliation": "Nie mo\u017cesz edytowa\u0107 konta docelowego transakcji uzgadniania.",
"source_account_reconciliation": "Nie mo\u017cesz edytowa\u0107 konta \u017ar\u00f3d\u0142owego transakcji uzgadniania.",
"budget": "Bud\u017cet",
"bill": "Subscription",
"bill": "Subskrypcja",
"you_create_withdrawal": "Tworzysz wydatek.",
"you_create_transfer": "Tworzysz przelew.",
"you_create_deposit": "Tworzysz wp\u0142at\u0119.",

View File

@@ -30,7 +30,7 @@
"apply_rules_checkbox": "\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430",
"fire_webhooks_checkbox": "\u041f\u043e\u0436\u0435\u0436\u043d\u0456 \u0432\u0435\u0431\u0433\u0430\u043a\u0438",
"no_budget_pointer": "\u0417\u0434\u0430\u0454\u0442\u044c\u0441\u044f, \u043d\u0435 \u0441\u0442\u0432\u043e\u0440\u0438\u043b\u0438 \u0436\u043e\u0434\u043d\u043e\u0433\u043e \u0431\u044e\u0434\u0436\u0435\u0442\u0443. \u0421\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456 <a href=\"budgets\">\u0431\u044e\u0434\u0436\u0435\u0442\u0456\u0432<\/a>. \u0411\u044e\u0434\u0436\u0435\u0442\u0438 \u043c\u043e\u0436\u0443\u0442\u044c \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u0432\u0430\u043c \u0441\u0442\u0435\u0436\u0438\u0442\u0438 \u0437\u0430 \u0432\u0438\u0442\u0440\u0430\u0442\u0430\u043c\u0438.",
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
"no_bill_pointer": "\u0421\u0445\u043e\u0436\u0435, \u0443 \u0432\u0430\u0441 \u0449\u0435 \u043d\u0435\u043c\u0430\u0454 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438. \u0421\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u0457\u0457 \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456 <a href=\"subscriptions\">\u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a<\/a>. \u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0438 \u0434\u043e\u043f\u043e\u043c\u043e\u0436\u0443\u0442\u044c \u0432\u0430\u043c \u0432\u0456\u0434\u0441\u0442\u0435\u0436\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0442\u0440\u0430\u0442\u0438.",
"source_account": "\u0412\u0438\u0445\u0456\u0434\u043d\u0438\u0439 \u0440\u0430\u0445\u0443\u043d\u043e\u043a",
"hidden_fields_preferences": "\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 \u043e\u043f\u0446\u0456\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0456\u0457 \u0443 \u0432\u0430\u0448\u043e\u043c\u0443 <a href=\"preferences\">\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f<\/a>.",
"destination_account": "\u0420\u0430\u0445\u0443\u043d\u043e\u043a \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f",

View File

@@ -220,7 +220,6 @@
{# Moment JS #}
<script src="v1/js/lib/moment.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/moment-tz.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/moment/{{ language|replace({'-':'_'}) }}.js?v={{ FF_VERSION }}" type="text/javascript"
nonce="{{ JS_NONCE }}"></script>