🤖 Auto commit for release 'develop' on 2026-07-10

This commit is contained in:
JC5
2026-07-10 08:52:04 +02:00
parent 4605923338
commit d26eef073e
18 changed files with 151 additions and 105 deletions
@@ -158,7 +158,10 @@ final class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
}
}
@@ -155,7 +155,10 @@ final class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
}
}
@@ -61,14 +61,14 @@ final class PreferencesController extends Controller
$preferences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.preferences.index') . $this->buildParams());
$paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.preferences.index').$this->buildParams());
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($preferences, $transformer, self::RESOURCE_KEY);
$resource = new FractalCollection($preferences, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
@@ -82,7 +82,7 @@ final class PreferencesController extends Controller
*/
public function show(Preference $preference): JsonResponse
{
$manager = $this->getManager();
$manager = $this->getManager();
if ('currencyPreference' === $preference->name) {
throw new FireflyException('Please use api/v1/currencies/primary instead.');
@@ -92,25 +92,25 @@ final class PreferencesController extends Controller
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($preference, $transformer, 'preferences');
$resource = new Item($preference, $transformer, 'preferences');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
public function showList(Collection $preferenceList): JsonResponse
{
$manager = $this->getManager();
$count = $preferenceList->count();
$names = implode(',', $preferenceList->pluck('name')->toArray());
$manager = $this->getManager();
$count = $preferenceList->count();
$names = implode(',', $preferenceList->pluck('name')->toArray());
// make paginator:
$paginator = new LengthAwarePaginator($preferenceList, $count, 31_337, 1);
$paginator->setPath(route('api.v1.preferences-list.show', [$names]) . $this->buildParams());
$paginator = new LengthAwarePaginator($preferenceList, $count, 31_337, 1);
$paginator->setPath(route('api.v1.preferences-list.show', [$names]).$this->buildParams());
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$resource = new FractalCollection($preferenceList, $transformer, self::RESOURCE_KEY);
$resource = new FractalCollection($preferenceList, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
@@ -124,20 +124,20 @@ final class PreferencesController extends Controller
*/
public function store(PreferenceStoreRequest $request): JsonResponse
{
$manager = $this->getManager();
$data = $request->getAll();
$manager = $this->getManager();
$data = $request->getAll();
if ('currencyPreference' === $data['name']) {
throw new FireflyException('Please use api/v1/currencies/default instead.');
}
$pref = Preferences::set($data['name'], $data['data']);
$pref = Preferences::set($data['name'], $data['data']);
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($pref, $transformer, 'preferences');
$resource = new Item($pref, $transformer, 'preferences');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
@@ -154,15 +154,15 @@ final class PreferencesController extends Controller
throw new FireflyException('Please use api/v1/currencies/primary instead.');
}
$manager = $this->getManager();
$data = $request->getAll();
$pref = Preferences::set($preference->name, $data['data']);
$manager = $this->getManager();
$data = $request->getAll();
$pref = Preferences::set($preference->name, $data['data']);
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($pref, $transformer, 'preferences');
$resource = new Item($pref, $transformer, 'preferences');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
@@ -255,7 +255,10 @@ final class IndexController extends Controller
if (count($bill['paid_dates']) < count($bill['pay_dates'])) {
$count = count($bill['pay_dates']) - count($bill['paid_dates']);
if ($count > 0) {
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
$avg = bcdiv(
bcadd((string) $bill['amount_min'], (string) $bill['amount_max']),
'2'
);
$avg = bcmul($avg, (string) $count);
$sums[$groupOrder][$currencyId]['total_left_to_pay'] = bcadd($sums[$groupOrder][$currencyId]['total_left_to_pay'], $avg);
Log::debug(
@@ -198,7 +198,13 @@ final class BudgetLimitController extends Controller
if ($request->expectsJson()) {
$array = $limit->toArray();
// add some extra metadata:
$spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
$spentArr = $this->opsRepository->sumExpenses(
$limit->start_date,
$limit->end_date,
null,
new Collection()->push($budget),
$currency
);
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
$array['left_formatted'] = Amount::formatAnything($limit->transactionCurrency, bcadd($array['spent'], (string) $array['amount']));
$array['amount_formatted'] = Amount::formatAnything($limit->transactionCurrency, $limit['amount']);
@@ -284,7 +284,10 @@ final class IndexController extends Controller
if (array_key_exists($currency->id, $spentArr) && array_key_exists('sum', $spentArr[$currency->id])) {
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
$array['spent'][$currency->id]['spent_outside'] = Steam::negative(bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']));
$array['spent'][$currency->id]['spent_outside'] = Steam::negative(bcsub(
$spentInLimits[$currency->id],
$spentArr[$currency->id]['sum']
));
$array['spent'][$currency->id]['currency_id'] = $currency->id;
$array['spent'][$currency->id]['currency_symbol'] = $currency->symbol;
$array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places;
@@ -539,7 +539,13 @@ final class BudgetController extends Controller
}
// get spent amount in this period for this currency.
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency);
$sum = $this->opsRepository->sumExpenses(
$currentStart,
$currentEnd,
$accounts,
new Collection()->push($budget),
$currency
);
$amount = Steam::positive($sum[$currency->id]['sum'] ?? '0');
$chartData[0]['entries'][$title] = Steam::bcround($amount, $currency->decimal_places);
+5 -5
View File
@@ -198,12 +198,12 @@ final class EditController extends Controller
foreach ($submittedOperators as $operator) {
try {
$renderedEntries[] = view('rules.partials.trigger', [
'oldTrigger' => OperatorQuerySearch::getRootOperator($operator['type']),
'oldValue' => $operator['value'],
'oldChecked' => false,
'oldTrigger' => OperatorQuerySearch::getRootOperator($operator['type']),
'oldValue' => $operator['value'],
'oldChecked' => false,
'oldProhibited' => null,
'count' => $index + 1,
'triggers' => $triggers,
'count' => $index + 1,
'triggers' => $triggers,
])->render();
} catch (Throwable $e) {
$message = sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage());
@@ -31,7 +31,6 @@ use FireflyIII\Support\Facades\AppConfiguration;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use FireflyIII\Support\System\IsOldVersion;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
@@ -39,7 +38,6 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Laravel\Passport\Passport;
use phpseclib3\Crypt\RSA;
@@ -78,6 +76,7 @@ final class InstallController extends Controller
return view('install.index');
}
return response()->redirectToRoute('home');
}
@@ -133,7 +132,7 @@ final class InstallController extends Controller
$response['hasNextCommand'] = array_key_exists($requestIndex + 1, $indexes);
$response['previous'] = $command;
if(false === $response['hasNextCommand']) {
if (false === $response['hasNextCommand']) {
// if no next command, set the things
try {
AppConfiguration::set('ff3_version', (string) config('firefly.version'));
+1
View File
@@ -68,6 +68,7 @@ class Installer
// or when old firefly version
if ($this->hasNoTables() || $this->isOldVersionInstalled()) {
Log::debug('Will redirect to installer.');
return response()->redirectTo(route('installer.index'));
}
OAuthKeys::verifyKeysRoutine();
+14 -2
View File
@@ -122,7 +122,13 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$spent = $repository->sumExpenses(
$previousStart,
$previousEnd,
null,
new Collection()->push($autoBudget->budget),
$autoBudget->transactionCurrency
);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
@@ -212,7 +218,13 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$spent = $repository->sumExpenses(
$previousStart,
$previousEnd,
null,
new Collection()->push($autoBudget->budget),
$autoBudget->transactionCurrency
);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
+5 -6
View File
@@ -23,8 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Support\Binder;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Routing\Route;
use Illuminate\Support\Collection;
@@ -48,17 +46,18 @@ class PreferenceList implements BinderInterface
throw new NotFoundHttpException();
}
$list = array_unique(explode(',', $value));
$list = array_unique(explode(',', $value));
Log::debug('List of preferences is', $list);
$result = new Collection;
foreach($list as $item) {
$result = new Collection();
foreach ($list as $item) {
$current = Preferences::get($item);
if(null !== $current) {
if (null !== $current) {
Log::debug(sprintf('Add %s to the result', $item));
$result->push($current);
}
}
Log::debug('List of preferences is', $result->toArray());
return $result;
}
Log::error('PreferenceList: user is not logged in.');
@@ -222,7 +222,14 @@ trait AugumentData
$currentEnd->addMonth();
}
// primary currency amount.
$expenses = $opsRepository->sumExpenses($currentStart, $currentEnd, null, $budgetCollection, $entry->transactionCurrency, $this->convertToPrimary);
$expenses = $opsRepository->sumExpenses(
$currentStart,
$currentEnd,
null,
$budgetCollection,
$entry->transactionCurrency,
$this->convertToPrimary
);
$spent = $expenses[$currency->id]['sum'] ?? '0';
$entry->pc_spent = $spent;
@@ -127,12 +127,12 @@ trait ModelInformation
foreach ($billTriggers as $index => $trigger) {
try {
$string = view('rules.partials.trigger', [
'oldTrigger' => $trigger,
'oldValue' => $values[$index],
'oldTrigger' => $trigger,
'oldValue' => $values[$index],
'oldProhibited' => null,
'oldChecked' => false,
'count' => $index + 1,
'triggers' => $triggers,
'oldChecked' => false,
'count' => $index + 1,
'triggers' => $triggers,
])->render();
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
@@ -243,12 +243,12 @@ trait ModelInformation
foreach ($journalTriggers as $ii => $trigger) {
try {
$renderInfo = [
'oldTrigger' => $trigger,
'oldValue' => $values[$ii],
'oldTrigger' => $trigger,
'oldValue' => $values[$ii],
'oldProhibited' => null,
'oldChecked' => false,
'count' => $ii + 1,
'triggers' => $triggers,
'oldChecked' => false,
'count' => $ii + 1,
'triggers' => $triggers,
];
$string = view('rules.partials.trigger', $renderInfo)->render();
} catch (Throwable $e) {
@@ -354,7 +354,11 @@ class RecurringEnrichment implements EnrichmentInterface
/** @var RecurrenceRepetition $repetition */
foreach ($set as $repetition) {
$recurrence = $this->collection->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)->first();
$recurrence = $this->collection->filter(
static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id
)
->first()
;
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
$recurrenceId = (int) $repetition->recurrence_id;
$repId = (int) $repetition->id;
+47 -47
View File
@@ -68,63 +68,63 @@ use FireflyIII\User;
return [
'bindables' => [
// models
'account' => Account::class,
'attachment' => Attachment::class,
'availableBudget' => AvailableBudget::class,
'bill' => Bill::class,
'budget' => Budget::class,
'budgetLimit' => BudgetLimit::class,
'category' => Category::class,
'linkType' => LinkType::class,
'transactionType' => TransactionType::class,
'journalLink' => TransactionJournalLink::class,
'currency' => TransactionCurrency::class,
'objectGroup' => ObjectGroup::class,
'piggyBank' => PiggyBank::class,
'preference' => Preference::class,
'preferenceName' => Preference::class,
'tj' => TransactionJournal::class,
'tag' => Tag::class,
'recurrence' => Recurrence::class,
'rule' => Rule::class,
'ruleGroup' => RuleGroup::class,
'transactionGroup' => TransactionGroup::class,
'user' => User::class,
'webhook' => Webhook::class,
'webhookMessage' => WebhookMessage::class,
'webhookAttempt' => WebhookAttempt::class,
'invitedUser' => InvitedUser::class,
'account' => Account::class,
'attachment' => Attachment::class,
'availableBudget' => AvailableBudget::class,
'bill' => Bill::class,
'budget' => Budget::class,
'budgetLimit' => BudgetLimit::class,
'category' => Category::class,
'linkType' => LinkType::class,
'transactionType' => TransactionType::class,
'journalLink' => TransactionJournalLink::class,
'currency' => TransactionCurrency::class,
'objectGroup' => ObjectGroup::class,
'piggyBank' => PiggyBank::class,
'preference' => Preference::class,
'preferenceName' => Preference::class,
'tj' => TransactionJournal::class,
'tag' => Tag::class,
'recurrence' => Recurrence::class,
'rule' => Rule::class,
'ruleGroup' => RuleGroup::class,
'transactionGroup' => TransactionGroup::class,
'user' => User::class,
'webhook' => Webhook::class,
'webhookMessage' => WebhookMessage::class,
'webhookAttempt' => WebhookAttempt::class,
'invitedUser' => InvitedUser::class,
// strings
'currency_code' => CurrencyCode::class,
'currency_code' => CurrencyCode::class,
// dates
'start_date' => Date::class,
'end_date' => Date::class,
'date' => Date::class,
'start_date' => Date::class,
'end_date' => Date::class,
'date' => Date::class,
// lists
'accountList' => AccountList::class,
'doubleList' => AccountList::class,
'budgetList' => BudgetList::class,
'journalList' => JournalList::class,
'categoryList' => CategoryList::class,
'tagList' => TagList::class,
'accountList' => AccountList::class,
'doubleList' => AccountList::class,
'budgetList' => BudgetList::class,
'journalList' => JournalList::class,
'categoryList' => CategoryList::class,
'tagList' => TagList::class,
'preferenceList' => PreferenceList::class,
// others
'fromCurrencyCode' => CurrencyCode::class,
'toCurrencyCode' => CurrencyCode::class,
'cliToken' => CLIToken::class,
'tagOrId' => TagOrId::class,
'dynamicConfigKey' => DynamicConfigKey::class,
'eitherConfigKey' => EitherConfigKey::class,
'fromCurrencyCode' => CurrencyCode::class,
'toCurrencyCode' => CurrencyCode::class,
'cliToken' => CLIToken::class,
'tagOrId' => TagOrId::class,
'dynamicConfigKey' => DynamicConfigKey::class,
'eitherConfigKey' => EitherConfigKey::class,
// V2 API endpoints:
'userGroupAccount' => UserGroupAccount::class,
'userGroupTransaction' => UserGroupTransaction::class,
'userGroupBill' => UserGroupBill::class,
'userGroupExchangeRate' => UserGroupExchangeRate::class,
'userGroup' => UserGroup::class,
'userGroupAccount' => UserGroupAccount::class,
'userGroupTransaction' => UserGroupTransaction::class,
'userGroupBill' => UserGroupBill::class,
'userGroupExchangeRate' => UserGroupExchangeRate::class,
'userGroup' => UserGroup::class,
],
];
+2 -2
View File
@@ -78,8 +78,8 @@ return [
'running_balance_column' => (bool)env_default_when_empty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2026-07-09',
'build_time' => 1783626404,
'version' => 'develop/2026-07-10',
'build_time' => 1783666324,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.
+3 -3
View File
@@ -829,11 +829,11 @@ Route::group(
'as' => 'api.v1.preferences-list.',
],
static function (): void {
// Route::get('', ['uses' => 'PreferencesController@index', 'as' => 'index']);
// Route::post('', ['uses' => 'PreferencesController@store', 'as' => 'store']);
// Route::get('', ['uses' => 'PreferencesController@index', 'as' => 'index']);
// Route::post('', ['uses' => 'PreferencesController@store', 'as' => 'store']);
// Route::get('{preferenceList}', ['uses' => 'PreferencesController@showList', 'as' => 'show-list'])->where('preferenceList', ',+');
Route::get('{preferenceList}', ['uses' => 'PreferencesController@showList', 'as' => 'show']);
// Route::put('{preferenceName}', ['uses' => 'PreferencesController@update', 'as' => 'update']);
// Route::put('{preferenceName}', ['uses' => 'PreferencesController@update', 'as' => 'update']);
}
);