mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2
# Conflicts: # app/Support/Steam.php
This commit is contained in:
commit
3c65b46aa5
@ -56,8 +56,8 @@ class AccountController extends Controller
|
||||
function ($request, $next) {
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||
$this->chartData = new ChartData();
|
||||
$this->default = app('amount')->getDefaultCurrency();
|
||||
$this->chartData = new ChartData();
|
||||
$this->default = app('amount')->getDefaultCurrency();
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -92,11 +92,11 @@ class AccountController extends Controller
|
||||
*/
|
||||
private function renderAccountData(array $params, Account $account): void
|
||||
{
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
$currency = $this->default;
|
||||
}
|
||||
$currentSet = [
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
|
||||
// the currency that belongs to the account.
|
||||
@ -117,18 +117,18 @@ class AccountController extends Controller
|
||||
'entries' => [],
|
||||
'native_entries' => [],
|
||||
];
|
||||
$currentStart = clone $params['start'];
|
||||
$range = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $currency);
|
||||
$currentStart = clone $params['start'];
|
||||
$range = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $currency);
|
||||
|
||||
$previous = array_values($range)[0]['balance'];
|
||||
$previousNative = array_values($range)[0]['native_balance'];
|
||||
while ($currentStart <= $params['end']) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->toAtomString();
|
||||
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
|
||||
$balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
|
||||
$previous = $balance;
|
||||
$previousNative = $balanceNative;
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->toAtomString();
|
||||
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
|
||||
$balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
|
||||
$previous = $balance;
|
||||
$previousNative = $balanceNative;
|
||||
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance;
|
||||
|
@ -29,11 +29,9 @@ use FireflyIII\Events\RequestedVersionCheckStatus;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Http\Middleware\Installer;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
@ -103,7 +103,7 @@ class PreferencesController extends Controller
|
||||
$darkMode = app('preferences')->get('darkMode', 'browser')->data;
|
||||
$customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data;
|
||||
$fiscalYearStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data;
|
||||
$convertToNative =app('preferences')->get('convert_to_native', false)->data;
|
||||
$convertToNative = app('preferences')->get('convert_to_native', false)->data;
|
||||
if (is_array($fiscalYearStartStr)) {
|
||||
$fiscalYearStartStr = '01-01';
|
||||
}
|
||||
@ -257,7 +257,7 @@ class PreferencesController extends Controller
|
||||
}
|
||||
|
||||
// convert native
|
||||
$convertToNative = 1 === (int) $request->get('convertToNative');
|
||||
$convertToNative = 1 === (int) $request->get('convertToNative');
|
||||
app('preferences')->set('convert_to_native', $convertToNative);
|
||||
|
||||
// custom fiscal year
|
||||
|
@ -28,7 +28,6 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use NumberFormatter;
|
||||
|
||||
/**
|
||||
* Class Amount.
|
||||
@ -56,15 +55,15 @@ class Amount
|
||||
*/
|
||||
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
|
||||
{
|
||||
$locale = app('steam')->getLocale();
|
||||
$rounded = app('steam')->bcround($amount, $decimalPlaces);
|
||||
$locale = app('steam')->getLocale();
|
||||
$rounded = app('steam')->bcround($amount, $decimalPlaces);
|
||||
$coloured ??= true;
|
||||
|
||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
||||
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
||||
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
||||
$result = (string) $fmt->format((float) $rounded); // intentional float
|
||||
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
||||
$fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
||||
$fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
||||
$fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
||||
$result = (string) $fmt->format((float) $rounded); // intentional float
|
||||
|
||||
if (true === $coloured) {
|
||||
if (1 === bccomp($rounded, '0')) {
|
||||
@ -110,7 +109,7 @@ class Amount
|
||||
|
||||
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
||||
{
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty('getDefaultCurrencyByGroup');
|
||||
$cache->addProperty($userGroup->id);
|
||||
if ($cache->has()) {
|
||||
@ -173,23 +172,23 @@ class Amount
|
||||
private function getLocaleInfo(): array
|
||||
{
|
||||
// get config from preference, not from translation:
|
||||
$locale = app('steam')->getLocale();
|
||||
$array = app('steam')->getLocaleArray($locale);
|
||||
$locale = app('steam')->getLocale();
|
||||
$array = app('steam')->getLocaleArray($locale);
|
||||
|
||||
setlocale(LC_MONETARY, $array);
|
||||
$info = localeconv();
|
||||
$info = localeconv();
|
||||
|
||||
// correct variables
|
||||
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
||||
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes');
|
||||
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
||||
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes');
|
||||
|
||||
$info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
||||
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space');
|
||||
$info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
||||
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space');
|
||||
|
||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
||||
|
||||
$info['mon_decimal_point'] = $fmt->getSymbol(NumberFormatter::MONETARY_SEPARATOR_SYMBOL);
|
||||
$info['mon_thousands_sep'] = $fmt->getSymbol(NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
||||
$info['mon_decimal_point'] = $fmt->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL);
|
||||
$info['mon_thousands_sep'] = $fmt->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
||||
|
||||
return $info;
|
||||
}
|
||||
@ -209,7 +208,7 @@ class Amount
|
||||
public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string
|
||||
{
|
||||
// negative first:
|
||||
$space = ' ';
|
||||
$space = ' ';
|
||||
|
||||
// require space between symbol and amount?
|
||||
if (false === $sepBySpace) {
|
||||
@ -218,11 +217,11 @@ class Amount
|
||||
|
||||
// there are five possible positions for the "+" or "-" sign (if it is even used)
|
||||
// pos_a and pos_e could be the ( and ) symbol.
|
||||
$posA = ''; // before everything
|
||||
$posB = ''; // before currency symbol
|
||||
$posC = ''; // after currency symbol
|
||||
$posD = ''; // before amount
|
||||
$posE = ''; // after everything
|
||||
$posA = ''; // before everything
|
||||
$posB = ''; // before currency symbol
|
||||
$posC = ''; // after currency symbol
|
||||
$posD = ''; // before amount
|
||||
$posE = ''; // after everything
|
||||
|
||||
// format would be (currency before amount)
|
||||
// AB%sC_D%vE
|
||||
@ -264,11 +263,11 @@ class Amount
|
||||
}
|
||||
|
||||
// default is amount before currency
|
||||
$format = $posA . $posD . '%v' . $space . $posB . '%s' . $posC . $posE;
|
||||
$format = $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE;
|
||||
|
||||
if ($csPrecedes) {
|
||||
// alternative is currency before amount
|
||||
$format = $posA . $posB . '%s' . $posC . $space . $posD . '%v' . $posE;
|
||||
$format = $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE;
|
||||
}
|
||||
|
||||
return $format;
|
||||
|
@ -47,7 +47,7 @@ class RemoteUserGuard implements Guard
|
||||
public function __construct(UserProvider $provider, Application $app)
|
||||
{
|
||||
/** @var null|Request $request */
|
||||
$request = $app->get('request');
|
||||
$request = $app->get('request');
|
||||
app('log')->debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
|
||||
$this->application = $app;
|
||||
$this->provider = $provider;
|
||||
@ -63,8 +63,8 @@ class RemoteUserGuard implements Guard
|
||||
return;
|
||||
}
|
||||
// Get the user identifier from $_SERVER or apache filtered headers
|
||||
$header = config('auth.guard_header', 'REMOTE_USER');
|
||||
$userID = request()->server($header) ?? null;
|
||||
$header = config('auth.guard_header', 'REMOTE_USER');
|
||||
$userID = request()->server($header) ?? null;
|
||||
|
||||
if (function_exists('apache_request_headers')) {
|
||||
app('log')->debug('Use apache_request_headers to find user ID.');
|
||||
@ -83,7 +83,7 @@ class RemoteUserGuard implements Guard
|
||||
$retrievedUser = $this->provider->retrieveById($userID);
|
||||
|
||||
// store email address if present in header and not already set.
|
||||
$header = config('auth.guard_email');
|
||||
$header = config('auth.guard_email');
|
||||
|
||||
if (null !== $header) {
|
||||
$emailAddress = (string) (request()->server($header) ?? apache_request_headers()[$header] ?? null);
|
||||
@ -99,7 +99,7 @@ class RemoteUserGuard implements Guard
|
||||
}
|
||||
|
||||
app('log')->debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email));
|
||||
$this->user = $retrievedUser;
|
||||
$this->user = $retrievedUser;
|
||||
}
|
||||
|
||||
public function guest(): bool
|
||||
@ -139,14 +139,14 @@ class RemoteUserGuard implements Guard
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
||||
*/
|
||||
public function id(): null | int | string
|
||||
public function id(): null|int|string
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
return $this->user?->id;
|
||||
}
|
||||
|
||||
public function setUser(null | Authenticatable | User $user): void // @phpstan-ignore-line
|
||||
public function setUser(null|Authenticatable|User $user): void // @phpstan-ignore-line
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
if ($user instanceof User) {
|
||||
|
@ -30,15 +30,13 @@ use FireflyIII\Models\Role;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Override;
|
||||
use Str;
|
||||
|
||||
/**
|
||||
* Class RemoteUserProvider
|
||||
*/
|
||||
class RemoteUserProvider implements UserProvider
|
||||
{
|
||||
#[Override]
|
||||
#[\Override]
|
||||
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
@ -74,7 +72,7 @@ class RemoteUserProvider implements UserProvider
|
||||
'blocked' => false,
|
||||
'blocked_code' => null,
|
||||
'email' => $identifier,
|
||||
'password' => bcrypt(Str::random(64)),
|
||||
'password' => bcrypt(\Str::random(64)),
|
||||
]
|
||||
);
|
||||
// if this is the first user, give them admin as well.
|
||||
|
@ -48,18 +48,19 @@ class Balance
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$query = Transaction::whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
|
||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->orderBy('transaction_journals.date', 'desc')
|
||||
->orderBy('transaction_journals.order', 'asc')
|
||||
->orderBy('transaction_journals.description', 'desc')
|
||||
->orderBy('transactions.amount', 'desc')
|
||||
->where('transaction_journals.date', '<=', $date);
|
||||
$query = Transaction::whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
|
||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->orderBy('transaction_journals.date', 'desc')
|
||||
->orderBy('transaction_journals.order', 'asc')
|
||||
->orderBy('transaction_journals.description', 'desc')
|
||||
->orderBy('transactions.amount', 'desc')
|
||||
->where('transaction_journals.date', '<=', $date)
|
||||
;
|
||||
|
||||
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']);
|
||||
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']);
|
||||
foreach ($result as $entry) {
|
||||
$accountId = (int) $entry->account_id;
|
||||
$currencyId = (int) $entry->transaction_currency_id;
|
||||
$accountId = (int) $entry->account_id;
|
||||
$currencyId = (int) $entry->transaction_currency_id;
|
||||
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
|
||||
$return[$accountId] ??= [];
|
||||
if (array_key_exists($currencyId, $return[$accountId])) {
|
||||
|
@ -43,21 +43,23 @@ class AccountList implements BinderInterface
|
||||
if ('allAssetAccounts' === $value) {
|
||||
/** @var Collection $collection */
|
||||
$collection = auth()->user()->accounts()
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE])
|
||||
->orderBy('accounts.name', 'ASC')
|
||||
->get(['accounts.*']);
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE])
|
||||
->orderBy('accounts.name', 'ASC')
|
||||
->get(['accounts.*'])
|
||||
;
|
||||
}
|
||||
if ('allAssetAccounts' !== $value) {
|
||||
$incoming = array_map('\intval', explode(',', $value));
|
||||
$list = array_merge(array_unique($incoming), [0]);
|
||||
$incoming = array_map('\intval', explode(',', $value));
|
||||
$list = array_merge(array_unique($incoming), [0]);
|
||||
|
||||
/** @var Collection $collection */
|
||||
$collection = auth()->user()->accounts()
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('accounts.id', $list)
|
||||
->orderBy('accounts.name', 'ASC')
|
||||
->get(['accounts.*']);
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('accounts.id', $list)
|
||||
->orderBy('accounts.name', 'ASC')
|
||||
->get(['accounts.*'])
|
||||
;
|
||||
}
|
||||
|
||||
if ($collection->count() > 0) {
|
||||
|
@ -41,12 +41,13 @@ class BudgetList implements BinderInterface
|
||||
if (auth()->check()) {
|
||||
if ('allBudgets' === $value) {
|
||||
return auth()->user()->budgets()->where('active', true)
|
||||
->orderBy('order', 'ASC')
|
||||
->orderBy('name', 'ASC')
|
||||
->get();
|
||||
->orderBy('order', 'ASC')
|
||||
->orderBy('name', 'ASC')
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||
|
||||
if (0 === count($list)) { // @phpstan-ignore-line
|
||||
app('log')->warning('Budget list count is zero, return 404.');
|
||||
@ -56,9 +57,10 @@ class BudgetList implements BinderInterface
|
||||
|
||||
/** @var Collection $collection */
|
||||
$collection = auth()->user()->budgets()
|
||||
->where('active', true)
|
||||
->whereIn('id', $list)
|
||||
->get();
|
||||
->where('active', true)
|
||||
->whereIn('id', $list)
|
||||
->get()
|
||||
;
|
||||
|
||||
// add empty budget if applicable.
|
||||
if (in_array(0, $list, true)) {
|
||||
|
@ -41,19 +41,21 @@ class CategoryList implements BinderInterface
|
||||
if (auth()->check()) {
|
||||
if ('allCategories' === $value) {
|
||||
return auth()->user()->categories()
|
||||
->orderBy('name', 'ASC')
|
||||
->get();
|
||||
->orderBy('name', 'ASC')
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||
if (0 === count($list)) { // @phpstan-ignore-line
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
/** @var Collection $collection */
|
||||
$collection = auth()->user()->categories()
|
||||
->whereIn('id', $list)
|
||||
->get();
|
||||
->whereIn('id', $list)
|
||||
->get()
|
||||
;
|
||||
|
||||
// add empty category if applicable.
|
||||
if (in_array(0, $list, true)) {
|
||||
|
@ -43,16 +43,16 @@ class Date implements BinderInterface
|
||||
/** @var FiscalHelperInterface $fiscalHelper */
|
||||
$fiscalHelper = app(FiscalHelperInterface::class);
|
||||
|
||||
$magicWords = [
|
||||
'currentMonthStart' => today(config('app.timezone'))->startOfMonth(),
|
||||
'currentMonthEnd' => today(config('app.timezone'))->endOfMonth(),
|
||||
'currentYearStart' => today(config('app.timezone'))->startOfYear(),
|
||||
'currentYearEnd' => today(config('app.timezone'))->endOfYear(),
|
||||
$magicWords = [
|
||||
'currentMonthStart' => today(config('app.timezone'))->startOfMonth(),
|
||||
'currentMonthEnd' => today(config('app.timezone'))->endOfMonth(),
|
||||
'currentYearStart' => today(config('app.timezone'))->startOfYear(),
|
||||
'currentYearEnd' => today(config('app.timezone'))->endOfYear(),
|
||||
|
||||
'previousMonthStart' => today(config('app.timezone'))->startOfMonth()->subDay()->startOfMonth(),
|
||||
'previousMonthEnd' => today(config('app.timezone'))->startOfMonth()->subDay()->endOfMonth(),
|
||||
'previousYearStart' => today(config('app.timezone'))->startOfYear()->subDay()->startOfYear(),
|
||||
'previousYearEnd' => today(config('app.timezone'))->startOfYear()->subDay()->endOfYear(),
|
||||
'previousMonthStart' => today(config('app.timezone'))->startOfMonth()->subDay()->startOfMonth(),
|
||||
'previousMonthEnd' => today(config('app.timezone'))->startOfMonth()->subDay()->endOfMonth(),
|
||||
'previousYearStart' => today(config('app.timezone'))->startOfYear()->subDay()->startOfYear(),
|
||||
'previousYearEnd' => today(config('app.timezone'))->startOfYear()->subDay()->endOfYear(),
|
||||
|
||||
'currentFiscalYearStart' => $fiscalHelper->startOfFiscalYear(today(config('app.timezone'))),
|
||||
'currentFiscalYearEnd' => $fiscalHelper->endOfFiscalYear(today(config('app.timezone'))),
|
||||
@ -68,7 +68,7 @@ class Date implements BinderInterface
|
||||
|
||||
try {
|
||||
$result = new Carbon($value);
|
||||
} catch (InvalidDateException | InvalidFormatException $e) { // @phpstan-ignore-line
|
||||
} catch (InvalidDateException|InvalidFormatException $e) { // @phpstan-ignore-line
|
||||
$message = sprintf('Could not parse date "%s" for user #%d: %s', $value, auth()->user()->id, $e->getMessage());
|
||||
app('log')->error($message);
|
||||
|
||||
|
@ -39,7 +39,7 @@ class JournalList implements BinderInterface
|
||||
public static function routeBinder(string $value, Route $route): array
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$list = self::parseList($value);
|
||||
$list = self::parseList($value);
|
||||
|
||||
// get the journals by using the collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
@ -47,7 +47,7 @@ class JournalList implements BinderInterface
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::RECONCILIATION]);
|
||||
$collector->withCategoryInformation()->withBudgetInformation()->withTagInformation()->withAccountInformation();
|
||||
$collector->setJournalIds($list);
|
||||
$result = $collector->getExtractedJournals();
|
||||
$result = $collector->getExtractedJournals();
|
||||
if (0 === count($result)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
@ -43,10 +43,11 @@ class TagList implements BinderInterface
|
||||
if (auth()->check()) {
|
||||
if ('allTags' === $value) {
|
||||
return auth()->user()->tags()
|
||||
->orderBy('tag', 'ASC')
|
||||
->get();
|
||||
->orderBy('tag', 'ASC')
|
||||
->get()
|
||||
;
|
||||
}
|
||||
$list = array_unique(array_map('\strtolower', explode(',', $value)));
|
||||
$list = array_unique(array_map('\strtolower', explode(',', $value)));
|
||||
app('log')->debug('List of tags is', $list);
|
||||
|
||||
if (0 === count($list)) { // @phpstan-ignore-line
|
||||
@ -58,7 +59,7 @@ class TagList implements BinderInterface
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$allTags = $repository->get();
|
||||
$allTags = $repository->get();
|
||||
|
||||
$collection = $allTags->filter(
|
||||
static function (Tag $tag) use ($list) {
|
||||
|
@ -40,7 +40,7 @@ class TagOrId implements BinderInterface
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
|
||||
$result = $repository->findByTag($value);
|
||||
$result = $repository->findByTag($value);
|
||||
if (null === $result) {
|
||||
$result = $repository->find((int) $value);
|
||||
}
|
||||
|
@ -42,8 +42,9 @@ class UserGroupAccount implements BinderInterface
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$account = Account::where('id', (int) $value)
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first();
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first()
|
||||
;
|
||||
if (null !== $account) {
|
||||
return $account;
|
||||
}
|
||||
|
@ -42,8 +42,9 @@ class UserGroupBill implements BinderInterface
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$currency = Bill::where('id', (int) $value)
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first();
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first()
|
||||
;
|
||||
if (null !== $currency) {
|
||||
return $currency;
|
||||
}
|
||||
|
@ -39,8 +39,9 @@ class UserGroupExchangeRate implements BinderInterface
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$rate = CurrencyExchangeRate::where('id', (int) $value)
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first();
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first()
|
||||
;
|
||||
if (null !== $rate) {
|
||||
return $rate;
|
||||
}
|
||||
|
@ -39,8 +39,9 @@ class UserGroupTransaction implements BinderInterface
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$group = TransactionGroup::where('id', (int) $value)
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first();
|
||||
->where('user_group_id', $user->user_group_id)
|
||||
->first()
|
||||
;
|
||||
if (null !== $group) {
|
||||
return $group;
|
||||
}
|
||||
|
@ -23,9 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Cache;
|
||||
use Illuminate\Support\Collection;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Class CacheProperties.
|
||||
@ -57,7 +55,7 @@ class CacheProperties
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return Cache::get($this->hash);
|
||||
return \Cache::get($this->hash);
|
||||
}
|
||||
|
||||
public function getHash(): string
|
||||
@ -72,16 +70,16 @@ class CacheProperties
|
||||
}
|
||||
$this->hash();
|
||||
|
||||
return Cache::has($this->hash);
|
||||
return \Cache::has($this->hash);
|
||||
}
|
||||
|
||||
private function hash(): void
|
||||
{
|
||||
$content = '';
|
||||
$content = '';
|
||||
foreach ($this->properties as $property) {
|
||||
try {
|
||||
$content .= json_encode($property, JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $e) {
|
||||
} catch (\JsonException $e) {
|
||||
// @ignoreException
|
||||
$content .= hash('sha256', (string) time());
|
||||
}
|
||||
@ -94,6 +92,6 @@ class CacheProperties
|
||||
*/
|
||||
public function store($data): void
|
||||
{
|
||||
Cache::forever($this->hash, $data);
|
||||
\Cache::forever($this->hash, $data);
|
||||
}
|
||||
}
|
||||
|
@ -26,16 +26,15 @@ namespace FireflyIII\Support\Calendar;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\IntervalException;
|
||||
use SplObjectStorage;
|
||||
|
||||
/**
|
||||
* Class Calculator
|
||||
*/
|
||||
class Calculator
|
||||
{
|
||||
public const int DEFAULT_INTERVAL = 1;
|
||||
private static ?SplObjectStorage $intervalMap = null;
|
||||
private static array $intervals = [];
|
||||
public const int DEFAULT_INTERVAL = 1;
|
||||
private static ?\SplObjectStorage $intervalMap = null;
|
||||
private static array $intervals = [];
|
||||
|
||||
/**
|
||||
* @throws IntervalException
|
||||
@ -66,14 +65,14 @@ class Calculator
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.MissingImport)
|
||||
*/
|
||||
private static function loadIntervalMap(): SplObjectStorage
|
||||
private static function loadIntervalMap(): \SplObjectStorage
|
||||
{
|
||||
if (null !== self::$intervalMap) {
|
||||
return self::$intervalMap;
|
||||
}
|
||||
self::$intervalMap = new SplObjectStorage();
|
||||
self::$intervalMap = new \SplObjectStorage();
|
||||
foreach (Periodicity::cases() as $interval) {
|
||||
$periodicityClass = __NAMESPACE__ . "\\Periodicity\\{$interval->name}";
|
||||
$periodicityClass = __NAMESPACE__."\\Periodicity\\{$interval->name}";
|
||||
self::$intervals[] = $interval->name;
|
||||
self::$intervalMap->attach($interval, new $periodicityClass());
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ class FrontpageChartGenerator
|
||||
*/
|
||||
private function processRow(array $data, Budget $budget, BudgetLimit $limit, array $entry): array
|
||||
{
|
||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||
if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) {
|
||||
$title = sprintf(
|
||||
'%s (%s) (%s - %s)',
|
||||
@ -165,7 +165,7 @@ class FrontpageChartGenerator
|
||||
$limit->end_date->isoFormat($this->monthAndDayFormat)
|
||||
);
|
||||
}
|
||||
$sumSpent = bcmul($entry['sum'], '-1'); // spent
|
||||
$sumSpent = bcmul($entry['sum'], '-1'); // spent
|
||||
|
||||
$data[0]['entries'][$title] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent; // spent
|
||||
$data[1]['entries'][$title] = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($entry['sum'], $limit->amount) : '0'; // left to spent
|
||||
|
@ -65,13 +65,13 @@ class FrontpageChartGenerator
|
||||
|
||||
public function generate(): array
|
||||
{
|
||||
$categories = $this->repository->getCategories();
|
||||
$accounts = $this->accountRepos->getAccountsByType(
|
||||
$categories = $this->repository->getCategories();
|
||||
$accounts = $this->accountRepos->getAccountsByType(
|
||||
[AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::ASSET, AccountType::DEFAULT]
|
||||
);
|
||||
|
||||
// get expenses + income per category:
|
||||
$collection = [];
|
||||
$collection = [];
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
@ -82,10 +82,10 @@ class FrontpageChartGenerator
|
||||
// collect for no-category:
|
||||
$collection[] = $this->collectNoCatExpenses($accounts);
|
||||
|
||||
$tempData = array_merge(...$collection);
|
||||
$tempData = array_merge(...$collection);
|
||||
|
||||
// sort temp array by amount.
|
||||
$amounts = array_column($tempData, 'sum_float');
|
||||
$amounts = array_column($tempData, 'sum_float');
|
||||
array_multisort($amounts, SORT_ASC, $tempData);
|
||||
|
||||
$currencyData = $this->createCurrencyGroups($tempData);
|
||||
|
@ -38,22 +38,22 @@ class WholePeriodChartGenerator
|
||||
{
|
||||
public function generate(Category $category, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$collection = new Collection([$category]);
|
||||
$collection = new Collection([$category]);
|
||||
|
||||
/** @var OperationsRepositoryInterface $opsRepository */
|
||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
$types = [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
||||
$accounts = $accountRepository->getAccountsByType($types);
|
||||
$step = $this->calculateStep($start, $end);
|
||||
$chartData = [];
|
||||
$spent = [];
|
||||
$earned = [];
|
||||
$types = [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
||||
$accounts = $accountRepository->getAccountsByType($types);
|
||||
$step = $this->calculateStep($start, $end);
|
||||
$chartData = [];
|
||||
$spent = [];
|
||||
$earned = [];
|
||||
|
||||
$current = clone $start;
|
||||
$current = clone $start;
|
||||
|
||||
while ($current <= $end) {
|
||||
$key = $current->format('Y-m-d');
|
||||
@ -63,14 +63,14 @@ class WholePeriodChartGenerator
|
||||
$current = app('navigation')->addPeriod($current, $step, 0);
|
||||
}
|
||||
|
||||
$currencies = $this->extractCurrencies($spent) + $this->extractCurrencies($earned);
|
||||
$currencies = $this->extractCurrencies($spent) + $this->extractCurrencies($earned);
|
||||
|
||||
// generate chart data (for each currency)
|
||||
/** @var array $currency */
|
||||
foreach ($currencies as $currency) {
|
||||
$code = $currency['currency_code'];
|
||||
$name = $currency['currency_name'];
|
||||
$chartData[sprintf('spent-in-%s', $code)] = [
|
||||
$code = $currency['currency_code'];
|
||||
$name = $currency['currency_name'];
|
||||
$chartData[sprintf('spent-in-%s', $code)] = [
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $name]),
|
||||
'entries' => [],
|
||||
'type' => 'bar',
|
||||
@ -85,11 +85,11 @@ class WholePeriodChartGenerator
|
||||
];
|
||||
}
|
||||
|
||||
$current = clone $start;
|
||||
$current = clone $start;
|
||||
|
||||
while ($current <= $end) {
|
||||
$key = $current->format('Y-m-d');
|
||||
$label = app('navigation')->periodShow($current, $step);
|
||||
$key = $current->format('Y-m-d');
|
||||
$label = app('navigation')->periodShow($current, $step);
|
||||
|
||||
/** @var array $currency */
|
||||
foreach ($currencies as $currency) {
|
||||
|
@ -46,7 +46,7 @@ class ChartData
|
||||
if (array_key_exists('native_currency_id', $data)) {
|
||||
$data['native_currency_id'] = (string) $data['native_currency_id'];
|
||||
}
|
||||
$required = ['start', 'date', 'end', 'entries', 'native_entries'];
|
||||
$required = ['start', 'date', 'end', 'entries', 'native_entries'];
|
||||
foreach ($required as $field) {
|
||||
if (!array_key_exists($field, $data)) {
|
||||
throw new FireflyException(sprintf('Data-set is missing the "%s"-variable.', $field));
|
||||
|
@ -55,7 +55,7 @@ class ChartColour
|
||||
public static function getColour(int $index): string
|
||||
{
|
||||
$index %= count(self::$colours);
|
||||
$row = self::$colours[$index];
|
||||
$row = self::$colours[$index];
|
||||
|
||||
return sprintf('rgba(%d, %d, %d, 0.7)', $row[0], $row[1], $row[2]);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ class AutoBudgetCronjob extends AbstractCronjob
|
||||
app('log')->info(sprintf('Will now fire auto budget cron job task for date "%s".', $this->date->format('Y-m-d')));
|
||||
|
||||
/** @var CreateAutoBudgetLimits $job */
|
||||
$job = app(CreateAutoBudgetLimits::class, [$this->date]);
|
||||
$job = app(CreateAutoBudgetLimits::class, [$this->date]);
|
||||
$job->setDate($this->date);
|
||||
$job->handle();
|
||||
|
||||
|
@ -80,7 +80,7 @@ class BillWarningCronjob extends AbstractCronjob
|
||||
app('log')->info(sprintf('Will now fire bill warning job task for date "%s".', $this->date->format('Y-m-d H:i:s')));
|
||||
|
||||
/** @var WarnAboutBills $job */
|
||||
$job = app(WarnAboutBills::class);
|
||||
$job = app(WarnAboutBills::class);
|
||||
$job->setDate($this->date);
|
||||
$job->setForce($this->force);
|
||||
$job->handle();
|
||||
|
@ -69,7 +69,7 @@ class ExchangeRatesCronjob extends AbstractCronjob
|
||||
app('log')->info(sprintf('Will now fire exchange rates cron job task for date "%s".', $this->date->format('Y-m-d')));
|
||||
|
||||
/** @var DownloadExchangeRates $job */
|
||||
$job = app(DownloadExchangeRates::class);
|
||||
$job = app(DownloadExchangeRates::class);
|
||||
$job->setDate($this->date);
|
||||
$job->handle();
|
||||
|
||||
|
@ -78,7 +78,7 @@ class RecurringCronjob extends AbstractCronjob
|
||||
{
|
||||
app('log')->info(sprintf('Will now fire recurring cron job task for date "%s".', $this->date->format('Y-m-d H:i:s')));
|
||||
|
||||
$job = new CreateRecurringTransactions($this->date);
|
||||
$job = new CreateRecurringTransactions($this->date);
|
||||
$job->setForce($this->force);
|
||||
$job->handle();
|
||||
|
||||
|
@ -27,7 +27,6 @@ use Eloquent;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Form\FormSupport;
|
||||
use Illuminate\Support\Collection;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class ExpandedForm.
|
||||
@ -43,7 +42,7 @@ class ExpandedForm
|
||||
*/
|
||||
public function amountNoCurrency(string $name, $value = null, ?array $options = null): string
|
||||
{
|
||||
$options ??= [];
|
||||
$options ??= [];
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
@ -57,7 +56,7 @@ class ExpandedForm
|
||||
// }
|
||||
try {
|
||||
$html = view('form.amount-no-currency', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Could not render amountNoCurrency(): %s', $e->getMessage()));
|
||||
$html = 'Could not render amountNoCurrency.';
|
||||
|
||||
@ -74,8 +73,8 @@ class ExpandedForm
|
||||
*/
|
||||
public function checkbox(string $name, ?int $value = null, $checked = null, ?array $options = null): string
|
||||
{
|
||||
$options ??= [];
|
||||
$value ??= 1;
|
||||
$options ??= [];
|
||||
$value ??= 1;
|
||||
$options['checked'] = true === $checked;
|
||||
|
||||
if (app('session')->has('preFilled')) {
|
||||
@ -83,16 +82,16 @@ class ExpandedForm
|
||||
$options['checked'] = $preFilled[$name] ?? $options['checked'];
|
||||
}
|
||||
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
|
||||
unset($options['placeholder'], $options['autocomplete'], $options['class']);
|
||||
|
||||
try {
|
||||
$html = view('form.checkbox', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render checkbox(): %s', $e->getMessage()));
|
||||
$html = 'Could not render checkbox.';
|
||||
|
||||
@ -117,7 +116,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render date(): %s', $e->getMessage()));
|
||||
$html = 'Could not render date.';
|
||||
|
||||
@ -139,7 +138,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.file', compact('classes', 'name', 'label', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render file(): %s', $e->getMessage()));
|
||||
$html = 'Could not render file.';
|
||||
|
||||
@ -157,15 +156,15 @@ class ExpandedForm
|
||||
public function integer(string $name, $value = null, ?array $options = null): string
|
||||
{
|
||||
$options ??= [];
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] ??= '1';
|
||||
|
||||
try {
|
||||
$html = view('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render integer(): %s', $e->getMessage()));
|
||||
$html = 'Could not render integer.';
|
||||
|
||||
@ -190,7 +189,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.location', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render location(): %s', $e->getMessage()));
|
||||
$html = 'Could not render location.';
|
||||
|
||||
@ -206,12 +205,12 @@ class ExpandedForm
|
||||
$selectList[0] = '(none)';
|
||||
$fields = ['title', 'name', 'description'];
|
||||
|
||||
/** @var Eloquent $entry */
|
||||
/** @var \Eloquent $entry */
|
||||
foreach ($set as $entry) {
|
||||
// All Eloquent models have an ID
|
||||
$entryId = $entry->id; // @phpstan-ignore-line
|
||||
$current = $entry->toArray();
|
||||
$title = null;
|
||||
$entryId = $entry->id; // @phpstan-ignore-line
|
||||
$current = $entry->toArray();
|
||||
$title = null;
|
||||
foreach ($fields as $field) {
|
||||
if (array_key_exists($field, $current) && null === $title) {
|
||||
$title = $current[$field];
|
||||
@ -243,7 +242,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.object_group', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render objectGroup(): %s', $e->getMessage()));
|
||||
$html = 'Could not render objectGroup.';
|
||||
|
||||
@ -260,7 +259,7 @@ class ExpandedForm
|
||||
{
|
||||
try {
|
||||
$html = view('form.options', compact('type', 'name'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render select(): %s', $e->getMessage()));
|
||||
$html = 'Could not render optionsList.';
|
||||
|
||||
@ -281,7 +280,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.password', compact('classes', 'name', 'label', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render password(): %s', $e->getMessage()));
|
||||
$html = 'Could not render password.';
|
||||
|
||||
@ -302,7 +301,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.password', compact('classes', 'value', 'name', 'label', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render passwordWithValue(): %s', $e->getMessage()));
|
||||
$html = 'Could not render passwordWithValue.';
|
||||
|
||||
@ -330,7 +329,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.percentage', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render percentage(): %s', $e->getMessage()));
|
||||
$html = 'Could not render percentage.';
|
||||
|
||||
@ -353,7 +352,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.static', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render staticText(): %s', $e->getMessage()));
|
||||
$html = 'Could not render staticText.';
|
||||
|
||||
@ -377,7 +376,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.text', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render text(): %s', $e->getMessage()));
|
||||
$html = 'Could not render text.';
|
||||
|
||||
@ -406,7 +405,7 @@ class ExpandedForm
|
||||
|
||||
try {
|
||||
$html = view('form.textarea', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render textarea(): %s', $e->getMessage()));
|
||||
$html = 'Could not render textarea.';
|
||||
|
||||
|
@ -82,8 +82,8 @@ class ExportDataGenerator
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->accounts = new Collection();
|
||||
$this->start = today(config('app.timezone'));
|
||||
$this->accounts = new Collection();
|
||||
$this->start = today(config('app.timezone'));
|
||||
$this->start->subYear();
|
||||
$this->end = today(config('app.timezone'));
|
||||
$this->exportTransactions = false;
|
||||
@ -141,7 +141,7 @@ class ExportDataGenerator
|
||||
*/
|
||||
private function exportAccounts(): string
|
||||
{
|
||||
$header = [
|
||||
$header = [
|
||||
'user_id',
|
||||
'account_id',
|
||||
'created_at',
|
||||
@ -162,7 +162,7 @@ class ExportDataGenerator
|
||||
];
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser($this->user);
|
||||
$allAccounts = $repository->getAccountsByType([]);
|
||||
$records = [];
|
||||
@ -192,7 +192,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -230,8 +230,8 @@ class ExportDataGenerator
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser($this->user);
|
||||
$bills = $repository->getBills();
|
||||
$header = [
|
||||
$bills = $repository->getBills();
|
||||
$header = [
|
||||
'user_id',
|
||||
'bill_id',
|
||||
'created_at',
|
||||
@ -245,7 +245,7 @@ class ExportDataGenerator
|
||||
'skip',
|
||||
'active',
|
||||
];
|
||||
$records = [];
|
||||
$records = [];
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
@ -266,7 +266,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -296,7 +296,7 @@ class ExportDataGenerator
|
||||
*/
|
||||
private function exportBudgets(): string
|
||||
{
|
||||
$header = [
|
||||
$header = [
|
||||
'user_id',
|
||||
'budget_id',
|
||||
'name',
|
||||
@ -310,9 +310,9 @@ class ExportDataGenerator
|
||||
|
||||
$budgetRepos = app(BudgetRepositoryInterface::class);
|
||||
$budgetRepos->setUser($this->user);
|
||||
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
||||
$budgets = $budgetRepos->getBudgets();
|
||||
$records = [];
|
||||
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
||||
$budgets = $budgetRepos->getBudgets();
|
||||
$records = [];
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
@ -335,7 +335,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -365,10 +365,10 @@ class ExportDataGenerator
|
||||
*/
|
||||
private function exportCategories(): string
|
||||
{
|
||||
$header = ['user_id', 'category_id', 'created_at', 'updated_at', 'name'];
|
||||
$header = ['user_id', 'category_id', 'created_at', 'updated_at', 'name'];
|
||||
|
||||
/** @var CategoryRepositoryInterface $catRepos */
|
||||
$catRepos = app(CategoryRepositoryInterface::class);
|
||||
$catRepos = app(CategoryRepositoryInterface::class);
|
||||
$catRepos->setUser($this->user);
|
||||
|
||||
$records = [];
|
||||
@ -386,7 +386,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -417,14 +417,14 @@ class ExportDataGenerator
|
||||
private function exportPiggies(): string
|
||||
{
|
||||
/** @var PiggyBankRepositoryInterface $piggyRepos */
|
||||
$piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$piggyRepos->setUser($this->user);
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$accountRepos->setUser($this->user);
|
||||
|
||||
$header = [
|
||||
$header = [
|
||||
'user_id',
|
||||
'piggy_bank_id',
|
||||
'created_at',
|
||||
@ -440,8 +440,8 @@ class ExportDataGenerator
|
||||
'order',
|
||||
'active',
|
||||
];
|
||||
$records = [];
|
||||
$piggies = $piggyRepos->getPiggyBanks();
|
||||
$records = [];
|
||||
$piggies = $piggyRepos->getPiggyBanks();
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggies as $piggy) {
|
||||
@ -466,7 +466,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -499,7 +499,7 @@ class ExportDataGenerator
|
||||
/** @var RecurringRepositoryInterface $recurringRepos */
|
||||
$recurringRepos = app(RecurringRepositoryInterface::class);
|
||||
$recurringRepos->setUser($this->user);
|
||||
$header = [
|
||||
$header = [
|
||||
// recurrence:
|
||||
'user_id', 'recurrence_id', 'row_contains', 'created_at', 'updated_at', 'type', 'title', 'description', 'first_date', 'repeat_until', 'latest_date', 'repetitions', 'apply_rules', 'active',
|
||||
|
||||
@ -508,8 +508,8 @@ class ExportDataGenerator
|
||||
// transactions + meta:
|
||||
'currency_code', 'foreign_currency_code', 'source_name', 'source_type', 'destination_name', 'destination_type', 'amount', 'foreign_amount', 'category', 'budget', 'piggy_bank', 'tags',
|
||||
];
|
||||
$records = [];
|
||||
$recurrences = $recurringRepos->getAll();
|
||||
$records = [];
|
||||
$recurrences = $recurringRepos->getAll();
|
||||
|
||||
/** @var Recurrence $recurrence */
|
||||
foreach ($recurrences as $recurrence) {
|
||||
@ -542,7 +542,7 @@ class ExportDataGenerator
|
||||
$piggyBankId = $recurringRepos->getPiggyBank($transaction);
|
||||
$tags = $recurringRepos->getTags($transaction);
|
||||
|
||||
$records[] = [
|
||||
$records[] = [
|
||||
// recurrence
|
||||
$this->user->id,
|
||||
$recurrence->id,
|
||||
@ -558,7 +558,7 @@ class ExportDataGenerator
|
||||
}
|
||||
}
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -595,8 +595,8 @@ class ExportDataGenerator
|
||||
'action_type', 'action_value', 'action_order', 'action_active', 'action_stop_processing'];
|
||||
$ruleRepos = app(RuleRepositoryInterface::class);
|
||||
$ruleRepos->setUser($this->user);
|
||||
$rules = $ruleRepos->getAll();
|
||||
$records = [];
|
||||
$rules = $ruleRepos->getAll();
|
||||
$records = [];
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
@ -635,7 +635,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -665,12 +665,12 @@ class ExportDataGenerator
|
||||
*/
|
||||
private function exportTags(): string
|
||||
{
|
||||
$header = ['user_id', 'tag_id', 'created_at', 'updated_at', 'tag', 'date', 'description', 'latitude', 'longitude', 'zoom_level'];
|
||||
$header = ['user_id', 'tag_id', 'created_at', 'updated_at', 'tag', 'date', 'description', 'latitude', 'longitude', 'zoom_level'];
|
||||
|
||||
$tagRepos = app(TagRepositoryInterface::class);
|
||||
$tagRepos->setUser($this->user);
|
||||
$tags = $tagRepos->get();
|
||||
$records = [];
|
||||
$tags = $tagRepos->get();
|
||||
$records = [];
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
@ -689,7 +689,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
@ -728,26 +728,27 @@ class ExportDataGenerator
|
||||
private function exportTransactions(): string
|
||||
{
|
||||
// TODO better place for keys?
|
||||
$header = ['user_id', 'group_id', 'journal_id', 'created_at', 'updated_at', 'group_title', 'type', 'amount', 'foreign_amount', 'currency_code', 'foreign_currency_code', 'description', 'date', 'source_name', 'source_iban', 'source_type', 'destination_name', 'destination_iban', 'destination_type', 'reconciled', 'category', 'budget', 'bill', 'tags', 'notes'];
|
||||
$header = ['user_id', 'group_id', 'journal_id', 'created_at', 'updated_at', 'group_title', 'type', 'amount', 'foreign_amount', 'currency_code', 'foreign_currency_code', 'description', 'date', 'source_name', 'source_iban', 'source_type', 'destination_name', 'destination_iban', 'destination_type', 'reconciled', 'category', 'budget', 'bill', 'tags', 'notes'];
|
||||
|
||||
$metaFields = config('firefly.journal_meta_fields');
|
||||
$header = array_merge($header, $metaFields);
|
||||
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($this->user);
|
||||
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
|
||||
->withBudgetInformation()->withTagInformation()->withNotes();
|
||||
->withBudgetInformation()->withTagInformation()->withNotes()
|
||||
;
|
||||
if (0 !== $this->accounts->count()) {
|
||||
$collector->setAccounts($this->accounts);
|
||||
}
|
||||
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
// get repository for meta data:
|
||||
$repository = app(TransactionGroupRepositoryInterface::class);
|
||||
$repository->setUser($this->user);
|
||||
|
||||
$records = [];
|
||||
$records = [];
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
@ -772,7 +773,7 @@ class ExportDataGenerator
|
||||
}
|
||||
|
||||
// load the CSV document from a string
|
||||
$csv = Writer::createFromString();
|
||||
$csv = Writer::createFromString();
|
||||
|
||||
// insert the header
|
||||
try {
|
||||
|
@ -23,8 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Cache;
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
@ -39,9 +37,9 @@ class FireflyConfig
|
||||
{
|
||||
public function delete(string $name): void
|
||||
{
|
||||
$fullName = 'ff-config-' . $name;
|
||||
if (Cache::has($fullName)) {
|
||||
Cache::forget($fullName);
|
||||
$fullName = 'ff-config-'.$name;
|
||||
if (\Cache::has($fullName)) {
|
||||
\Cache::forget($fullName);
|
||||
}
|
||||
Configuration::where('name', $name)->forceDelete();
|
||||
}
|
||||
@ -81,20 +79,20 @@ class FireflyConfig
|
||||
*/
|
||||
public function get(string $name, $default = null): ?Configuration
|
||||
{
|
||||
$fullName = 'ff-config-' . $name;
|
||||
if (Cache::has($fullName)) {
|
||||
return Cache::get($fullName);
|
||||
$fullName = 'ff-config-'.$name;
|
||||
if (\Cache::has($fullName)) {
|
||||
return \Cache::get($fullName);
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var null|Configuration $config */
|
||||
$config = Configuration::where('name', $name)->first(['id', 'name', 'data']);
|
||||
} catch (Exception | QueryException $e) {
|
||||
} catch (\Exception|QueryException $e) {
|
||||
throw new FireflyException(sprintf('Could not poll the database: %s', $e->getMessage()), 0, $e);
|
||||
}
|
||||
|
||||
if (null !== $config) {
|
||||
Cache::forever($fullName, $config);
|
||||
\Cache::forever($fullName, $config);
|
||||
|
||||
return $config;
|
||||
}
|
||||
@ -124,13 +122,13 @@ class FireflyConfig
|
||||
$item->name = $name;
|
||||
$item->data = $value;
|
||||
$item->save();
|
||||
Cache::forget('ff-config-' . $name);
|
||||
\Cache::forget('ff-config-'.$name);
|
||||
|
||||
return $item;
|
||||
}
|
||||
$config->data = $value;
|
||||
$config->save();
|
||||
Cache::forget('ff-config-' . $name);
|
||||
\Cache::forget('ff-config-'.$name);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class AccountForm
|
||||
@ -69,7 +68,7 @@ class AccountForm
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$role = (string) $repository->getMetaValue($account, 'account_role');
|
||||
$role = (string) $repository->getMetaValue($account, 'account_role');
|
||||
if (in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||
$role = sprintf('l_%s', $account->accountType->type);
|
||||
}
|
||||
@ -94,9 +93,9 @@ class AccountForm
|
||||
*/
|
||||
public function activeWithdrawalDestinations(string $name, mixed $value = null, ?array $options = null): string
|
||||
{
|
||||
$types = [AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN, AccountType::EXPENSE];
|
||||
$repository = $this->getAccountRepository();
|
||||
$grouped = $this->getAccountsGrouped($types, $repository);
|
||||
$types = [AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN, AccountType::EXPENSE];
|
||||
$repository = $this->getAccountRepository();
|
||||
$grouped = $this->getAccountsGrouped($types, $repository);
|
||||
|
||||
$cash = $repository->getCashAccount();
|
||||
$key = (string) trans('firefly.cash_account_type');
|
||||
@ -112,21 +111,21 @@ class AccountForm
|
||||
*/
|
||||
public function assetAccountCheckList(string $name, ?array $options = null): string
|
||||
{
|
||||
$options ??= [];
|
||||
$options ??= [];
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$selected = request()->old($name) ?? [];
|
||||
|
||||
// get all asset accounts:
|
||||
$types = [AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT];
|
||||
$grouped = $this->getAccountsGrouped($types);
|
||||
$types = [AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT];
|
||||
$grouped = $this->getAccountsGrouped($types);
|
||||
|
||||
unset($options['class']);
|
||||
|
||||
try {
|
||||
$html = view('form.assetAccountCheckList', compact('classes', 'selected', 'name', 'label', 'options', 'grouped'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render assetAccountCheckList(): %s', $e->getMessage()));
|
||||
$html = 'Could not render assetAccountCheckList.';
|
||||
|
||||
|
@ -28,7 +28,6 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class CurrencyForm
|
||||
@ -62,15 +61,15 @@ class CurrencyForm
|
||||
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
|
||||
|
||||
/** @var Collection $currencies */
|
||||
$currencies = app('amount')->getCurrencies();
|
||||
$currencies = app('amount')->getCurrencies();
|
||||
unset($options['currency'], $options['placeholder']);
|
||||
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
|
||||
$preFilled = session('preFilled');
|
||||
$preFilled = session('preFilled');
|
||||
if (!is_array($preFilled)) {
|
||||
$preFilled = [];
|
||||
}
|
||||
$key = 'amount_currency_id_' . $name;
|
||||
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
||||
$key = 'amount_currency_id_'.$name;
|
||||
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
||||
|
||||
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
||||
|
||||
@ -90,8 +89,8 @@ class CurrencyForm
|
||||
}
|
||||
|
||||
try {
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
$html = view('form.'.$view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
||||
$html = 'Could not render currencyField.';
|
||||
|
||||
@ -130,16 +129,16 @@ class CurrencyForm
|
||||
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
|
||||
|
||||
/** @var Collection $currencies */
|
||||
$currencies = app('amount')->getAllCurrencies();
|
||||
$currencies = app('amount')->getAllCurrencies();
|
||||
unset($options['currency'], $options['placeholder']);
|
||||
|
||||
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
|
||||
$preFilled = session('preFilled');
|
||||
$preFilled = session('preFilled');
|
||||
if (!is_array($preFilled)) {
|
||||
$preFilled = [];
|
||||
}
|
||||
$key = 'amount_currency_id_' . $name;
|
||||
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
||||
$key = 'amount_currency_id_'.$name;
|
||||
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
||||
|
||||
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
||||
|
||||
@ -159,8 +158,8 @@ class CurrencyForm
|
||||
}
|
||||
|
||||
try {
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (Throwable $e) {
|
||||
$html = view('form.'.$view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
||||
$html = 'Could not render currencyField.';
|
||||
|
||||
@ -181,12 +180,12 @@ class CurrencyForm
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
// get all currencies:
|
||||
$list = $currencyRepos->get();
|
||||
$array = [];
|
||||
$list = $currencyRepos->get();
|
||||
$array = [];
|
||||
|
||||
/** @var TransactionCurrency $currency */
|
||||
foreach ($list as $currency) {
|
||||
$array[$currency->id] = $currency->name . ' (' . $currency->symbol . ')';
|
||||
$array[$currency->id] = $currency->name.' ('.$currency->symbol.')';
|
||||
}
|
||||
|
||||
return $this->select($name, $array, $value, $options);
|
||||
@ -203,14 +202,14 @@ class CurrencyForm
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
// get all currencies:
|
||||
$list = $currencyRepos->get();
|
||||
$array = [
|
||||
$list = $currencyRepos->get();
|
||||
$array = [
|
||||
0 => (string) trans('firefly.no_currency'),
|
||||
];
|
||||
|
||||
/** @var TransactionCurrency $currency */
|
||||
foreach ($list as $currency) {
|
||||
$array[$currency->id] = $currency->name . ' (' . $currency->symbol . ')';
|
||||
$array[$currency->id] = $currency->name.' ('.$currency->symbol.')';
|
||||
}
|
||||
|
||||
return $this->select($name, $array, $value, $options);
|
||||
|
@ -28,7 +28,6 @@ use Carbon\Carbon;
|
||||
use Carbon\Exceptions\InvalidDateException;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Trait FormSupport
|
||||
@ -37,7 +36,7 @@ trait FormSupport
|
||||
{
|
||||
public function multiSelect(string $name, ?array $list = null, $selected = null, ?array $options = null): string
|
||||
{
|
||||
$list ??= [];
|
||||
$list ??= [];
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
@ -47,7 +46,7 @@ trait FormSupport
|
||||
|
||||
try {
|
||||
$html = view('form.multi-select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render multi-select(): %s', $e->getMessage()));
|
||||
$html = 'Could not render multi-select.';
|
||||
}
|
||||
@ -63,7 +62,7 @@ trait FormSupport
|
||||
}
|
||||
$name = str_replace('[]', '', $name);
|
||||
|
||||
return (string) trans('form.' . $name);
|
||||
return (string) trans('form.'.$name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,10 +70,10 @@ trait FormSupport
|
||||
*/
|
||||
protected function expandOptionArray(string $name, $label, ?array $options = null): array
|
||||
{
|
||||
$options ??= [];
|
||||
$options ??= [];
|
||||
$name = str_replace('[]', '', $name);
|
||||
$options['class'] = 'form-control';
|
||||
$options['id'] = 'ffInput_' . $name;
|
||||
$options['id'] = 'ffInput_'.$name;
|
||||
$options['autocomplete'] = 'off';
|
||||
$options['placeholder'] = ucfirst($label);
|
||||
|
||||
@ -123,7 +122,7 @@ trait FormSupport
|
||||
*/
|
||||
public function select(string $name, ?array $list = null, $selected = null, ?array $options = null): string
|
||||
{
|
||||
$list ??= [];
|
||||
$list ??= [];
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
@ -132,7 +131,7 @@ trait FormSupport
|
||||
|
||||
try {
|
||||
$html = view('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Could not render select(): %s', $e->getMessage()));
|
||||
$html = 'Could not render select.';
|
||||
}
|
||||
|
@ -62,14 +62,14 @@ class PiggyBankForm
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggyBanks as $piggy) {
|
||||
$group = $piggy->objectGroups->first();
|
||||
$groupTitle = null;
|
||||
$groupOrder = 0;
|
||||
$group = $piggy->objectGroups->first();
|
||||
$groupTitle = null;
|
||||
$groupOrder = 0;
|
||||
if (null !== $group) {
|
||||
$groupTitle = $group->title;
|
||||
$groupOrder = $group->order;
|
||||
}
|
||||
$subList[$groupOrder] ??= [
|
||||
$subList[$groupOrder] ??= [
|
||||
'group' => [
|
||||
'title' => $groupTitle,
|
||||
],
|
||||
|
@ -41,8 +41,8 @@ class RuleForm
|
||||
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
||||
|
||||
// get all currencies:
|
||||
$list = $groupRepos->get();
|
||||
$array = [];
|
||||
$list = $groupRepos->get();
|
||||
$array = [];
|
||||
|
||||
/** @var RuleGroup $group */
|
||||
foreach ($list as $group) {
|
||||
@ -57,15 +57,15 @@ class RuleForm
|
||||
*/
|
||||
public function ruleGroupListWithEmpty(string $name, $value = null, ?array $options = null): string
|
||||
{
|
||||
$options ??= [];
|
||||
$options ??= [];
|
||||
$options['class'] = 'form-control';
|
||||
|
||||
/** @var RuleGroupRepositoryInterface $groupRepos */
|
||||
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
||||
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
||||
|
||||
// get all currencies:
|
||||
$list = $groupRepos->get();
|
||||
$array = [
|
||||
$list = $groupRepos->get();
|
||||
$array = [
|
||||
0 => (string) trans('firefly.none_in_select_list'),
|
||||
];
|
||||
|
||||
|
@ -64,7 +64,7 @@ class AccountBalanceGrouped
|
||||
/** @var array $currency */
|
||||
foreach ($this->data as $currency) {
|
||||
// income and expense array prepped:
|
||||
$income = [
|
||||
$income = [
|
||||
'label' => 'earned',
|
||||
'currency_id' => (string) $currency['currency_id'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
@ -81,7 +81,7 @@ class AccountBalanceGrouped
|
||||
'entries' => [],
|
||||
'native_entries' => [],
|
||||
];
|
||||
$expense = [
|
||||
$expense = [
|
||||
'label' => 'spent',
|
||||
'currency_id' => (string) $currency['currency_id'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
@ -101,22 +101,22 @@ class AccountBalanceGrouped
|
||||
// loop all possible periods between $start and $end, and add them to the correct dataset.
|
||||
$currentStart = clone $this->start;
|
||||
while ($currentStart <= $this->end) {
|
||||
$key = $currentStart->format($this->carbonFormat);
|
||||
$label = $currentStart->toAtomString();
|
||||
$key = $currentStart->format($this->carbonFormat);
|
||||
$label = $currentStart->toAtomString();
|
||||
// normal entries
|
||||
$income['entries'][$label] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
|
||||
$expense['entries'][$label] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
|
||||
$income['entries'][$label] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
|
||||
$expense['entries'][$label] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
|
||||
|
||||
// converted entries
|
||||
$income['native_entries'][$label] = app('steam')->bcround($currency[$key]['native_earned'] ?? '0', $currency['native_currency_decimal_places']);
|
||||
$expense['native_entries'][$label] = app('steam')->bcround($currency[$key]['native_spent'] ?? '0', $currency['native_currency_decimal_places']);
|
||||
|
||||
// next loop
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $this->preferredRange, 0);
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $this->preferredRange, 0);
|
||||
}
|
||||
|
||||
$chartData[] = $income;
|
||||
$chartData[] = $expense;
|
||||
$chartData[] = $income;
|
||||
$chartData[] = $expense;
|
||||
}
|
||||
|
||||
return $chartData;
|
||||
@ -142,9 +142,9 @@ class AccountBalanceGrouped
|
||||
private function processJournal(array $journal): void
|
||||
{
|
||||
// format the date according to the period
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currency = $this->findCurrency($currencyId);
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currency = $this->findCurrency($currencyId);
|
||||
|
||||
// set the array with monetary info, if it does not exist.
|
||||
$this->createDefaultDataEntry($journal);
|
||||
@ -152,12 +152,12 @@ class AccountBalanceGrouped
|
||||
$this->createDefaultPeriodEntry($journal);
|
||||
|
||||
// is this journal's amount in- our outgoing?
|
||||
$key = $this->getDataKey($journal);
|
||||
$amount = 'spent' === $key ? app('steam')->negative($journal['amount']) : app('steam')->positive($journal['amount']);
|
||||
$key = $this->getDataKey($journal);
|
||||
$amount = 'spent' === $key ? app('steam')->negative($journal['amount']) : app('steam')->positive($journal['amount']);
|
||||
|
||||
// get conversion rate
|
||||
$rate = $this->getRate($currency, $journal['date']);
|
||||
$amountConverted = bcmul($amount, $rate);
|
||||
$rate = $this->getRate($currency, $journal['date']);
|
||||
$amountConverted = bcmul($amount, $rate);
|
||||
|
||||
// perhaps transaction already has the foreign amount in the native currency.
|
||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||
@ -166,7 +166,7 @@ class AccountBalanceGrouped
|
||||
}
|
||||
|
||||
// add normal entry
|
||||
$this->data[$currencyId][$period][$key] = bcadd($this->data[$currencyId][$period][$key], $amount);
|
||||
$this->data[$currencyId][$period][$key] = bcadd($this->data[$currencyId][$period][$key], $amount);
|
||||
|
||||
// add converted entry
|
||||
$convertedKey = sprintf('native_%s', $key);
|
||||
@ -185,7 +185,7 @@ class AccountBalanceGrouped
|
||||
|
||||
private function createDefaultDataEntry(array $journal): void
|
||||
{
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$this->data[$currencyId] ??= [
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_symbol' => $journal['currency_symbol'],
|
||||
@ -202,8 +202,8 @@ class AccountBalanceGrouped
|
||||
|
||||
private function createDefaultPeriodEntry(array $journal): void
|
||||
{
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$period = $journal['date']->format($this->carbonFormat);
|
||||
$this->data[$currencyId][$period] ??= [
|
||||
'period' => $period,
|
||||
'spent' => '0',
|
||||
|
@ -25,7 +25,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support\Http\Api;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateTimeInterface;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
@ -46,7 +45,7 @@ trait ConvertsExchangeRates
|
||||
|
||||
// if not enabled, return the same array but without conversion:
|
||||
return $set;
|
||||
$this->enabled = false;
|
||||
$this->enabled = false;
|
||||
if (false === $this->enabled) {
|
||||
$set['converted'] = false;
|
||||
|
||||
@ -56,8 +55,8 @@ trait ConvertsExchangeRates
|
||||
$set['converted'] = true;
|
||||
|
||||
/** @var TransactionCurrency $native */
|
||||
$native = app('amount')->getDefaultCurrency();
|
||||
$currency = $this->getCurrency((int) $set['currency_id']);
|
||||
$native = app('amount')->getDefaultCurrency();
|
||||
$currency = $this->getCurrency((int) $set['currency_id']);
|
||||
if ($native->id === $currency->id) {
|
||||
$set['native_currency_id'] = (string) $currency->id;
|
||||
$set['native_currency_code'] = $currency->code;
|
||||
@ -67,9 +66,9 @@ trait ConvertsExchangeRates
|
||||
return $set;
|
||||
}
|
||||
foreach ($set['entries'] as $date => $entry) {
|
||||
$carbon = Carbon::createFromFormat(DateTimeInterface::ATOM, $date);
|
||||
$rate = $this->getRate($currency, $native, $carbon);
|
||||
$rate = '0' === $rate ? '1' : $rate;
|
||||
$carbon = Carbon::createFromFormat(\DateTimeInterface::ATOM, $date);
|
||||
$rate = $this->getRate($currency, $native, $carbon);
|
||||
$rate = '0' === $rate ? '1' : $rate;
|
||||
app('log')->debug(sprintf('bcmul("%s", "%s")', (string) $entry, $rate));
|
||||
$set['entries'][$date] = (float) bcmul((string) $entry, $rate);
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ class ExchangeRateConverter
|
||||
*/
|
||||
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||
{
|
||||
$key = $this->getCacheKey($from, $to, $date);
|
||||
$res = Cache::get($key, null);
|
||||
$key = $this->getCacheKey($from, $to, $date);
|
||||
$res = Cache::get($key, null);
|
||||
|
||||
// find in cache
|
||||
if (null !== $res) {
|
||||
@ -96,7 +96,7 @@ class ExchangeRateConverter
|
||||
}
|
||||
|
||||
// find in database
|
||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
Cache::forever($key, $rate);
|
||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||
@ -105,7 +105,7 @@ class ExchangeRateConverter
|
||||
}
|
||||
|
||||
// find reverse in database
|
||||
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
$rate = bcdiv('1', $rate);
|
||||
Cache::forever($key, $rate);
|
||||
@ -143,7 +143,7 @@ class ExchangeRateConverter
|
||||
if ($from === $to) {
|
||||
return '1';
|
||||
}
|
||||
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
||||
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
||||
|
||||
// perhaps the rate has been cached during this particular run
|
||||
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
||||
@ -153,7 +153,7 @@ class ExchangeRateConverter
|
||||
return $preparedRate;
|
||||
}
|
||||
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
$rate = $cache->get();
|
||||
@ -166,15 +166,16 @@ class ExchangeRateConverter
|
||||
}
|
||||
|
||||
/** @var null|CurrencyExchangeRate $result */
|
||||
$result = auth()->user()
|
||||
?->currencyExchangeRates()
|
||||
->where('from_currency_id', $from)
|
||||
->where('to_currency_id', $to)
|
||||
->where('date', '<=', $date)
|
||||
->orderBy('date', 'DESC')
|
||||
->first();
|
||||
$result = auth()->user()
|
||||
?->currencyExchangeRates()
|
||||
->where('from_currency_id', $from)
|
||||
->where('to_currency_id', $to)
|
||||
->where('date', '<=', $date)
|
||||
->orderBy('date', 'DESC')
|
||||
->first()
|
||||
;
|
||||
++$this->queryCount;
|
||||
$rate = (string) $result?->rate;
|
||||
$rate = (string) $result?->rate;
|
||||
|
||||
if ('' === $rate) {
|
||||
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
||||
@ -214,13 +215,13 @@ class ExchangeRateConverter
|
||||
if ($euroId === $currency->id) {
|
||||
return '1';
|
||||
}
|
||||
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
|
||||
|
||||
if (null !== $rate) {
|
||||
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
|
||||
return $rate;
|
||||
}
|
||||
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
|
||||
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
|
||||
if (null !== $rate) {
|
||||
return bcdiv('1', $rate);
|
||||
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate));
|
||||
@ -249,7 +250,7 @@ class ExchangeRateConverter
|
||||
if ($cache->has()) {
|
||||
return (int) $cache->get();
|
||||
}
|
||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||
++$this->queryCount;
|
||||
if (null === $euro) {
|
||||
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
||||
@ -271,13 +272,14 @@ class ExchangeRateConverter
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
$set = auth()->user()
|
||||
->currencyExchangeRates()
|
||||
->where('from_currency_id', $from->id)
|
||||
->where('to_currency_id', $to->id)
|
||||
->where('date', '<=', $end->format('Y-m-d'))
|
||||
->where('date', '>=', $start->format('Y-m-d'))
|
||||
->orderBy('date', 'DESC')->get();
|
||||
$set = auth()->user()
|
||||
->currencyExchangeRates()
|
||||
->where('from_currency_id', $from->id)
|
||||
->where('to_currency_id', $to->id)
|
||||
->where('date', '<=', $end->format('Y-m-d'))
|
||||
->where('date', '>=', $start->format('Y-m-d'))
|
||||
->orderBy('date', 'DESC')->get()
|
||||
;
|
||||
++$this->queryCount;
|
||||
if (0 === $set->count()) {
|
||||
Log::debug('No prepared rates found in this period, use the fallback');
|
||||
@ -291,10 +293,10 @@ class ExchangeRateConverter
|
||||
$this->isPrepared = true;
|
||||
|
||||
// so there is a fallback just in case. Now loop the set of rates we DO have.
|
||||
$temp = [];
|
||||
$count = 0;
|
||||
$temp = [];
|
||||
$count = 0;
|
||||
foreach ($set as $rate) {
|
||||
$date = $rate->date->format('Y-m-d');
|
||||
$date = $rate->date->format('Y-m-d');
|
||||
$temp[$date] ??= [
|
||||
$from->id => [
|
||||
$to->id => $rate->rate,
|
||||
@ -303,11 +305,11 @@ class ExchangeRateConverter
|
||||
++$count;
|
||||
}
|
||||
Log::debug(sprintf('Found %d rates in this period.', $count));
|
||||
$currentStart = clone $start;
|
||||
$currentStart = clone $start;
|
||||
while ($currentStart->lte($end)) {
|
||||
$currentDate = $currentStart->format('Y-m-d');
|
||||
$currentDate = $currentStart->format('Y-m-d');
|
||||
$this->prepared[$currentDate] ??= [];
|
||||
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
|
||||
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
|
||||
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
|
||||
// fill from temp or fallback or from temp (see before)
|
||||
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
|
||||
|
@ -40,7 +40,7 @@ trait ParsesQueryFilters
|
||||
|
||||
private function dateOrToday(QueryParameters $parameters, string $field): Carbon
|
||||
{
|
||||
$date = today();
|
||||
$date = today();
|
||||
|
||||
$value = $parameters->filter()?->value($field, date('Y-m-d'));
|
||||
|
||||
|
@ -30,7 +30,7 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SummaryBalanceGrouped
|
||||
{
|
||||
private const string SUM = 'sum';
|
||||
private const string SUM = 'sum';
|
||||
private array $amounts = [];
|
||||
private array $currencies;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
@ -47,9 +47,9 @@ class SummaryBalanceGrouped
|
||||
public function groupData(): array
|
||||
{
|
||||
Log::debug('Now going to group data.');
|
||||
$return = [];
|
||||
$return = [];
|
||||
foreach ($this->keys as $key) {
|
||||
$title = match ($key) {
|
||||
$title = match ($key) {
|
||||
'sum' => 'balance',
|
||||
'expense' => 'spent',
|
||||
'income' => 'earned',
|
||||
@ -108,11 +108,11 @@ class SummaryBalanceGrouped
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
// transaction info:
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$amount = bcmul($journal['amount'], $multiplier);
|
||||
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = $currency;
|
||||
$nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$amount = bcmul($journal['amount'], $multiplier);
|
||||
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = $currency;
|
||||
$nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||
// use foreign amount instead
|
||||
$nativeAmount = $journal['foreign_amount'];
|
||||
|
@ -56,8 +56,8 @@ trait ValidatesUserGroupTrait
|
||||
}
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$groupId = 0;
|
||||
$user = auth()->user();
|
||||
$groupId = 0;
|
||||
if (!$request->has('user_group_id')) {
|
||||
$groupId = $user->user_group_id;
|
||||
Log::debug(sprintf('validateUserGroup: no user group submitted, use default group #%d.', $groupId));
|
||||
@ -68,7 +68,7 @@ trait ValidatesUserGroupTrait
|
||||
}
|
||||
|
||||
/** @var UserGroupRepositoryInterface $repository */
|
||||
$repository = app(UserGroupRepositoryInterface::class);
|
||||
$repository = app(UserGroupRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
$memberships = $repository->getMembershipsFromGroupId($groupId);
|
||||
|
||||
@ -79,14 +79,14 @@ trait ValidatesUserGroupTrait
|
||||
}
|
||||
|
||||
// need to get the group from the membership:
|
||||
$group = $repository->getById($groupId);
|
||||
$group = $repository->getById($groupId);
|
||||
if (null === $group) {
|
||||
Log::debug(sprintf('validateUserGroup: group #%d does not exist.', $groupId));
|
||||
|
||||
throw new AuthorizationException((string) trans('validation.belongs_user_or_user_group'));
|
||||
}
|
||||
Log::debug(sprintf('validateUserGroup: validate access of user to group #%d ("%s").', $groupId, $group->title));
|
||||
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : []; // @phpstan-ignore-line
|
||||
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : []; // @phpstan-ignore-line
|
||||
if (0 === count($roles)) {
|
||||
Log::debug('validateUserGroup: no roles defined, so no access.');
|
||||
|
||||
|
@ -55,10 +55,10 @@ trait AugumentData
|
||||
|
||||
/** @var Account $expenseAccount */
|
||||
foreach ($accounts as $expenseAccount) {
|
||||
$collection = new Collection();
|
||||
$collection = new Collection();
|
||||
$collection->push($expenseAccount);
|
||||
|
||||
$revenue = $repository->findByName($expenseAccount->name, [AccountType::REVENUE]);
|
||||
$revenue = $repository->findByName($expenseAccount->name, [AccountType::REVENUE]);
|
||||
if (null !== $revenue) {
|
||||
$collection->push($revenue);
|
||||
}
|
||||
@ -115,7 +115,7 @@ trait AugumentData
|
||||
$return[$accountId] = $grouped[$accountId][0]['name'];
|
||||
}
|
||||
}
|
||||
$return[0] = '(no name)';
|
||||
$return[0] = '(no name)';
|
||||
|
||||
return $return;
|
||||
}
|
||||
@ -135,7 +135,7 @@ trait AugumentData
|
||||
$return[$budgetId] = $grouped[$budgetId][0]['name'];
|
||||
}
|
||||
}
|
||||
$return[0] = (string) trans('firefly.no_budget');
|
||||
$return[0] = (string) trans('firefly.no_budget');
|
||||
|
||||
return $return;
|
||||
}
|
||||
@ -157,7 +157,7 @@ trait AugumentData
|
||||
$return[$categoryId] = $grouped[$categoryId][0]['name'];
|
||||
}
|
||||
}
|
||||
$return[0] = (string) trans('firefly.no_category');
|
||||
$return[0] = (string) trans('firefly.no_category');
|
||||
|
||||
return $return;
|
||||
}
|
||||
@ -168,14 +168,14 @@ trait AugumentData
|
||||
protected function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection // get data + augment with info
|
||||
{
|
||||
/** @var OperationsRepositoryInterface $opsRepository */
|
||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||
|
||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
|
||||
$end->endOfMonth();
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($budget->id);
|
||||
@ -191,7 +191,7 @@ trait AugumentData
|
||||
|
||||
/** @var BudgetLimit $entry */
|
||||
foreach ($set as $entry) {
|
||||
$currency = $entry->transactionCurrency;
|
||||
$currency = $entry->transactionCurrency;
|
||||
|
||||
if (null === $currency) {
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
@ -227,7 +227,7 @@ trait AugumentData
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($array as $journal) {
|
||||
$name = '(no name)';
|
||||
$name = '(no name)';
|
||||
if (TransactionType::WITHDRAWAL === $journal['transaction_type_type']) {
|
||||
$name = $journal['destination_account_name'];
|
||||
}
|
||||
@ -250,16 +250,16 @@ trait AugumentData
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
|
||||
$total = $assets->merge($opposing);
|
||||
$total = $assets->merge($opposing);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($total);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$sum = [
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$sum = [
|
||||
'grand_sum' => '0',
|
||||
'per_currency' => [],
|
||||
];
|
||||
// loop to support multi currency
|
||||
foreach ($journals as $journal) {
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
|
||||
// if not set, set to zero:
|
||||
if (!array_key_exists($currencyId, $sum['per_currency'])) {
|
||||
|
@ -46,7 +46,7 @@ trait ChartGeneration
|
||||
protected function accountBalanceChart(Collection $accounts, Carbon $start, Carbon $end): array // chart helper method.
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('chart.account.account-balance-chart');
|
||||
@ -56,21 +56,21 @@ trait ChartGeneration
|
||||
// return $cache->get();
|
||||
}
|
||||
app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.');
|
||||
$locale = app('steam')->getLocale();
|
||||
$locale = app('steam')->getLocale();
|
||||
|
||||
/** @var GeneratorInterface $generator */
|
||||
$generator = app(GeneratorInterface::class);
|
||||
$generator = app(GeneratorInterface::class);
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
$chartData = [];
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
$chartData = [];
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
// TODO we can use getAccountCurrency instead.
|
||||
$currency = $accountRepos->getAccountCurrency($account);
|
||||
$currency = $accountRepos->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
$currency = $default;
|
||||
}
|
||||
@ -79,7 +79,7 @@ trait ChartGeneration
|
||||
$currency = $default;
|
||||
}
|
||||
|
||||
$currentSet = [
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'entries' => [],
|
||||
@ -89,16 +89,16 @@ trait ChartGeneration
|
||||
$range = Steam::finalAccountBalanceInRange($account, $start, clone $end);
|
||||
$previous = array_values($range)[0];
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = trim($currentStart->isoFormat((string) trans('config.month_and_day_js', [], $locale)));
|
||||
$balance = $range[$format] ?? $previous;
|
||||
$previous = $balance;
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = trim($currentStart->isoFormat((string) trans('config.month_and_day_js', [], $locale)));
|
||||
$balance = $range[$format] ?? $previous;
|
||||
$previous = $balance;
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance['balance']; // TODO or native_balance
|
||||
}
|
||||
$chartData[] = $currentSet;
|
||||
$chartData[] = $currentSet;
|
||||
}
|
||||
$data = $generator->multiSet($chartData);
|
||||
$data = $generator->multiSet($chartData);
|
||||
$cache->store($data);
|
||||
|
||||
return $data;
|
||||
|
@ -102,7 +102,7 @@ trait CreateStuff
|
||||
return;
|
||||
}
|
||||
|
||||
$key = RSA::createKey(4096);
|
||||
$key = RSA::createKey(4096);
|
||||
|
||||
Log::alert('NO OAuth keys were found. They have been created.');
|
||||
|
||||
|
@ -90,19 +90,19 @@ trait DateCalculation
|
||||
protected function getNextPeriods(Carbon $date, string $range): array
|
||||
{
|
||||
// select thing for next 12 periods:
|
||||
$loop = [];
|
||||
$loop = [];
|
||||
|
||||
/** @var Carbon $current */
|
||||
$current = app('navigation')->startOfPeriod($date, $range);
|
||||
$current = app('navigation')->endOfPeriod($current, $range);
|
||||
$current->addDay();
|
||||
$count = 0;
|
||||
$count = 0;
|
||||
|
||||
while ($count < 12) {
|
||||
$current = app('navigation')->endOfPeriod($current, $range);
|
||||
$currentStart = app('navigation')->startOfPeriod($current, $range);
|
||||
|
||||
$loop[] = [
|
||||
$loop[] = [
|
||||
'label' => $current->format('Y-m-d'),
|
||||
'title' => app('navigation')->periodShow($current, $range),
|
||||
'start' => clone $currentStart,
|
||||
@ -122,7 +122,7 @@ trait DateCalculation
|
||||
protected function getPreviousPeriods(Carbon $date, string $range): array
|
||||
{
|
||||
// select thing for last 12 periods:
|
||||
$loop = [];
|
||||
$loop = [];
|
||||
|
||||
/** @var Carbon $current */
|
||||
$current = app('navigation')->startOfPeriod($date, $range);
|
||||
|
@ -61,13 +61,13 @@ trait GetConfigurationData
|
||||
$steps = [];
|
||||
if (is_array($elements) && count($elements) > 0) {
|
||||
foreach ($elements as $key => $options) {
|
||||
$currentStep = $options;
|
||||
$currentStep = $options;
|
||||
|
||||
// get the text:
|
||||
$currentStep['intro'] = (string) trans('intro.' . $route . '_' . $key);
|
||||
$currentStep['intro'] = (string) trans('intro.'.$route.'_'.$key);
|
||||
|
||||
// save in array:
|
||||
$steps[] = $currentStep;
|
||||
$steps[] = $currentStep;
|
||||
}
|
||||
}
|
||||
app('log')->debug(sprintf('Total basic steps for %s is %d', $routeKey, count($steps)));
|
||||
@ -82,22 +82,22 @@ trait GetConfigurationData
|
||||
*/
|
||||
protected function getDateRangeConfig(): array // get configuration + get preferences.
|
||||
{
|
||||
$viewRange = app('navigation')->getViewRange(false);
|
||||
$viewRange = app('navigation')->getViewRange(false);
|
||||
|
||||
Log::debug(sprintf('dateRange: the view range is "%s"', $viewRange));
|
||||
|
||||
/** @var Carbon $start */
|
||||
$start = session('start');
|
||||
$start = session('start');
|
||||
|
||||
/** @var Carbon $end */
|
||||
$end = session('end');
|
||||
$end = session('end');
|
||||
|
||||
/** @var Carbon $first */
|
||||
$first = session('first');
|
||||
$title = sprintf('%s - %s', $start->isoFormat($this->monthAndDayFormat), $end->isoFormat($this->monthAndDayFormat));
|
||||
$isCustom = true === session('is_custom_range', false);
|
||||
$today = today(config('app.timezone'));
|
||||
$ranges = [
|
||||
$first = session('first');
|
||||
$title = sprintf('%s - %s', $start->isoFormat($this->monthAndDayFormat), $end->isoFormat($this->monthAndDayFormat));
|
||||
$isCustom = true === session('is_custom_range', false);
|
||||
$today = today(config('app.timezone'));
|
||||
$ranges = [
|
||||
// first range is the current range:
|
||||
$title => [$start, $end],
|
||||
];
|
||||
@ -127,10 +127,10 @@ trait GetConfigurationData
|
||||
|
||||
// today:
|
||||
/** @var Carbon $todayStart */
|
||||
$todayStart = app('navigation')->startOfPeriod($today, $viewRange);
|
||||
$todayStart = app('navigation')->startOfPeriod($today, $viewRange);
|
||||
|
||||
/** @var Carbon $todayEnd */
|
||||
$todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange);
|
||||
$todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange);
|
||||
|
||||
if ($todayStart->ne($start) || $todayEnd->ne($end)) {
|
||||
$ranges[ucfirst((string) trans('firefly.today'))] = [$todayStart, $todayEnd];
|
||||
@ -186,16 +186,16 @@ trait GetConfigurationData
|
||||
// user is on page with specific instructions:
|
||||
if ('' !== $specificPage) {
|
||||
$routeKey = str_replace('.', '_', $route);
|
||||
$elements = config(sprintf('intro.%s', $routeKey . '_' . $specificPage));
|
||||
$elements = config(sprintf('intro.%s', $routeKey.'_'.$specificPage));
|
||||
if (is_array($elements) && count($elements) > 0) {
|
||||
foreach ($elements as $key => $options) {
|
||||
$currentStep = $options;
|
||||
$currentStep = $options;
|
||||
|
||||
// get the text:
|
||||
$currentStep['intro'] = (string) trans('intro.' . $route . '_' . $specificPage . '_' . $key);
|
||||
$currentStep['intro'] = (string) trans('intro.'.$route.'_'.$specificPage.'_'.$key);
|
||||
|
||||
// save in array:
|
||||
$steps[] = $currentStep;
|
||||
$steps[] = $currentStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Trait ModelInformation
|
||||
@ -56,7 +55,7 @@ trait ModelInformation
|
||||
'count' => 1,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
$result = 'Could not render view. See log files.';
|
||||
@ -75,14 +74,14 @@ trait ModelInformation
|
||||
protected function getLiabilityTypes(): array
|
||||
{
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
|
||||
// types of liability:
|
||||
/** @var AccountType $debt */
|
||||
$debt = $repository->getAccountTypeByType(AccountType::DEBT);
|
||||
$debt = $repository->getAccountTypeByType(AccountType::DEBT);
|
||||
|
||||
/** @var AccountType $loan */
|
||||
$loan = $repository->getAccountTypeByType(AccountType::LOAN);
|
||||
$loan = $repository->getAccountTypeByType(AccountType::LOAN);
|
||||
|
||||
/** @var AccountType $mortgage */
|
||||
$mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE);
|
||||
@ -114,8 +113,8 @@ trait ModelInformation
|
||||
protected function getTriggersForBill(Bill $bill): array // get info and argument
|
||||
{
|
||||
// TODO duplicate code
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
foreach ($operators as $key => $operator) {
|
||||
if ('user_action' !== $key && false === $operator['alias']) {
|
||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||
@ -143,7 +142,7 @@ trait ModelInformation
|
||||
'triggers' => $triggers,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
|
||||
app('log')->debug($e->getTraceAsString());
|
||||
|
||||
@ -165,8 +164,8 @@ trait ModelInformation
|
||||
private function getTriggersForJournal(TransactionJournal $journal): array
|
||||
{
|
||||
// TODO duplicated code.
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
foreach ($operators as $key => $operator) {
|
||||
if ('user_action' !== $key && false === $operator['alias']) {
|
||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||
@ -174,18 +173,18 @@ trait ModelInformation
|
||||
}
|
||||
asort($triggers);
|
||||
|
||||
$result = [];
|
||||
$journalTriggers = [];
|
||||
$values = [];
|
||||
$index = 0;
|
||||
$result = [];
|
||||
$journalTriggers = [];
|
||||
$values = [];
|
||||
$index = 0;
|
||||
|
||||
// amount, description, category, budget, tags, source, destination, notes, currency type
|
||||
// ,type
|
||||
/** @var null|Transaction $source */
|
||||
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
|
||||
/** @var null|Transaction $destination */
|
||||
$destination = $journal->transactions()->where('amount', '>', 0)->first();
|
||||
$destination = $journal->transactions()->where('amount', '>', 0)->first();
|
||||
if (null === $destination || null === $source) {
|
||||
return $result;
|
||||
}
|
||||
@ -220,21 +219,21 @@ trait ModelInformation
|
||||
++$index;
|
||||
|
||||
// category (if)
|
||||
$category = $journal->categories()->first();
|
||||
$category = $journal->categories()->first();
|
||||
if (null !== $category) {
|
||||
$journalTriggers[$index] = 'category_is';
|
||||
$values[$index] = $category->name;
|
||||
++$index;
|
||||
}
|
||||
// budget (if)
|
||||
$budget = $journal->budgets()->first();
|
||||
$budget = $journal->budgets()->first();
|
||||
if (null !== $budget) {
|
||||
$journalTriggers[$index] = 'budget_is';
|
||||
$values[$index] = $budget->name;
|
||||
++$index;
|
||||
}
|
||||
// tags (if)
|
||||
$tags = $journal->tags()->get();
|
||||
$tags = $journal->tags()->get();
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
@ -243,7 +242,7 @@ trait ModelInformation
|
||||
++$index;
|
||||
}
|
||||
// notes (if)
|
||||
$notes = $journal->notes()->first();
|
||||
$notes = $journal->notes()->first();
|
||||
if (null !== $notes) {
|
||||
$journalTriggers[$index] = 'notes_are';
|
||||
$values[$index] = $notes->text;
|
||||
@ -259,7 +258,7 @@ trait ModelInformation
|
||||
'triggers' => $triggers,
|
||||
];
|
||||
$string = view('rules.partials.trigger', $renderInfo)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Throwable was thrown in getTriggersForJournal(): %s', $e->getMessage()));
|
||||
app('log')->debug($e->getTraceAsString());
|
||||
|
||||
|
@ -75,11 +75,11 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('account-show-period-entries');
|
||||
@ -89,32 +89,32 @@ trait PeriodOverview
|
||||
}
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// collect all expenses in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]));
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all income in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]));
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all transfers in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]));
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::TRANSFER]);
|
||||
$transferSet = $collector->getExtractedJournals();
|
||||
$transferSet = $collector->getExtractedJournals();
|
||||
|
||||
// loop dates
|
||||
foreach ($dates as $currentDate) {
|
||||
@ -125,15 +125,15 @@ trait PeriodOverview
|
||||
$transferredIn = $this->filterTransferredIn($account, $this->filterJournalsByDate($transferSet, $currentDate['start'], $currentDate['end']));
|
||||
$entries[]
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('accounts.show', [$account->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'title' => $title,
|
||||
'route' => route('accounts.show', [$account->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferredAway) + count($transferredIn),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred_away' => $this->groupByCurrency($transferredAway),
|
||||
'transferred_in' => $this->groupByCurrency($transferredIn),
|
||||
];
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferredAway) + count($transferredIn),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred_away' => $this->groupByCurrency($transferredAway),
|
||||
'transferred_in' => $this->groupByCurrency($transferredIn),
|
||||
];
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
@ -197,8 +197,8 @@ trait PeriodOverview
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = $journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = $journal['foreign_currency_id'];
|
||||
if (!array_key_exists($currencyId, $return)) {
|
||||
$return[$currencyId] = [
|
||||
'amount' => '0',
|
||||
@ -240,11 +240,11 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getCategoryPeriodOverview(Category $category, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for entries with their amounts.
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($range);
|
||||
@ -256,32 +256,32 @@ trait PeriodOverview
|
||||
}
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// collect all expenses in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setCategory($category);
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all income in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setCategory($category);
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all transfers in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setCategory($category);
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::TRANSFER]);
|
||||
$transferSet = $collector->getExtractedJournals();
|
||||
$transferSet = $collector->getExtractedJournals();
|
||||
foreach ($dates as $currentDate) {
|
||||
$spent = $this->filterJournalsByDate($spentSet, $currentDate['start'], $currentDate['end']);
|
||||
$earned = $this->filterJournalsByDate($earnedSet, $currentDate['start'], $currentDate['end']);
|
||||
@ -289,17 +289,17 @@ trait PeriodOverview
|
||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||
$entries[]
|
||||
= [
|
||||
'transactions' => 0,
|
||||
'title' => $title,
|
||||
'route' => route(
|
||||
'categories.show',
|
||||
[$category->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
||||
),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
'transactions' => 0,
|
||||
'title' => $title,
|
||||
'route' => route(
|
||||
'categories.show',
|
||||
[$category->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
||||
),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
@ -315,11 +315,11 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getNoBudgetPeriodOverview(Carbon $start, Carbon $end): array
|
||||
{
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('no-budget-period-entries');
|
||||
@ -329,28 +329,28 @@ trait PeriodOverview
|
||||
}
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// get all expenses without a budget.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->withoutBudget()->withAccountInformation()->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($dates as $currentDate) {
|
||||
$set = $this->filterJournalsByDate($journals, $currentDate['start'], $currentDate['end']);
|
||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||
$entries[]
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('budgets.no-budget', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($set),
|
||||
'spent' => $this->groupByCurrency($set),
|
||||
'earned' => [],
|
||||
'transferred_away' => [],
|
||||
'transferred_in' => [],
|
||||
];
|
||||
'title' => $title,
|
||||
'route' => route('budgets.no-budget', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($set),
|
||||
'spent' => $this->groupByCurrency($set),
|
||||
'earned' => [],
|
||||
'transferred_away' => [],
|
||||
'transferred_in' => [],
|
||||
];
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
@ -367,38 +367,38 @@ trait PeriodOverview
|
||||
protected function getNoCategoryPeriodOverview(Carbon $theDate): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d')));
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$first = $this->journalRepos->firstNull();
|
||||
$start = null === $first ? new Carbon() : $first->date;
|
||||
$end = clone $theDate;
|
||||
$end = app('navigation')->endOfPeriod($end, $range);
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$first = $this->journalRepos->firstNull();
|
||||
$start = null === $first ? new Carbon() : $first->date;
|
||||
$end = clone $theDate;
|
||||
$end = app('navigation')->endOfPeriod($end, $range);
|
||||
|
||||
app('log')->debug(sprintf('Start for getNoCategoryPeriodOverview() is %s', $start->format('Y-m-d')));
|
||||
app('log')->debug(sprintf('End for getNoCategoryPeriodOverview() is %s', $end->format('Y-m-d')));
|
||||
|
||||
// properties for cache
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// collect all expenses in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->withoutCategory();
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all income in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->withoutCategory();
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all transfers in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->withoutCategory();
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::TRANSFER]);
|
||||
@ -412,13 +412,13 @@ trait PeriodOverview
|
||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||
$entries[]
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('categories.no-category', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
'title' => $title,
|
||||
'route' => route('categories.no-category', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
}
|
||||
app('log')->debug('End of loops');
|
||||
|
||||
@ -432,11 +432,11 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getTagPeriodOverview(Tag $tag, Carbon $start, Carbon $end): array // period overview for tags.
|
||||
{
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('tag-period-entries');
|
||||
@ -446,37 +446,37 @@ trait PeriodOverview
|
||||
}
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// collect all expenses in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTag($tag);
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
$earnedSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all income in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTag($tag);
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
$spentSet = $collector->getExtractedJournals();
|
||||
|
||||
// collect all transfers in this period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTag($tag);
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::TRANSFER]);
|
||||
$transferSet = $collector->getExtractedJournals();
|
||||
$transferSet = $collector->getExtractedJournals();
|
||||
|
||||
// filer all of them:
|
||||
$earnedSet = $this->filterJournalsByTag($earnedSet, $tag);
|
||||
$spentSet = $this->filterJournalsByTag($spentSet, $tag);
|
||||
$transferSet = $this->filterJournalsByTag($transferSet, $tag);
|
||||
$earnedSet = $this->filterJournalsByTag($earnedSet, $tag);
|
||||
$spentSet = $this->filterJournalsByTag($spentSet, $tag);
|
||||
$transferSet = $this->filterJournalsByTag($transferSet, $tag);
|
||||
|
||||
foreach ($dates as $currentDate) {
|
||||
$spent = $this->filterJournalsByDate($spentSet, $currentDate['start'], $currentDate['end']);
|
||||
@ -485,17 +485,17 @@ trait PeriodOverview
|
||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||
$entries[]
|
||||
= [
|
||||
'transactions' => 0,
|
||||
'title' => $title,
|
||||
'route' => route(
|
||||
'tags.show',
|
||||
[$tag->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
||||
),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
'transactions' => 0,
|
||||
'title' => $title,
|
||||
'route' => route(
|
||||
'tags.show',
|
||||
[$tag->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
||||
),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
}
|
||||
|
||||
return $entries;
|
||||
@ -505,7 +505,7 @@ trait PeriodOverview
|
||||
{
|
||||
$return = [];
|
||||
foreach ($set as $entry) {
|
||||
$found = false;
|
||||
$found = false;
|
||||
|
||||
/** @var array $localTag */
|
||||
foreach ($entry['tags'] as $localTag) {
|
||||
@ -527,12 +527,12 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('transactions-period-entries');
|
||||
@ -542,13 +542,13 @@ trait PeriodOverview
|
||||
}
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
|
||||
// collect all journals in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes($types)->setRange($start, $end);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($dates as $currentDate) {
|
||||
$spent = [];
|
||||
@ -567,14 +567,14 @@ trait PeriodOverview
|
||||
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
$entries[]
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
= [
|
||||
'title' => $title,
|
||||
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
}
|
||||
|
||||
return $entries;
|
||||
|
@ -37,7 +37,6 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Trait RenderPartialViews
|
||||
@ -52,24 +51,24 @@ trait RenderPartialViews
|
||||
protected function budgetEntry(array $attributes): string // generate view for report.
|
||||
{
|
||||
/** @var PopupReportInterface $popupHelper */
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
|
||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budget = $budgetRepository->find((int) $attributes['budgetId']);
|
||||
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$account = $accountRepos->find((int) $attributes['accountId']);
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$account = $accountRepos->find((int) $attributes['accountId']);
|
||||
|
||||
if (null === $budget || null === $account) {
|
||||
throw new FireflyException('Could not render popup.report.balance-amount because budget or account is null.');
|
||||
}
|
||||
|
||||
$journals = $popupHelper->balanceForBudget($budget, $account, $attributes);
|
||||
$journals = $popupHelper->balanceForBudget($budget, $account, $attributes);
|
||||
|
||||
try {
|
||||
$view = view('popup.report.balance-amount', compact('journals', 'budget', 'account'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||
|
||||
@ -92,7 +91,7 @@ trait RenderPartialViews
|
||||
|
||||
try {
|
||||
$result = view('reports.options.budget', compact('budgets'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage()));
|
||||
$result = 'Could not render view.';
|
||||
|
||||
@ -113,18 +112,18 @@ trait RenderPartialViews
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
/** @var PopupReportInterface $popupHelper */
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
|
||||
$budget = $budgetRepository->find((int) $attributes['budgetId']);
|
||||
$budget = $budgetRepository->find((int) $attributes['budgetId']);
|
||||
if (null === $budget) {
|
||||
// transactions without a budget.
|
||||
$budget = new Budget();
|
||||
}
|
||||
$journals = $popupHelper->byBudget($budget, $attributes);
|
||||
$journals = $popupHelper->byBudget($budget, $attributes);
|
||||
|
||||
try {
|
||||
$view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||
|
||||
@ -142,7 +141,7 @@ trait RenderPartialViews
|
||||
protected function categoryEntry(array $attributes): string // generate view for report.
|
||||
{
|
||||
/** @var PopupReportInterface $popupHelper */
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
|
||||
/** @var CategoryRepositoryInterface $categoryRepository */
|
||||
$categoryRepository = app(CategoryRepositoryInterface::class);
|
||||
@ -151,7 +150,7 @@ trait RenderPartialViews
|
||||
|
||||
try {
|
||||
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||
|
||||
@ -174,7 +173,7 @@ trait RenderPartialViews
|
||||
|
||||
try {
|
||||
$result = view('reports.options.category', compact('categories'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Cannot render reports.options.category: %s', $e->getMessage()));
|
||||
$result = 'Could not render view.';
|
||||
|
||||
@ -216,7 +215,7 @@ trait RenderPartialViews
|
||||
|
||||
try {
|
||||
$result = view('reports.options.double', compact('set'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage()));
|
||||
$result = 'Could not render view.';
|
||||
|
||||
@ -237,19 +236,19 @@ trait RenderPartialViews
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
/** @var PopupReportInterface $popupHelper */
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
|
||||
$account = $accountRepository->find((int) $attributes['accountId']);
|
||||
$account = $accountRepository->find((int) $attributes['accountId']);
|
||||
|
||||
if (null === $account) {
|
||||
return 'This is an unknown account. Apologies.';
|
||||
}
|
||||
|
||||
$journals = $popupHelper->byExpenses($account, $attributes);
|
||||
$journals = $popupHelper->byExpenses($account, $attributes);
|
||||
|
||||
try {
|
||||
$view = view('popup.report.expense-entry', compact('journals', 'account'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||
|
||||
@ -266,8 +265,8 @@ trait RenderPartialViews
|
||||
*/
|
||||
protected function getCurrentActions(Rule $rule): array // get info from object and present.
|
||||
{
|
||||
$index = 0;
|
||||
$actions = [];
|
||||
$index = 0;
|
||||
$actions = [];
|
||||
// must be repos
|
||||
$currentActions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
||||
|
||||
@ -285,7 +284,7 @@ trait RenderPartialViews
|
||||
'count' => $count,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
|
||||
@ -306,8 +305,8 @@ trait RenderPartialViews
|
||||
protected function getCurrentTriggers(Rule $rule): array // get info from object and present.
|
||||
{
|
||||
// TODO duplicated code.
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
foreach ($operators as $key => $operator) {
|
||||
if ('user_action' !== $key && false === $operator['alias']) {
|
||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||
@ -325,7 +324,7 @@ trait RenderPartialViews
|
||||
$count = ($index + 1);
|
||||
|
||||
try {
|
||||
$rootOperator = OperatorQuerySearch::getRootOperator((string) $entry->trigger_type);
|
||||
$rootOperator = OperatorQuerySearch::getRootOperator((string) $entry->trigger_type);
|
||||
if (str_starts_with($rootOperator, '-')) {
|
||||
$rootOperator = substr($rootOperator, 1);
|
||||
}
|
||||
@ -340,7 +339,7 @@ trait RenderPartialViews
|
||||
'triggers' => $triggers,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
|
||||
@ -365,18 +364,18 @@ trait RenderPartialViews
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
/** @var PopupReportInterface $popupHelper */
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
$account = $accountRepository->find((int) $attributes['accountId']);
|
||||
$popupHelper = app(PopupReportInterface::class);
|
||||
$account = $accountRepository->find((int) $attributes['accountId']);
|
||||
|
||||
if (null === $account) {
|
||||
return 'This is an unknown category. Apologies.';
|
||||
}
|
||||
|
||||
$journals = $popupHelper->byIncome($account, $attributes);
|
||||
$journals = $popupHelper->byIncome($account, $attributes);
|
||||
|
||||
try {
|
||||
$view = view('popup.report.income-entry', compact('journals', 'account'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||
|
||||
@ -395,7 +394,7 @@ trait RenderPartialViews
|
||||
{
|
||||
try {
|
||||
$result = view('reports.options.no-options')->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Cannot render reports.options.no-options: %s', $e->getMessage()));
|
||||
$result = 'Could not render view.';
|
||||
|
||||
@ -418,7 +417,7 @@ trait RenderPartialViews
|
||||
|
||||
try {
|
||||
$result = view('reports.options.tag', compact('tags'))->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage()));
|
||||
$result = 'Could not render view.';
|
||||
|
||||
|
@ -30,7 +30,6 @@ use FireflyIII\Http\Requests\RuleFormRequest;
|
||||
use FireflyIII\Http\Requests\TestRuleFormRequest;
|
||||
use FireflyIII\Support\Binder\AccountList;
|
||||
use FireflyIII\User;
|
||||
use Hash;
|
||||
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
@ -83,13 +82,13 @@ trait RequestInformation
|
||||
$page = $this->getPageName();
|
||||
$specificPage = $this->getSpecificPageName();
|
||||
// indicator if user has seen the help for this page ( + special page):
|
||||
$key = sprintf('shown_demo_%s%s', $page, $specificPage);
|
||||
$key = sprintf('shown_demo_%s%s', $page, $specificPage);
|
||||
// is there an intro for this route?
|
||||
$intro = config(sprintf('intro.%s', $page)) ?? [];
|
||||
$specialIntro = config(sprintf('intro.%s%s', $page, $specificPage)) ?? [];
|
||||
// some routes have a "what" parameter, which indicates a special page:
|
||||
|
||||
$shownDemo = true;
|
||||
$shownDemo = true;
|
||||
// both must be array and either must be > 0
|
||||
if (count($intro) > 0 || count($specialIntro) > 0) {
|
||||
$shownDemo = app('preferences')->get($key, false)->data;
|
||||
@ -123,7 +122,7 @@ trait RequestInformation
|
||||
final protected function notInSessionRange(Carbon $date): bool // Validate a preference
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', today(config('app.timezone'))->startOfMonth());
|
||||
$start = session('start', today(config('app.timezone'))->startOfMonth());
|
||||
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
@ -145,20 +144,20 @@ trait RequestInformation
|
||||
final protected function parseAttributes(array $attributes): array // parse input + return result
|
||||
{
|
||||
$attributes['location'] ??= '';
|
||||
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', []));
|
||||
$date = Carbon::createFromFormat('Ymd', $attributes['startDate']);
|
||||
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', []));
|
||||
$date = Carbon::createFromFormat('Ymd', $attributes['startDate']);
|
||||
if (null === $date) {
|
||||
$date = today(config('app.timezone'));
|
||||
}
|
||||
$date->startOfMonth();
|
||||
$attributes['startDate'] = $date;
|
||||
|
||||
$date2 = Carbon::createFromFormat('Ymd', $attributes['endDate']);
|
||||
$date2 = Carbon::createFromFormat('Ymd', $attributes['endDate']);
|
||||
if (null === $date2) {
|
||||
$date2 = today(config('app.timezone'));
|
||||
}
|
||||
$date2->endOfDay();
|
||||
$attributes['endDate'] = $date2;
|
||||
$attributes['endDate'] = $date2;
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
@ -170,7 +169,7 @@ trait RequestInformation
|
||||
*/
|
||||
final protected function validatePassword(User $user, string $current, string $new): bool // get request info
|
||||
{
|
||||
if (!Hash::check($current, $user->password)) {
|
||||
if (!\Hash::check($current, $user->password)) {
|
||||
throw new ValidationException((string) trans('firefly.invalid_current_password'));
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||
use Illuminate\Http\Request;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Trait RuleManagement
|
||||
@ -55,7 +54,7 @@ trait RuleManagement
|
||||
'count' => $index + 1,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->error(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
|
||||
@ -74,8 +73,8 @@ trait RuleManagement
|
||||
protected function getPreviousTriggers(Request $request): array
|
||||
{
|
||||
// TODO duplicated code.
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
$operators = config('search.operators');
|
||||
$triggers = [];
|
||||
foreach ($operators as $key => $operator) {
|
||||
if ('user_action' !== $key && false === $operator['alias']) {
|
||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||
@ -100,7 +99,7 @@ trait RuleManagement
|
||||
'triggers' => $triggers,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
|
||||
@ -129,7 +128,7 @@ trait RuleManagement
|
||||
}
|
||||
asort($triggers);
|
||||
|
||||
$index = 0;
|
||||
$index = 0;
|
||||
foreach ($submittedOperators as $operator) {
|
||||
$rootOperator = OperatorQuerySearch::getRootOperator($operator['type']);
|
||||
$needsContext = (bool) config(sprintf('search.operators.%s.needs_context', $rootOperator));
|
||||
@ -146,7 +145,7 @@ trait RuleManagement
|
||||
'triggers' => $triggers,
|
||||
]
|
||||
)->render();
|
||||
} catch (Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
app('log')->debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
|
||||
|
@ -39,14 +39,15 @@ trait TransactionCalculation
|
||||
*/
|
||||
protected function getExpensesForOpposing(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$total = $accounts->merge($opposing);
|
||||
$total = $accounts->merge($opposing);
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($total)
|
||||
->setRange($start, $end)
|
||||
->withAccountInformation()
|
||||
->setTypes([TransactionType::WITHDRAWAL]);
|
||||
->setRange($start, $end)
|
||||
->withAccountInformation()
|
||||
->setTypes([TransactionType::WITHDRAWAL])
|
||||
;
|
||||
|
||||
return $collector->getExtractedJournals();
|
||||
}
|
||||
@ -60,7 +61,8 @@ trait TransactionCalculation
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->setTags($tags)->withAccountInformation();
|
||||
->setTags($tags)->withAccountInformation()
|
||||
;
|
||||
|
||||
return $collector->getExtractedJournals();
|
||||
}
|
||||
@ -73,7 +75,8 @@ trait TransactionCalculation
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->setBudgets($budgets)->withAccountInformation();
|
||||
->setBudgets($budgets)->withAccountInformation()
|
||||
;
|
||||
|
||||
return $collector->getExtractedJournals();
|
||||
}
|
||||
@ -90,7 +93,8 @@ trait TransactionCalculation
|
||||
->setRange($start, $end)
|
||||
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->setCategories($categories)
|
||||
->withAccountInformation();
|
||||
->withAccountInformation()
|
||||
;
|
||||
|
||||
return $collector->getExtractedJournals();
|
||||
}
|
||||
@ -103,7 +107,8 @@ trait TransactionCalculation
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||
->setCategories($categories)->withAccountInformation();
|
||||
->setCategories($categories)->withAccountInformation()
|
||||
;
|
||||
|
||||
return $collector->getExtractedJournals();
|
||||
}
|
||||
@ -113,7 +118,7 @@ trait TransactionCalculation
|
||||
*/
|
||||
protected function getIncomeForOpposing(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$total = $accounts->merge($opposing);
|
||||
$total = $accounts->merge($opposing);
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
@ -130,7 +135,8 @@ trait TransactionCalculation
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||
->setTags($tags)->withAccountInformation();
|
||||
->setTags($tags)->withAccountInformation()
|
||||
;
|
||||
|
||||
return $collector->getExtractedJournals();
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ trait UserNavigation
|
||||
final protected function isEditableGroup(TransactionGroup $group): bool
|
||||
{
|
||||
/** @var null|TransactionJournal $journal */
|
||||
$journal = $group->transactionJournals()->first();
|
||||
$journal = $group->transactionJournals()->first();
|
||||
if (null === $journal) {
|
||||
return false;
|
||||
}
|
||||
@ -96,10 +96,10 @@ trait UserNavigation
|
||||
|
||||
return redirect(route('index'));
|
||||
}
|
||||
$journal = $transaction->transactionJournal;
|
||||
$journal = $transaction->transactionJournal;
|
||||
|
||||
/** @var null|Transaction $other */
|
||||
$other = $journal->transactions()->where('id', '!=', $transaction->id)->first();
|
||||
$other = $journal->transactions()->where('id', '!=', $transaction->id)->first();
|
||||
if (null === $other) {
|
||||
app('log')->error(sprintf('Account #%d has no valid journals. Dont know where it belongs.', $account->id));
|
||||
session()->flash('error', trans('firefly.cant_find_redirect_account'));
|
||||
@ -119,7 +119,7 @@ trait UserNavigation
|
||||
final protected function redirectGroupToAccount(TransactionGroup $group)
|
||||
{
|
||||
/** @var null|TransactionJournal $journal */
|
||||
$journal = $group->transactionJournals()->first();
|
||||
$journal = $group->transactionJournals()->first();
|
||||
if (null === $journal) {
|
||||
app('log')->error(sprintf('No journals in group #%d', $group->id));
|
||||
|
||||
|
@ -37,7 +37,7 @@ trait UserGroupDetectable
|
||||
public function detectUserGroup(): ?UserGroup
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$user = auth()->user();
|
||||
app('log')->debug('Now in detectUserGroup()');
|
||||
|
||||
/** @var null|UserGroup $userGroup */
|
||||
@ -49,7 +49,7 @@ trait UserGroupDetectable
|
||||
app('log')->debug(sprintf('Request class has no user_group_id parameter, grab default from user (group #%d).', $user->user_group_id));
|
||||
$userGroupId = (int) $user->user_group_id;
|
||||
}
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
if (null === $userGroup) {
|
||||
app('log')->error(sprintf('Request class has user_group_id (#%d), but group does not exist.', $userGroupId));
|
||||
|
||||
|
@ -25,7 +25,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
@ -37,8 +36,6 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Override;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class AccountEnrichment
|
||||
@ -66,7 +63,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
$this->end = null;
|
||||
}
|
||||
|
||||
#[Override]
|
||||
#[\Override]
|
||||
public function enrichSingle(Model $model): Account
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
@ -76,7 +73,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
return $collection->first();
|
||||
}
|
||||
|
||||
#[Override]
|
||||
#[\Override]
|
||||
/**
|
||||
* Do the actual enrichment.
|
||||
*/
|
||||
@ -147,7 +144,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
$metaFields = $this->repository->getMetaValues($this->collection, ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
|
||||
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
|
||||
|
||||
$currencies = [];
|
||||
$currencies = [];
|
||||
foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) {
|
||||
$id = $currency->id;
|
||||
$currencies[$id] = $currency;
|
||||
@ -177,8 +174,8 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
$default = $this->default;
|
||||
|
||||
// get start and end, so the balance difference can be generated.
|
||||
$start = null;
|
||||
$end = null;
|
||||
$start = null;
|
||||
$end = null;
|
||||
if (null !== $this->start) {
|
||||
$start = Balance::getAccountBalances($this->collection, $this->start);
|
||||
}
|
||||
@ -200,7 +197,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
'balance_difference' => null,
|
||||
];
|
||||
if (array_key_exists($account->id, $balances)) {
|
||||
$set = [];
|
||||
$set = [];
|
||||
foreach ($balances[$account->id] as $currencyId => $entry) {
|
||||
$left = $start[$account->id][$currencyId]['balance'] ?? null;
|
||||
$right = $end[$account->id][$currencyId]['balance'] ?? null;
|
||||
@ -242,11 +239,12 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function getObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->where('object_groupable_type', Account::class)
|
||||
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
|
||||
->distinct()
|
||||
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id']);
|
||||
$set = \DB::table('object_groupables')
|
||||
->where('object_groupable_type', Account::class)
|
||||
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
|
||||
->distinct()
|
||||
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id'])
|
||||
;
|
||||
// get the groups:
|
||||
$groupIds = $set->pluck('object_group_id')->toArray();
|
||||
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
|
||||
@ -256,7 +254,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
$this->objectGroups[$group->id] = $group;
|
||||
}
|
||||
|
||||
/** @var stdClass $entry */
|
||||
/** @var \stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->grouped[(int) $entry->object_groupable_id] = (int) $entry->object_group_id;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ trait ExpandsQuery
|
||||
$config = config('api.valid_api_filters')[$class];
|
||||
$parsed = [];
|
||||
foreach ($filters->all() as $filter) {
|
||||
$key = $filter->key();
|
||||
$key = $filter->key();
|
||||
if (!in_array($key, $config, true)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ trait FiltersPagination
|
||||
$pagination['number'] = min(65536, max($pagination['number'], 1));
|
||||
|
||||
// clean up page size
|
||||
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
|
||||
$pagination['size'] = min(1337, max($pagination['size'], 1));
|
||||
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
|
||||
$pagination['size'] = min(1337, max($pagination['size'], 1));
|
||||
|
||||
return $pagination;
|
||||
}
|
||||
|
@ -71,14 +71,15 @@ class AccountBalanceCalculator
|
||||
$balances = [];
|
||||
$count = 0;
|
||||
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
// this order is the same as GroupCollector, but in the exact reverse.
|
||||
->orderBy('transaction_journals.date', 'asc')
|
||||
->orderBy('transaction_journals.order', 'desc')
|
||||
->orderBy('transaction_journals.id', 'asc')
|
||||
->orderBy('transaction_journals.description', 'asc')
|
||||
->orderBy('transactions.amount', 'asc');
|
||||
->orderBy('transaction_journals.date', 'asc')
|
||||
->orderBy('transaction_journals.order', 'desc')
|
||||
->orderBy('transaction_journals.id', 'asc')
|
||||
->orderBy('transaction_journals.description', 'asc')
|
||||
->orderBy('transactions.amount', 'asc')
|
||||
;
|
||||
if ($accounts->count() > 0) {
|
||||
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
||||
}
|
||||
@ -87,7 +88,7 @@ class AccountBalanceCalculator
|
||||
$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']);
|
||||
$set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']);
|
||||
|
||||
// the balance value is an array.
|
||||
// first entry is the balance, second is the date.
|
||||
@ -99,8 +100,8 @@ class AccountBalanceCalculator
|
||||
$balances[$entry->account_id][$entry->transaction_currency_id] ??= [$this->getLatestBalance($entry->account_id, $entry->transaction_currency_id, $notBefore), null];
|
||||
|
||||
// before and after are easy:
|
||||
$before = $balances[$entry->account_id][$entry->transaction_currency_id][0];
|
||||
$after = bcadd($before, $entry->amount);
|
||||
$before = $balances[$entry->account_id][$entry->transaction_currency_id][0];
|
||||
$after = bcadd($before, $entry->amount);
|
||||
if (true === $entry->balance_dirty || $accounts->count() > 0) {
|
||||
// update the transaction:
|
||||
$entry->balance_before = $before;
|
||||
@ -126,17 +127,18 @@ class AccountBalanceCalculator
|
||||
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')
|
||||
$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);
|
||||
->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);
|
||||
|
||||
@ -168,7 +170,7 @@ class AccountBalanceCalculator
|
||||
*/
|
||||
foreach ($currencies as $currencyId => $balance) {
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = TransactionCurrency::find($currencyId);
|
||||
$currency = TransactionCurrency::find($currencyId);
|
||||
if (null === $currency) {
|
||||
Log::error(sprintf('Could not find currency #%d, will not save account balance.', $currencyId));
|
||||
|
||||
@ -196,7 +198,7 @@ class AccountBalanceCalculator
|
||||
public static function recalculateForJournal(TransactionJournal $transactionJournal): void
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$object = new self();
|
||||
$object = new self();
|
||||
|
||||
// recalculate the involved accounts:
|
||||
$accounts = new Collection();
|
||||
@ -208,9 +210,9 @@ class AccountBalanceCalculator
|
||||
|
||||
private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance
|
||||
{
|
||||
$query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency);
|
||||
$query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency);
|
||||
|
||||
$entry = $query->first();
|
||||
$entry = $query->first();
|
||||
if (null !== $entry) {
|
||||
// Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
|
||||
|
||||
@ -229,9 +231,9 @@ class AccountBalanceCalculator
|
||||
|
||||
private function getAccountBalanceByJournal(string $title, int $account, int $journal, int $currency): AccountBalance
|
||||
{
|
||||
$query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency);
|
||||
$query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency);
|
||||
|
||||
$entry = $query->first();
|
||||
$entry = $query->first();
|
||||
if (null !== $entry) {
|
||||
return $entry;
|
||||
}
|
||||
|
@ -49,15 +49,15 @@ class BillDateCalculator
|
||||
Log::debug(sprintf('Dates must be between %s and %s.', $earliest->format('Y-m-d'), $latest->format('Y-m-d')));
|
||||
Log::debug(sprintf('Bill started on %s, period is "%s", skip is %d, last paid = "%s".', $billStart->format('Y-m-d'), $period, $skip, $lastPaid?->format('Y-m-d')));
|
||||
|
||||
$daysUntilEOM = app('navigation')->daysUntilEndOfMonth($billStart);
|
||||
$daysUntilEOM = app('navigation')->daysUntilEndOfMonth($billStart);
|
||||
Log::debug(sprintf('For bill start, days until end of month is %d', $daysUntilEOM));
|
||||
|
||||
$set = new Collection();
|
||||
$currentStart = clone $earliest;
|
||||
$set = new Collection();
|
||||
$currentStart = clone $earliest;
|
||||
|
||||
// 2023-06-23 subDay to fix 7655
|
||||
$currentStart->subDay();
|
||||
$loop = 0;
|
||||
$loop = 0;
|
||||
|
||||
Log::debug('Start of loop');
|
||||
while ($currentStart <= $latest) {
|
||||
@ -107,7 +107,7 @@ class BillDateCalculator
|
||||
// for the next loop, go to end of period, THEN add day.
|
||||
Log::debug('Add one day to nextExpectedMatch/currentStart.');
|
||||
$nextExpectedMatch->addDay();
|
||||
$currentStart = clone $nextExpectedMatch;
|
||||
$currentStart = clone $nextExpectedMatch;
|
||||
|
||||
++$loop;
|
||||
if ($loop > 12) {
|
||||
@ -117,7 +117,7 @@ class BillDateCalculator
|
||||
}
|
||||
}
|
||||
Log::debug('end of loop');
|
||||
$simple = $set->map(
|
||||
$simple = $set->map(
|
||||
static function (Carbon $date) {
|
||||
return $date->format('Y-m-d');
|
||||
}
|
||||
@ -142,7 +142,7 @@ class BillDateCalculator
|
||||
return $billStartDate;
|
||||
}
|
||||
|
||||
$steps = app('navigation')->diffInPeriods($period, $skip, $earliest, $billStartDate);
|
||||
$steps = app('navigation')->diffInPeriods($period, $skip, $earliest, $billStartDate);
|
||||
if ($steps === $this->diffInMonths) {
|
||||
Log::debug(sprintf('Steps is %d, which is the same as diffInMonths (%d), so we add another 1.', $steps, $this->diffInMonths));
|
||||
++$steps;
|
||||
|
@ -39,7 +39,7 @@ trait ReturnsIntegerIdTrait
|
||||
protected function id(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn($value) => (int) $value,
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -37,14 +37,14 @@ trait ReturnsIntegerUserIdTrait
|
||||
protected function userGroupId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn($value) => (int) $value,
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
|
||||
protected function userId(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: static fn($value) => (int) $value,
|
||||
get: static fn ($value) => (int) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ use FireflyIII\Helpers\Fiscal\FiscalHelperInterface;
|
||||
use FireflyIII\Support\Calendar\Calculator;
|
||||
use FireflyIII\Support\Calendar\Periodicity;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class Navigation.
|
||||
@ -77,10 +76,10 @@ class Navigation
|
||||
|
||||
if (!array_key_exists($repeatFreq, $functionMap)) {
|
||||
Log::error(sprintf(
|
||||
'The periodicity %s is unknown. Choose one of available periodicity: %s',
|
||||
$repeatFreq,
|
||||
implode(', ', array_keys($functionMap))
|
||||
));
|
||||
'The periodicity %s is unknown. Choose one of available periodicity: %s',
|
||||
$repeatFreq,
|
||||
implode(', ', array_keys($functionMap))
|
||||
));
|
||||
|
||||
return $theDate;
|
||||
}
|
||||
@ -94,7 +93,7 @@ class Navigation
|
||||
return $this->calculator->nextDateByInterval($epoch, $periodicity, $skipInterval);
|
||||
} catch (IntervalException $exception) {
|
||||
Log::warning($exception->getMessage(), ['exception' => $exception]);
|
||||
} catch (Throwable $exception) { // @phpstan-ignore-line
|
||||
} catch (\Throwable $exception) { // @phpstan-ignore-line
|
||||
Log::error($exception->getMessage(), ['exception' => $exception]);
|
||||
}
|
||||
|
||||
@ -111,7 +110,7 @@ class Navigation
|
||||
if ($end < $start) {
|
||||
[$start, $end] = [$end, $start];
|
||||
}
|
||||
$periods = [];
|
||||
$periods = [];
|
||||
// first, 13 periods of [range]
|
||||
$loopCount = 0;
|
||||
$loopDate = clone $end;
|
||||
@ -161,9 +160,9 @@ class Navigation
|
||||
|
||||
public function startOfPeriod(Carbon $theDate, string $repeatFreq): Carbon
|
||||
{
|
||||
$date = clone $theDate;
|
||||
$date = clone $theDate;
|
||||
// Log::debug(sprintf('Now in startOfPeriod("%s", "%s")', $date->toIso8601String(), $repeatFreq));
|
||||
$functionMap = [
|
||||
$functionMap = [
|
||||
'1D' => 'startOfDay',
|
||||
'daily' => 'startOfDay',
|
||||
'1W' => 'startOfWeek',
|
||||
@ -210,7 +209,7 @@ class Navigation
|
||||
return $date;
|
||||
}
|
||||
|
||||
$result = match ($repeatFreq) {
|
||||
$result = match ($repeatFreq) {
|
||||
'last7' => $date->subDays(7)->startOfDay(),
|
||||
'last30' => $date->subDays(30)->startOfDay(),
|
||||
'last90' => $date->subDays(90)->startOfDay(),
|
||||
@ -238,7 +237,7 @@ class Navigation
|
||||
|
||||
public function endOfPeriod(Carbon $end, string $repeatFreq): Carbon
|
||||
{
|
||||
$currentEnd = clone $end;
|
||||
$currentEnd = clone $end;
|
||||
// Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq));
|
||||
|
||||
$functionMap = [
|
||||
@ -272,7 +271,7 @@ class Navigation
|
||||
Log::debug('Session data available.');
|
||||
|
||||
/** @var Carbon $tStart */
|
||||
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
||||
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
||||
|
||||
/** @var Carbon $tEnd */
|
||||
$tEnd = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
@ -292,7 +291,7 @@ class Navigation
|
||||
return $end->endOfMonth();
|
||||
}
|
||||
|
||||
$result = match ($repeatFreq) {
|
||||
$result = match ($repeatFreq) {
|
||||
'last7' => $currentEnd->addDays(7)->startOfDay(),
|
||||
'last30' => $currentEnd->addDays(30)->startOfDay(),
|
||||
'last90' => $currentEnd->addDays(90)->startOfDay(),
|
||||
@ -312,7 +311,7 @@ class Navigation
|
||||
|
||||
return $end;
|
||||
}
|
||||
$function = $functionMap[$repeatFreq];
|
||||
$function = $functionMap[$repeatFreq];
|
||||
|
||||
if (array_key_exists($repeatFreq, $modifierMap)) {
|
||||
$currentEnd->{$function}($modifierMap[$repeatFreq]); // @phpstan-ignore-line
|
||||
@ -343,13 +342,13 @@ class Navigation
|
||||
public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int
|
||||
{
|
||||
Log::debug(sprintf(
|
||||
'diffInPeriods: %s (skip: %d), between %s and %s.',
|
||||
$period,
|
||||
$skip,
|
||||
$beginning->format('Y-m-d'),
|
||||
$end->format('Y-m-d')
|
||||
));
|
||||
$map = [
|
||||
'diffInPeriods: %s (skip: %d), between %s and %s.',
|
||||
$period,
|
||||
$skip,
|
||||
$beginning->format('Y-m-d'),
|
||||
$end->format('Y-m-d')
|
||||
));
|
||||
$map = [
|
||||
'daily' => 'diffInDays',
|
||||
'weekly' => 'diffInWeeks',
|
||||
'monthly' => 'diffInMonths',
|
||||
@ -362,7 +361,7 @@ class Navigation
|
||||
|
||||
return 1;
|
||||
}
|
||||
$func = $map[$period];
|
||||
$func = $map[$period];
|
||||
// first do the diff
|
||||
$floatDiff = $beginning->{$func}($end, true); // @phpstan-ignore-line
|
||||
|
||||
@ -377,7 +376,7 @@ class Navigation
|
||||
}
|
||||
|
||||
// then do ceil()
|
||||
$diff = ceil($floatDiff);
|
||||
$diff = ceil($floatDiff);
|
||||
|
||||
Log::debug(sprintf('Diff is %f periods (%d rounded up)', $floatDiff, $diff));
|
||||
|
||||
@ -385,11 +384,11 @@ class Navigation
|
||||
$parameter = $skip + 1;
|
||||
$diff = ceil($diff / $parameter) * $parameter;
|
||||
Log::debug(sprintf(
|
||||
'diffInPeriods: skip is %d, so param is %d, and diff becomes %d',
|
||||
$skip,
|
||||
$parameter,
|
||||
$diff
|
||||
));
|
||||
'diffInPeriods: skip is %d, so param is %d, and diff becomes %d',
|
||||
$skip,
|
||||
$parameter,
|
||||
$diff
|
||||
));
|
||||
}
|
||||
|
||||
return (int) $diff;
|
||||
@ -414,7 +413,7 @@ class Navigation
|
||||
'yearly' => 'endOfYear',
|
||||
];
|
||||
|
||||
$currentEnd = clone $theCurrentEnd;
|
||||
$currentEnd = clone $theCurrentEnd;
|
||||
|
||||
if (array_key_exists($repeatFreq, $functionMap)) {
|
||||
$function = $functionMap[$repeatFreq];
|
||||
@ -469,7 +468,7 @@ class Navigation
|
||||
*/
|
||||
public function listOfPeriods(Carbon $start, Carbon $end): array
|
||||
{
|
||||
$locale = app('steam')->getLocale();
|
||||
$locale = app('steam')->getLocale();
|
||||
// define period to increment
|
||||
$increment = 'addDay';
|
||||
$format = $this->preferredCarbonFormat($start, $end);
|
||||
@ -486,8 +485,8 @@ class Navigation
|
||||
$increment = 'addYear';
|
||||
$displayFormat = (string) trans('config.year_js');
|
||||
}
|
||||
$begin = clone $start;
|
||||
$entries = [];
|
||||
$begin = clone $start;
|
||||
$entries = [];
|
||||
while ($begin < $end) {
|
||||
$formatted = $begin->format($format);
|
||||
$displayed = $begin->isoFormat($displayFormat);
|
||||
@ -649,7 +648,7 @@ class Navigation
|
||||
public function subtractPeriod(Carbon $theDate, string $repeatFreq, ?int $subtract = null): Carbon
|
||||
{
|
||||
$subtract ??= 1;
|
||||
$date = clone $theDate;
|
||||
$date = clone $theDate;
|
||||
// 1D 1W 1M 3M 6M 1Y
|
||||
$functionMap = [
|
||||
'1D' => 'subDays',
|
||||
@ -688,7 +687,7 @@ class Navigation
|
||||
// this is then subtracted from $theDate (* $subtract).
|
||||
if ('custom' === $repeatFreq) {
|
||||
/** @var Carbon $tStart */
|
||||
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
||||
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
||||
|
||||
/** @var Carbon $tEnd */
|
||||
$tEnd = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
@ -782,7 +781,7 @@ class Navigation
|
||||
|
||||
return $fiscalHelper->endOfFiscalYear($end);
|
||||
}
|
||||
$list = [
|
||||
$list = [
|
||||
'last7',
|
||||
'last30',
|
||||
'last90',
|
||||
|
@ -24,12 +24,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* Class NullArrayObject
|
||||
*/
|
||||
class NullArrayObject extends ArrayObject
|
||||
class NullArrayObject extends \ArrayObject
|
||||
{
|
||||
/** @var null|mixed */
|
||||
public $default;
|
||||
|
@ -77,15 +77,15 @@ class ParseDateString
|
||||
public function parseDate(string $date): Carbon
|
||||
{
|
||||
app('log')->debug(sprintf('parseDate("%s")', $date));
|
||||
$date = strtolower($date);
|
||||
$date = strtolower($date);
|
||||
// parse keywords:
|
||||
if (in_array($date, $this->keywords, true)) {
|
||||
return $this->parseKeyword($date);
|
||||
}
|
||||
|
||||
// if regex for YYYY-MM-DD:
|
||||
$pattern = '/^(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])$/';
|
||||
$result = preg_match($pattern, $date);
|
||||
$pattern = '/^(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])$/';
|
||||
$result = preg_match($pattern, $date);
|
||||
if (false !== $result && 0 !== $result) {
|
||||
return $this->parseDefaultDate($date);
|
||||
}
|
||||
@ -178,11 +178,11 @@ class ParseDateString
|
||||
|
||||
foreach ($parts as $part) {
|
||||
app('log')->debug(sprintf('Now parsing part "%s"', $part));
|
||||
$part = trim($part);
|
||||
$part = trim($part);
|
||||
|
||||
// verify if correct
|
||||
$pattern = '/[+-]\d+[wqmdy]/';
|
||||
$result = preg_match($pattern, $part);
|
||||
$pattern = '/[+-]\d+[wqmdy]/';
|
||||
$result = preg_match($pattern, $part);
|
||||
if (0 === $result || false === $result) {
|
||||
app('log')->error(sprintf('Part "%s" does not match regular expression. Will be skipped.', $part));
|
||||
|
||||
@ -196,7 +196,7 @@ class ParseDateString
|
||||
|
||||
continue;
|
||||
}
|
||||
$func = $functions[$direction][$period];
|
||||
$func = $functions[$direction][$period];
|
||||
app('log')->debug(sprintf('Will now do %s(%d) on %s', $func, $number, $today->format('Y-m-d')));
|
||||
$today->{$func}($number); // @phpstan-ignore-line
|
||||
app('log')->debug(sprintf('Resulting date is %s', $today->format('Y-m-d')));
|
||||
|
@ -47,15 +47,16 @@ class Preferences
|
||||
}
|
||||
|
||||
return Preference::where('user_id', $user->id)
|
||||
->where('name', '!=', 'currencyPreference')
|
||||
->where(function (Builder $q) use ($user): void {
|
||||
$q->whereNull('user_group_id');
|
||||
$q->orWhere('user_group_id', $user->user_group_id);
|
||||
})
|
||||
->get();
|
||||
->where('name', '!=', 'currencyPreference')
|
||||
->where(function (Builder $q) use ($user): void {
|
||||
$q->whereNull('user_group_id');
|
||||
$q->orWhere('user_group_id', $user->user_group_id);
|
||||
})
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
public function get(string $name, null | array | bool | int | string $default = null): ?Preference
|
||||
public function get(string $name, null|array|bool|int|string $default = null): ?Preference
|
||||
{
|
||||
/** @var null|User $user */
|
||||
$user = auth()->user();
|
||||
@ -69,7 +70,7 @@ class Preferences
|
||||
return $this->getForUser($user, $name, $default);
|
||||
}
|
||||
|
||||
public function getForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference
|
||||
public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference
|
||||
{
|
||||
// don't care about user group ID, except for some specific preferences.
|
||||
$userGroupId = $this->getUserGroupId($user, $name);
|
||||
@ -121,16 +122,16 @@ class Preferences
|
||||
Cache::put($key, '', 5);
|
||||
}
|
||||
|
||||
public function setForUser(User $user, string $name, null | array | bool | int | string $value): Preference
|
||||
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);
|
||||
$groupId = $this->getUserGroupId($user, $name);
|
||||
$groupId = 0 === (int) $groupId ? null : (int) $groupId;
|
||||
|
||||
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']);
|
||||
$pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']);
|
||||
|
||||
if (null !== $pref && null === $value) {
|
||||
$pref->delete();
|
||||
@ -173,12 +174,13 @@ class Preferences
|
||||
{
|
||||
$result = [];
|
||||
$preferences = Preference::where('user_id', $user->id)
|
||||
->where(function (Builder $q) use ($user): void {
|
||||
$q->whereNull('user_group_id');
|
||||
$q->orWhere('user_group_id', $user->user_group_id);
|
||||
})
|
||||
->whereIn('name', $list)
|
||||
->get(['id', 'name', 'data']);
|
||||
->where(function (Builder $q) use ($user): void {
|
||||
$q->whereNull('user_group_id');
|
||||
$q->orWhere('user_group_id', $user->user_group_id);
|
||||
})
|
||||
->whereIn('name', $list)
|
||||
->get(['id', 'name', 'data'])
|
||||
;
|
||||
|
||||
/** @var Preference $preference */
|
||||
foreach ($preferences as $preference) {
|
||||
@ -216,7 +218,7 @@ class Preferences
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getEncryptedForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference
|
||||
public function getEncryptedForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference
|
||||
{
|
||||
$result = $this->getForUser($user, $name, $default);
|
||||
if ('' === $result->data) {
|
||||
@ -237,7 +239,7 @@ class Preferences
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getFresh(string $name, null | array | bool | int | string $default = null): ?Preference
|
||||
public function getFresh(string $name, null|array|bool|int|string $default = null): ?Preference
|
||||
{
|
||||
/** @var null|User $user */
|
||||
$user = auth()->user();
|
||||
@ -275,7 +277,7 @@ class Preferences
|
||||
Session::forget('first');
|
||||
}
|
||||
|
||||
public function set(string $name, null | array | bool | int | string $value): Preference
|
||||
public function set(string $name, null|array|bool|int|string $value): Preference
|
||||
{
|
||||
/** @var null|User $user */
|
||||
$user = auth()->user();
|
||||
|
@ -76,7 +76,7 @@ class BudgetReportGenerator
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($this->accounts as $account) {
|
||||
$accountId = $account->id;
|
||||
$accountId = $account->id;
|
||||
$this->report[$accountId] ??= [
|
||||
'name' => $account->name,
|
||||
'id' => $account->id,
|
||||
@ -113,18 +113,18 @@ class BudgetReportGenerator
|
||||
|
||||
$this->report[$sourceAccountId]['currencies'][$currencyId]
|
||||
??= [
|
||||
'currency_id' => $expenses['currency_id'],
|
||||
'currency_symbol' => $expenses['currency_symbol'],
|
||||
'currency_name' => $expenses['currency_name'],
|
||||
'currency_decimal_places' => $expenses['currency_decimal_places'],
|
||||
'budgets' => [],
|
||||
];
|
||||
'currency_id' => $expenses['currency_id'],
|
||||
'currency_symbol' => $expenses['currency_symbol'],
|
||||
'currency_name' => $expenses['currency_name'],
|
||||
'currency_decimal_places' => $expenses['currency_decimal_places'],
|
||||
'budgets' => [],
|
||||
];
|
||||
|
||||
$this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId]
|
||||
??= '0';
|
||||
|
||||
$this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId]
|
||||
= bcadd($this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId], $journal['amount']);
|
||||
= bcadd($this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId], $journal['amount']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ class BudgetReportGenerator
|
||||
*/
|
||||
private function processBudget(Budget $budget): void
|
||||
{
|
||||
$budgetId = $budget->id;
|
||||
$budgetId = $budget->id;
|
||||
$this->report['budgets'][$budgetId] ??= [
|
||||
'budget_id' => $budgetId,
|
||||
'budget_name' => $budget->name,
|
||||
@ -171,7 +171,7 @@ class BudgetReportGenerator
|
||||
];
|
||||
|
||||
// get all budget limits for budget in period:
|
||||
$limits = $this->blRepository->getBudgetLimits($budget, $this->start, $this->end);
|
||||
$limits = $this->blRepository->getBudgetLimits($budget, $this->start, $this->end);
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
@ -184,14 +184,14 @@ class BudgetReportGenerator
|
||||
*/
|
||||
private function processLimit(Budget $budget, BudgetLimit $limit): void
|
||||
{
|
||||
$budgetId = $budget->id;
|
||||
$limitId = $limit->id;
|
||||
$limitCurrency = $limit->transactionCurrency ?? $this->currency;
|
||||
$currencyId = $limitCurrency->id;
|
||||
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget]));
|
||||
$spent = $expenses[$currencyId]['sum'] ?? '0';
|
||||
$left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent);
|
||||
$overspent = 1 === bccomp(bcmul($spent, '-1'), $limit->amount) ? bcadd($spent, $limit->amount) : '0';
|
||||
$budgetId = $budget->id;
|
||||
$limitId = $limit->id;
|
||||
$limitCurrency = $limit->transactionCurrency ?? $this->currency;
|
||||
$currencyId = $limitCurrency->id;
|
||||
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget]));
|
||||
$spent = $expenses[$currencyId]['sum'] ?? '0';
|
||||
$left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent);
|
||||
$overspent = 1 === bccomp(bcmul($spent, '-1'), $limit->amount) ? bcadd($spent, $limit->amount) : '0';
|
||||
|
||||
$this->report['budgets'][$budgetId]['budget_limits'][$limitId] ??= [
|
||||
'budget_limit_id' => $limitId,
|
||||
@ -212,17 +212,17 @@ class BudgetReportGenerator
|
||||
|
||||
// make sum information:
|
||||
$this->report['sums'][$currencyId]
|
||||
??= [
|
||||
'budgeted' => '0',
|
||||
'spent' => '0',
|
||||
'left' => '0',
|
||||
'overspent' => '0',
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $limitCurrency->code,
|
||||
'currency_name' => $limitCurrency->name,
|
||||
'currency_symbol' => $limitCurrency->symbol,
|
||||
'currency_decimal_places' => $limitCurrency->decimal_places,
|
||||
];
|
||||
??= [
|
||||
'budgeted' => '0',
|
||||
'spent' => '0',
|
||||
'left' => '0',
|
||||
'overspent' => '0',
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $limitCurrency->code,
|
||||
'currency_name' => $limitCurrency->name,
|
||||
'currency_symbol' => $limitCurrency->symbol,
|
||||
'currency_decimal_places' => $limitCurrency->decimal_places,
|
||||
];
|
||||
$this->report['sums'][$currencyId]['budgeted'] = bcadd($this->report['sums'][$currencyId]['budgeted'], $limit->amount);
|
||||
$this->report['sums'][$currencyId]['spent'] = bcadd($this->report['sums'][$currencyId]['spent'], $spent);
|
||||
$this->report['sums'][$currencyId]['left'] = bcadd($this->report['sums'][$currencyId]['left'], bcadd($limit->amount, $spent));
|
||||
@ -242,16 +242,16 @@ class BudgetReportGenerator
|
||||
'budget_limits' => [],
|
||||
];
|
||||
|
||||
$noBudget = $this->nbRepository->sumExpenses($this->start, $this->end, $this->accounts);
|
||||
$noBudget = $this->nbRepository->sumExpenses($this->start, $this->end, $this->accounts);
|
||||
foreach ($noBudget as $noBudgetEntry) {
|
||||
// currency information:
|
||||
$nbCurrencyId = (int) ($noBudgetEntry['currency_id'] ?? $this->currency->id);
|
||||
$nbCurrencyCode = $noBudgetEntry['currency_code'] ?? $this->currency->code;
|
||||
$nbCurrencyName = $noBudgetEntry['currency_name'] ?? $this->currency->name;
|
||||
$nbCurrencySymbol = $noBudgetEntry['currency_symbol'] ?? $this->currency->symbol;
|
||||
$nbCurrencyDp = $noBudgetEntry['currency_decimal_places'] ?? $this->currency->decimal_places;
|
||||
$nbCurrencyId = (int) ($noBudgetEntry['currency_id'] ?? $this->currency->id);
|
||||
$nbCurrencyCode = $noBudgetEntry['currency_code'] ?? $this->currency->code;
|
||||
$nbCurrencyName = $noBudgetEntry['currency_name'] ?? $this->currency->name;
|
||||
$nbCurrencySymbol = $noBudgetEntry['currency_symbol'] ?? $this->currency->symbol;
|
||||
$nbCurrencyDp = $noBudgetEntry['currency_decimal_places'] ?? $this->currency->decimal_places;
|
||||
|
||||
$this->report['budgets'][0]['budget_limits'][] = [
|
||||
$this->report['budgets'][0]['budget_limits'][] = [
|
||||
'budget_limit_id' => null,
|
||||
'start_date' => $this->start,
|
||||
'end_date' => $this->end,
|
||||
@ -267,7 +267,7 @@ class BudgetReportGenerator
|
||||
'currency_symbol' => $nbCurrencySymbol,
|
||||
'currency_decimal_places' => $nbCurrencyDp,
|
||||
];
|
||||
$this->report['sums'][$nbCurrencyId]['spent'] = bcadd($this->report['sums'][$nbCurrencyId]['spent'] ?? '0', $noBudgetEntry['sum']);
|
||||
$this->report['sums'][$nbCurrencyId]['spent'] = bcadd($this->report['sums'][$nbCurrencyId]['spent'] ?? '0', $noBudgetEntry['sum']);
|
||||
// append currency info because it may be missing:
|
||||
$this->report['sums'][$nbCurrencyId]['currency_id'] = $nbCurrencyId;
|
||||
$this->report['sums'][$nbCurrencyId]['currency_code'] = $nbCurrencyCode;
|
||||
@ -290,15 +290,15 @@ class BudgetReportGenerator
|
||||
// make percentages based on total amount.
|
||||
foreach ($this->report['budgets'] as $budgetId => $data) {
|
||||
foreach ($data['budget_limits'] as $limitId => $entry) {
|
||||
$budgetId = (int) $budgetId;
|
||||
$limitId = (int) $limitId;
|
||||
$currencyId = (int) $entry['currency_id'];
|
||||
$spent = $entry['spent'];
|
||||
$totalSpent = $this->report['sums'][$currencyId]['spent'] ?? '0';
|
||||
$spentPct = '0';
|
||||
$budgeted = $entry['budgeted'];
|
||||
$totalBudgeted = $this->report['sums'][$currencyId]['budgeted'] ?? '0';
|
||||
$budgetedPct = '0';
|
||||
$budgetId = (int) $budgetId;
|
||||
$limitId = (int) $limitId;
|
||||
$currencyId = (int) $entry['currency_id'];
|
||||
$spent = $entry['spent'];
|
||||
$totalSpent = $this->report['sums'][$currencyId]['spent'] ?? '0';
|
||||
$spentPct = '0';
|
||||
$budgeted = $entry['budgeted'];
|
||||
$totalBudgeted = $this->report['sums'][$currencyId]['budgeted'] ?? '0';
|
||||
$budgetedPct = '0';
|
||||
|
||||
if (0 !== bccomp($spent, '0') && 0 !== bccomp($totalSpent, '0')) {
|
||||
$spentPct = round((float) bcmul(bcdiv($spent, $totalSpent), '100'));
|
||||
@ -306,7 +306,7 @@ class BudgetReportGenerator
|
||||
if (0 !== bccomp($budgeted, '0') && 0 !== bccomp($totalBudgeted, '0')) {
|
||||
$budgetedPct = round((float) bcmul(bcdiv($budgeted, $totalBudgeted), '100'));
|
||||
}
|
||||
$this->report['sums'][$currencyId]['budgeted'] ??= '0';
|
||||
$this->report['sums'][$currencyId]['budgeted'] ??= '0';
|
||||
$this->report['budgets'][$budgetId]['budget_limits'][$limitId]['spent_pct'] = $spentPct;
|
||||
$this->report['budgets'][$budgetId]['budget_limits'][$limitId]['budgeted_pct'] = $budgetedPct;
|
||||
}
|
||||
|
@ -62,17 +62,17 @@ class CategoryReportGenerator
|
||||
*/
|
||||
public function operations(): void
|
||||
{
|
||||
$earnedWith = $this->opsRepository->listIncome($this->start, $this->end, $this->accounts);
|
||||
$spentWith = $this->opsRepository->listExpenses($this->start, $this->end, $this->accounts);
|
||||
$earnedWith = $this->opsRepository->listIncome($this->start, $this->end, $this->accounts);
|
||||
$spentWith = $this->opsRepository->listExpenses($this->start, $this->end, $this->accounts);
|
||||
|
||||
// also transferred out and transferred into these accounts in this category:
|
||||
$transferredIn = $this->opsRepository->listTransferredIn($this->start, $this->end, $this->accounts);
|
||||
$transferredOut = $this->opsRepository->listTransferredOut($this->start, $this->end, $this->accounts);
|
||||
|
||||
$earnedWithout = $this->noCatRepository->listIncome($this->start, $this->end, $this->accounts);
|
||||
$spentWithout = $this->noCatRepository->listExpenses($this->start, $this->end, $this->accounts);
|
||||
$earnedWithout = $this->noCatRepository->listIncome($this->start, $this->end, $this->accounts);
|
||||
$spentWithout = $this->noCatRepository->listExpenses($this->start, $this->end, $this->accounts);
|
||||
|
||||
$this->report = [
|
||||
$this->report = [
|
||||
'categories' => [],
|
||||
'sums' => [],
|
||||
];
|
||||
@ -121,7 +121,7 @@ class CategoryReportGenerator
|
||||
|
||||
private function processCategoryRow(int $currencyId, array $currencyRow, int $categoryId, array $categoryRow): void
|
||||
{
|
||||
$key = sprintf('%s-%s', $currencyId, $categoryId);
|
||||
$key = sprintf('%s-%s', $currencyId, $categoryId);
|
||||
$this->report['categories'][$key] ??= [
|
||||
'id' => $categoryId,
|
||||
'title' => $categoryRow['name'],
|
||||
@ -137,9 +137,9 @@ class CategoryReportGenerator
|
||||
// loop journals:
|
||||
foreach ($categoryRow['transaction_journals'] as $journal) {
|
||||
// sum of sums
|
||||
$this->report['sums'][$currencyId]['sum'] = bcadd($this->report['sums'][$currencyId]['sum'], $journal['amount']);
|
||||
$this->report['sums'][$currencyId]['sum'] = bcadd($this->report['sums'][$currencyId]['sum'], $journal['amount']);
|
||||
// sum of spent:
|
||||
$this->report['sums'][$currencyId]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd(
|
||||
$this->report['sums'][$currencyId]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd(
|
||||
$this->report['sums'][$currencyId]['spent'],
|
||||
$journal['amount']
|
||||
) : $this->report['sums'][$currencyId]['spent'];
|
||||
@ -150,14 +150,14 @@ class CategoryReportGenerator
|
||||
) : $this->report['sums'][$currencyId]['earned'];
|
||||
|
||||
// sum of category
|
||||
$this->report['categories'][$key]['sum'] = bcadd($this->report['categories'][$key]['sum'], $journal['amount']);
|
||||
$this->report['categories'][$key]['sum'] = bcadd($this->report['categories'][$key]['sum'], $journal['amount']);
|
||||
// total spent in category
|
||||
$this->report['categories'][$key]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd(
|
||||
$this->report['categories'][$key]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd(
|
||||
$this->report['categories'][$key]['spent'],
|
||||
$journal['amount']
|
||||
) : $this->report['categories'][$key]['spent'];
|
||||
// total earned in category
|
||||
$this->report['categories'][$key]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd(
|
||||
$this->report['categories'][$key]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd(
|
||||
$this->report['categories'][$key]['earned'],
|
||||
$journal['amount']
|
||||
) : $this->report['categories'][$key]['earned'];
|
||||
|
@ -82,8 +82,8 @@ trait CalculateRangeOccurrences
|
||||
*/
|
||||
protected function getNdomInRange(Carbon $start, Carbon $end, int $skipMod, string $moment): array
|
||||
{
|
||||
$return = [];
|
||||
$attempts = 0;
|
||||
$return = [];
|
||||
$attempts = 0;
|
||||
$start->startOfMonth();
|
||||
// this feels a bit like a cop out but why reinvent the wheel?
|
||||
$counters = [1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth'];
|
||||
@ -108,12 +108,12 @@ trait CalculateRangeOccurrences
|
||||
*/
|
||||
protected function getWeeklyInRange(Carbon $start, Carbon $end, int $skipMod, string $moment): array
|
||||
{
|
||||
$return = [];
|
||||
$attempts = 0;
|
||||
$return = [];
|
||||
$attempts = 0;
|
||||
app('log')->debug('Rep is weekly.');
|
||||
// monday = 1
|
||||
// sunday = 7
|
||||
$dayOfWeek = (int) $moment;
|
||||
$dayOfWeek = (int) $moment;
|
||||
app('log')->debug(sprintf('DoW in repetition is %d, in mutator is %d', $dayOfWeek, $start->dayOfWeekIso));
|
||||
if ($start->dayOfWeekIso > $dayOfWeek) {
|
||||
// day has already passed this week, add one week:
|
||||
@ -154,8 +154,8 @@ trait CalculateRangeOccurrences
|
||||
}
|
||||
|
||||
// is $date between $start and $end?
|
||||
$obj = clone $date;
|
||||
$count = 0;
|
||||
$obj = clone $date;
|
||||
$count = 0;
|
||||
while ($obj <= $end && $obj >= $start && $count < 10) {
|
||||
if (0 === $attempts % $skipMod) {
|
||||
$return[] = clone $obj;
|
||||
|
@ -89,10 +89,10 @@ trait CalculateXOccurrences
|
||||
*/
|
||||
protected function getXNDomOccurrences(Carbon $date, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
$mutator->addDay(); // always assume today has passed.
|
||||
$mutator->startOfMonth();
|
||||
// this feels a bit like a cop out but why reinvent the wheel?
|
||||
@ -120,14 +120,14 @@ trait CalculateXOccurrences
|
||||
*/
|
||||
protected function getXWeeklyOccurrences(Carbon $date, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
// monday = 1
|
||||
// sunday = 7
|
||||
$mutator->addDay(); // always assume today has passed.
|
||||
$dayOfWeek = (int) $moment;
|
||||
$dayOfWeek = (int) $moment;
|
||||
if ($mutator->dayOfWeekIso > $dayOfWeek) {
|
||||
// day has already passed this week, add one week:
|
||||
$mutator->addWeek();
|
||||
@ -164,7 +164,7 @@ trait CalculateXOccurrences
|
||||
if ($mutator > $date) {
|
||||
$date->addYear();
|
||||
}
|
||||
$obj = clone $date;
|
||||
$obj = clone $date;
|
||||
while ($total < $count) {
|
||||
if (0 === $attempts % $skipMod) {
|
||||
$return[] = clone $obj;
|
||||
|
@ -86,7 +86,7 @@ trait CalculateXOccurrencesSince
|
||||
++$total;
|
||||
}
|
||||
++$attempts;
|
||||
$mutator = $mutator->endOfMonth()->addDay();
|
||||
$mutator = $mutator->endOfMonth()->addDay();
|
||||
}
|
||||
|
||||
return $return;
|
||||
@ -101,10 +101,10 @@ trait CalculateXOccurrencesSince
|
||||
protected function getXNDomOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
$mutator->addDay(); // always assume today has passed.
|
||||
$mutator->startOfMonth();
|
||||
// this feels a bit like a cop out but why reinvent the wheel?
|
||||
@ -135,15 +135,15 @@ trait CalculateXOccurrencesSince
|
||||
protected function getXWeeklyOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
$mutator = clone $date;
|
||||
// monday = 1
|
||||
// sunday = 7
|
||||
// Removed assumption today has passed, see issue https://github.com/firefly-iii/firefly-iii/issues/4798
|
||||
// $mutator->addDay(); // always assume today has passed.
|
||||
$dayOfWeek = (int) $moment;
|
||||
$dayOfWeek = (int) $moment;
|
||||
if ($mutator->dayOfWeekIso > $dayOfWeek) {
|
||||
// day has already passed this week, add one week:
|
||||
$mutator->addWeek();
|
||||
@ -187,7 +187,7 @@ trait CalculateXOccurrencesSince
|
||||
$date->addYear();
|
||||
app('log')->debug(sprintf('Date is now %s', $date->format('Y-m-d')));
|
||||
}
|
||||
$obj = clone $date;
|
||||
$obj = clone $date;
|
||||
while ($total < $count) {
|
||||
app('log')->debug(sprintf('total (%d) < count (%d) so go.', $total, $count));
|
||||
app('log')->debug(sprintf('attempts (%d) %% skipmod (%d) === %d', $attempts, $skipMod, $attempts % $skipMod));
|
||||
|
@ -44,7 +44,7 @@ trait FiltersWeekends
|
||||
|
||||
return $dates;
|
||||
}
|
||||
$return = [];
|
||||
$return = [];
|
||||
|
||||
/** @var Carbon $date */
|
||||
foreach ($dates as $date) {
|
||||
@ -58,7 +58,7 @@ trait FiltersWeekends
|
||||
|
||||
// is weekend and must set back to Friday?
|
||||
if (RecurrenceRepetition::WEEKEND_TO_FRIDAY === $repetition->weekend) {
|
||||
$clone = clone $date;
|
||||
$clone = clone $date;
|
||||
$clone->addDays(5 - $date->dayOfWeekIso);
|
||||
app('log')->debug(
|
||||
sprintf('Date is %s, and this is in the weekend, so corrected to %s (Friday).', $date->format('D d M Y'), $clone->format('D d M Y'))
|
||||
@ -70,7 +70,7 @@ trait FiltersWeekends
|
||||
|
||||
// postpone to Monday?
|
||||
if (RecurrenceRepetition::WEEKEND_TO_MONDAY === $repetition->weekend) {
|
||||
$clone = clone $date;
|
||||
$clone = clone $date;
|
||||
$clone->addDays(8 - $date->dayOfWeekIso);
|
||||
app('log')->debug(
|
||||
sprintf('Date is %s, and this is in the weekend, so corrected to %s (Monday).', $date->format('D d M Y'), $clone->format('D d M Y'))
|
||||
|
@ -54,10 +54,10 @@ trait UserGroupTrait
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function setUser(null | Authenticatable | User $user): void
|
||||
public function setUser(null|Authenticatable|User $user): void
|
||||
{
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
$this->user = $user;
|
||||
if (null === $user->userGroup) {
|
||||
throw new FireflyException(sprintf('User #%d has no user group.', $user->id));
|
||||
}
|
||||
@ -70,15 +70,16 @@ trait UserGroupTrait
|
||||
*/
|
||||
public function setUserGroupById(int $userGroupId): void
|
||||
{
|
||||
$memberships = GroupMembership::where('user_id', $this->user->id)
|
||||
->where('user_group_id', $userGroupId)
|
||||
->count();
|
||||
$memberships = GroupMembership::where('user_id', $this->user->id)
|
||||
->where('user_group_id', $userGroupId)
|
||||
->count()
|
||||
;
|
||||
if (0 === $memberships) {
|
||||
throw new FireflyException(sprintf('User #%d has no access to administration #%d', $this->user->id, $userGroupId));
|
||||
}
|
||||
|
||||
/** @var null|UserGroup $userGroup */
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
if (null === $userGroup) {
|
||||
throw new FireflyException(sprintf('Cannot find administration for user #%d', $this->user->id));
|
||||
}
|
||||
|
@ -82,12 +82,12 @@ trait AppendsLocationData
|
||||
$data['latitude'] = null;
|
||||
$data['zoom_level'] = null;
|
||||
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
$isValidPOST = $this->isValidPost($prefix);
|
||||
$isValidPUT = $this->isValidPUT($prefix);
|
||||
$isValidEmptyPUT = $this->isValidEmptyPUT($prefix);
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
$isValidPOST = $this->isValidPost($prefix);
|
||||
$isValidPUT = $this->isValidPUT($prefix);
|
||||
$isValidEmptyPUT = $this->isValidEmptyPUT($prefix);
|
||||
|
||||
// for a POST (store), all fields must be present and not NULL.
|
||||
if ($isValidPOST) {
|
||||
@ -245,9 +245,9 @@ trait AppendsLocationData
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
|
||||
return (
|
||||
null === $this->get($longitudeKey)
|
||||
&& null === $this->get($latitudeKey)
|
||||
&& null === $this->get($zoomLevelKey))
|
||||
null === $this->get($longitudeKey)
|
||||
&& null === $this->get($latitudeKey)
|
||||
&& null === $this->get($zoomLevelKey))
|
||||
&& (
|
||||
'PUT' === $this->method()
|
||||
|| ('POST' === $this->method() && $this->routeIs('*.update'))
|
||||
|
@ -40,7 +40,7 @@ trait ChecksLogin
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
// Only allow logged-in users
|
||||
$check = auth()->check();
|
||||
$check = auth()->check();
|
||||
if (!$check) {
|
||||
return false;
|
||||
}
|
||||
@ -79,7 +79,7 @@ trait ChecksLogin
|
||||
public function getUserGroup(): ?UserGroup
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$user = auth()->user();
|
||||
app('log')->debug('Now in getUserGroup()');
|
||||
|
||||
/** @var null|UserGroup $userGroup */
|
||||
@ -91,7 +91,7 @@ trait ChecksLogin
|
||||
app('log')->debug(sprintf('Request class has no user_group_id parameter, grab default from user (group #%d).', $user->user_group_id));
|
||||
$userGroupId = (int) $user->user_group_id;
|
||||
}
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
if (null === $userGroup) {
|
||||
app('log')->error(sprintf('Request class has user_group_id (#%d), but group does not exist.', $userGroupId));
|
||||
|
||||
|
@ -27,6 +27,4 @@ namespace FireflyIII\Support\Request;
|
||||
/**
|
||||
* Trait ConvertAPIDataTypes
|
||||
*/
|
||||
trait ConvertAPIDataTypes
|
||||
{
|
||||
}
|
||||
trait ConvertAPIDataTypes {}
|
||||
|
@ -38,13 +38,13 @@ trait GetFilterInstructions
|
||||
return [];
|
||||
}
|
||||
foreach ($set as $info) {
|
||||
$column = $info['column'] ?? 'NOPE';
|
||||
$filterValue = (string) ($info['filter'] ?? self::INVALID_FILTER);
|
||||
$column = $info['column'] ?? 'NOPE';
|
||||
$filterValue = (string) ($info['filter'] ?? self::INVALID_FILTER);
|
||||
if (false === in_array($column, $allowed, true)) {
|
||||
// skip invalid column
|
||||
continue;
|
||||
}
|
||||
$filterType = $config[$column] ?? false;
|
||||
$filterType = $config[$column] ?? false;
|
||||
|
||||
switch ($filterType) {
|
||||
default:
|
||||
|
@ -35,8 +35,8 @@ trait GetSortInstructions
|
||||
return [];
|
||||
}
|
||||
foreach ($set as $info) {
|
||||
$column = $info['column'] ?? 'NOPE';
|
||||
$direction = $info['direction'] ?? 'NOPE';
|
||||
$column = $info['column'] ?? 'NOPE';
|
||||
$direction = $info['direction'] ?? 'NOPE';
|
||||
if ('asc' !== $direction && 'desc' !== $direction) {
|
||||
// skip invalid direction
|
||||
continue;
|
||||
|
@ -35,16 +35,16 @@ use Illuminate\Support\Collection;
|
||||
class AccountSearch implements GenericSearchInterface
|
||||
{
|
||||
/** @var string */
|
||||
public const string SEARCH_ALL = 'all';
|
||||
public const string SEARCH_ALL = 'all';
|
||||
|
||||
/** @var string */
|
||||
public const string SEARCH_IBAN = 'iban';
|
||||
public const string SEARCH_IBAN = 'iban';
|
||||
|
||||
/** @var string */
|
||||
public const string SEARCH_ID = 'id';
|
||||
public const string SEARCH_ID = 'id';
|
||||
|
||||
/** @var string */
|
||||
public const string SEARCH_NAME = 'name';
|
||||
public const string SEARCH_NAME = 'name';
|
||||
|
||||
/** @var string */
|
||||
public const string SEARCH_NUMBER = 'number';
|
||||
@ -61,9 +61,10 @@ class AccountSearch implements GenericSearchInterface
|
||||
public function search(): Collection
|
||||
{
|
||||
$searchQuery = $this->user->accounts()
|
||||
->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id')
|
||||
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
|
||||
->whereIn('account_types.type', $this->types);
|
||||
->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id')
|
||||
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
|
||||
->whereIn('account_types.type', $this->types)
|
||||
;
|
||||
$like = sprintf('%%%s%%', $this->query);
|
||||
$originalQuery = $this->query;
|
||||
|
||||
@ -134,7 +135,7 @@ class AccountSearch implements GenericSearchInterface
|
||||
$this->types = $types;
|
||||
}
|
||||
|
||||
public function setUser(null | Authenticatable | User $user): void
|
||||
public function setUser(null|Authenticatable|User $user): void
|
||||
{
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
|
@ -57,8 +57,6 @@ use Gdbots\QueryParser\Node\Word;
|
||||
use Gdbots\QueryParser\QueryParser;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use LogicException;
|
||||
use TypeError;
|
||||
|
||||
/**
|
||||
* Class OperatorQuerySearch
|
||||
@ -151,7 +149,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
try {
|
||||
$query1 = $parser->parse($query);
|
||||
} catch (LogicException | TypeError $e) {
|
||||
} catch (\LogicException|\TypeError $e) {
|
||||
app('log')->error($e->getMessage());
|
||||
app('log')->error(sprintf('Could not parse search: "%s".', $query));
|
||||
|
||||
@ -203,7 +201,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case Emoticon::class:
|
||||
case Emoji::class:
|
||||
case Mention::class:
|
||||
$allWords = (string) $searchNode->getValue();
|
||||
$allWords = (string) $searchNode->getValue();
|
||||
app('log')->debug(sprintf('Add words "%s" to search string, because Node class is "%s"', $allWords, $class));
|
||||
$this->words[] = $allWords;
|
||||
|
||||
@ -214,10 +212,10 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
/** @var Field $searchNode */
|
||||
// used to search for x:y
|
||||
$operator = strtolower($searchNode->getValue());
|
||||
$value = $searchNode->getNode()->getValue();
|
||||
$prohibited = BoolOperator::PROHIBITED === $searchNode->getBoolOperator();
|
||||
$context = config(sprintf('search.operators.%s.needs_context', $operator));
|
||||
$operator = strtolower($searchNode->getValue());
|
||||
$value = $searchNode->getNode()->getValue();
|
||||
$prohibited = BoolOperator::PROHIBITED === $searchNode->getBoolOperator();
|
||||
$context = config(sprintf('search.operators.%s.needs_context', $operator));
|
||||
|
||||
// is an operator that needs no context, and value is false, then prohibited = true.
|
||||
if ('false' === $value && in_array($operator, $this->validOperators, true) && false === $context && !$prohibited) {
|
||||
@ -277,15 +275,15 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
throw new FireflyException(sprintf('Unsupported search operator: "%s"', $operator));
|
||||
|
||||
// some search operators are ignored, basically:
|
||||
// some search operators are ignored, basically:
|
||||
case 'user_action':
|
||||
app('log')->info(sprintf('Ignore search operator "%s"', $operator));
|
||||
|
||||
return false;
|
||||
|
||||
//
|
||||
// all account related searches:
|
||||
//
|
||||
//
|
||||
// all account related searches:
|
||||
//
|
||||
case 'account_is':
|
||||
$this->searchAccount($value, SearchDirection::BOTH, StringPosition::IS);
|
||||
|
||||
@ -447,7 +445,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'source_account_id':
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
if (null !== $account) {
|
||||
$this->collector->setSourceAccounts(new Collection([$account]));
|
||||
}
|
||||
@ -459,7 +457,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-source_account_id':
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
if (null !== $account) {
|
||||
$this->collector->excludeSourceAccounts(new Collection([$account]));
|
||||
}
|
||||
@ -471,25 +469,25 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'journal_id':
|
||||
$parts = explode(',', $value);
|
||||
$parts = explode(',', $value);
|
||||
$this->collector->setJournalIds($parts);
|
||||
|
||||
break;
|
||||
|
||||
case '-journal_id':
|
||||
$parts = explode(',', $value);
|
||||
$parts = explode(',', $value);
|
||||
$this->collector->excludeJournalIds($parts);
|
||||
|
||||
break;
|
||||
|
||||
case 'id':
|
||||
$parts = explode(',', $value);
|
||||
$parts = explode(',', $value);
|
||||
$this->collector->setIds($parts);
|
||||
|
||||
break;
|
||||
|
||||
case '-id':
|
||||
$parts = explode(',', $value);
|
||||
$parts = explode(',', $value);
|
||||
$this->collector->excludeIds($parts);
|
||||
|
||||
break;
|
||||
@ -575,7 +573,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'destination_account_id':
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
if (null !== $account) {
|
||||
$this->collector->setDestinationAccounts(new Collection([$account]));
|
||||
}
|
||||
@ -586,7 +584,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-destination_account_id':
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
$account = $this->accountRepository->find((int) $value);
|
||||
if (null !== $account) {
|
||||
$this->collector->excludeDestinationAccounts(new Collection([$account]));
|
||||
}
|
||||
@ -597,8 +595,8 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'account_id':
|
||||
$parts = explode(',', $value);
|
||||
$collection = new Collection();
|
||||
$parts = explode(',', $value);
|
||||
$collection = new Collection();
|
||||
foreach ($parts as $accountId) {
|
||||
$account = $this->accountRepository->find((int) $accountId);
|
||||
if (null !== $account) {
|
||||
@ -615,8 +613,8 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-account_id':
|
||||
$parts = explode(',', $value);
|
||||
$collection = new Collection();
|
||||
$parts = explode(',', $value);
|
||||
$collection = new Collection();
|
||||
foreach ($parts as $accountId) {
|
||||
$account = $this->accountRepository->find((int) $accountId);
|
||||
if (null !== $account) {
|
||||
@ -632,48 +630,48 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// cash account
|
||||
//
|
||||
//
|
||||
// cash account
|
||||
//
|
||||
case 'source_is_cash':
|
||||
$account = $this->getCashAccount();
|
||||
$account = $this->getCashAccount();
|
||||
$this->collector->setSourceAccounts(new Collection([$account]));
|
||||
|
||||
break;
|
||||
|
||||
case '-source_is_cash':
|
||||
$account = $this->getCashAccount();
|
||||
$account = $this->getCashAccount();
|
||||
$this->collector->excludeSourceAccounts(new Collection([$account]));
|
||||
|
||||
break;
|
||||
|
||||
case 'destination_is_cash':
|
||||
$account = $this->getCashAccount();
|
||||
$account = $this->getCashAccount();
|
||||
$this->collector->setDestinationAccounts(new Collection([$account]));
|
||||
|
||||
break;
|
||||
|
||||
case '-destination_is_cash':
|
||||
$account = $this->getCashAccount();
|
||||
$account = $this->getCashAccount();
|
||||
$this->collector->excludeDestinationAccounts(new Collection([$account]));
|
||||
|
||||
break;
|
||||
|
||||
case 'account_is_cash':
|
||||
$account = $this->getCashAccount();
|
||||
$account = $this->getCashAccount();
|
||||
$this->collector->setAccounts(new Collection([$account]));
|
||||
|
||||
break;
|
||||
|
||||
case '-account_is_cash':
|
||||
$account = $this->getCashAccount();
|
||||
$account = $this->getCashAccount();
|
||||
$this->collector->excludeAccounts(new Collection([$account]));
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// description
|
||||
//
|
||||
//
|
||||
// description
|
||||
//
|
||||
case 'description_starts':
|
||||
$this->collector->descriptionStarts([$value]);
|
||||
|
||||
@ -695,7 +693,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'description_contains':
|
||||
$this->words[] = $value;
|
||||
$this->words[] = $value;
|
||||
|
||||
return false;
|
||||
|
||||
@ -714,11 +712,11 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// currency
|
||||
//
|
||||
//
|
||||
// currency
|
||||
//
|
||||
case 'currency_is':
|
||||
$currency = $this->findCurrency($value);
|
||||
$currency = $this->findCurrency($value);
|
||||
if (null !== $currency) {
|
||||
$this->collector->setCurrency($currency);
|
||||
}
|
||||
@ -729,7 +727,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-currency_is':
|
||||
$currency = $this->findCurrency($value);
|
||||
$currency = $this->findCurrency($value);
|
||||
if (null !== $currency) {
|
||||
$this->collector->excludeCurrency($currency);
|
||||
}
|
||||
@ -740,7 +738,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'foreign_currency_is':
|
||||
$currency = $this->findCurrency($value);
|
||||
$currency = $this->findCurrency($value);
|
||||
if (null !== $currency) {
|
||||
$this->collector->setForeignCurrency($currency);
|
||||
}
|
||||
@ -751,7 +749,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-foreign_currency_is':
|
||||
$currency = $this->findCurrency($value);
|
||||
$currency = $this->findCurrency($value);
|
||||
if (null !== $currency) {
|
||||
$this->collector->excludeForeignCurrency($currency);
|
||||
}
|
||||
@ -761,9 +759,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// attachments
|
||||
//
|
||||
//
|
||||
// attachments
|
||||
//
|
||||
case 'has_attachments':
|
||||
case '-has_no_attachments':
|
||||
app('log')->debug('Set collector to filter on attachments.');
|
||||
@ -778,8 +776,8 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// categories
|
||||
//
|
||||
// categories
|
||||
case '-has_any_category':
|
||||
case 'has_no_category':
|
||||
$this->collector->withoutCategory();
|
||||
@ -793,7 +791,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'category_is':
|
||||
$category = $this->categoryRepository->findByName($value);
|
||||
$category = $this->categoryRepository->findByName($value);
|
||||
if (null !== $category) {
|
||||
$this->collector->setCategory($category);
|
||||
|
||||
@ -804,7 +802,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-category_is':
|
||||
$category = $this->categoryRepository->findByName($value);
|
||||
$category = $this->categoryRepository->findByName($value);
|
||||
if (null !== $category) {
|
||||
$this->collector->excludeCategory($category);
|
||||
|
||||
@ -814,7 +812,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'category_ends':
|
||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setCategories($result);
|
||||
}
|
||||
@ -825,7 +823,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-category_ends':
|
||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeCategories($result);
|
||||
}
|
||||
@ -836,7 +834,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'category_starts':
|
||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setCategories($result);
|
||||
}
|
||||
@ -847,7 +845,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-category_starts':
|
||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeCategories($result);
|
||||
}
|
||||
@ -858,7 +856,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'category_contains':
|
||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setCategories($result);
|
||||
}
|
||||
@ -869,7 +867,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-category_contains':
|
||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeCategories($result);
|
||||
}
|
||||
@ -879,9 +877,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// budgets
|
||||
//
|
||||
//
|
||||
// budgets
|
||||
//
|
||||
case '-has_any_budget':
|
||||
case 'has_no_budget':
|
||||
$this->collector->withoutBudget();
|
||||
@ -895,7 +893,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'budget_contains':
|
||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBudgets($result);
|
||||
}
|
||||
@ -906,7 +904,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-budget_contains':
|
||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeBudgets($result);
|
||||
}
|
||||
@ -917,7 +915,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'budget_is':
|
||||
$budget = $this->budgetRepository->findByName($value);
|
||||
$budget = $this->budgetRepository->findByName($value);
|
||||
if (null !== $budget) {
|
||||
$this->collector->setBudget($budget);
|
||||
|
||||
@ -928,7 +926,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-budget_is':
|
||||
$budget = $this->budgetRepository->findByName($value);
|
||||
$budget = $this->budgetRepository->findByName($value);
|
||||
if (null !== $budget) {
|
||||
$this->collector->excludeBudget($budget);
|
||||
|
||||
@ -939,7 +937,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'budget_ends':
|
||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBudgets($result);
|
||||
}
|
||||
@ -950,7 +948,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-budget_ends':
|
||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeBudgets($result);
|
||||
}
|
||||
@ -961,7 +959,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'budget_starts':
|
||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBudgets($result);
|
||||
}
|
||||
@ -972,7 +970,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-budget_starts':
|
||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeBudgets($result);
|
||||
}
|
||||
@ -982,9 +980,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// bill
|
||||
//
|
||||
//
|
||||
// bill
|
||||
//
|
||||
case '-has_any_bill':
|
||||
case 'has_no_bill':
|
||||
$this->collector->withoutBill();
|
||||
@ -998,7 +996,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'bill_contains':
|
||||
$result = $this->billRepository->searchBill($value, 1337);
|
||||
$result = $this->billRepository->searchBill($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBills($result);
|
||||
|
||||
@ -1009,7 +1007,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-bill_contains':
|
||||
$result = $this->billRepository->searchBill($value, 1337);
|
||||
$result = $this->billRepository->searchBill($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeBills($result);
|
||||
|
||||
@ -1020,7 +1018,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'bill_is':
|
||||
$bill = $this->billRepository->findByName($value);
|
||||
$bill = $this->billRepository->findByName($value);
|
||||
if (null !== $bill) {
|
||||
$this->collector->setBill($bill);
|
||||
|
||||
@ -1031,7 +1029,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-bill_is':
|
||||
$bill = $this->billRepository->findByName($value);
|
||||
$bill = $this->billRepository->findByName($value);
|
||||
if (null !== $bill) {
|
||||
$this->collector->excludeBills(new Collection([$bill]));
|
||||
|
||||
@ -1042,7 +1040,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'bill_ends':
|
||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBills($result);
|
||||
}
|
||||
@ -1053,7 +1051,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-bill_ends':
|
||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeBills($result);
|
||||
}
|
||||
@ -1064,7 +1062,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'bill_starts':
|
||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->setBills($result);
|
||||
}
|
||||
@ -1075,7 +1073,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-bill_starts':
|
||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||
if ($result->count() > 0) {
|
||||
$this->collector->excludeBills($result);
|
||||
}
|
||||
@ -1085,9 +1083,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// tags
|
||||
//
|
||||
//
|
||||
// tags
|
||||
//
|
||||
case '-has_any_tag':
|
||||
case 'has_no_tag':
|
||||
$this->collector->withoutTags();
|
||||
@ -1102,7 +1100,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
case '-tag_is_not':
|
||||
case 'tag_is':
|
||||
$result = $this->tagRepository->findByTag($value);
|
||||
$result = $this->tagRepository->findByTag($value);
|
||||
if (null !== $result) {
|
||||
$this->includeTags[] = $result->id;
|
||||
$this->includeTags = array_unique($this->includeTags);
|
||||
@ -1116,7 +1114,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'tag_contains':
|
||||
$tags = $this->tagRepository->searchTag($value);
|
||||
$tags = $this->tagRepository->searchTag($value);
|
||||
if (0 === $tags->count()) {
|
||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||
$this->collector->findNothing();
|
||||
@ -1130,7 +1128,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'tag_starts':
|
||||
$tags = $this->tagRepository->tagStartsWith($value);
|
||||
$tags = $this->tagRepository->tagStartsWith($value);
|
||||
if (0 === $tags->count()) {
|
||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||
$this->collector->findNothing();
|
||||
@ -1144,7 +1142,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-tag_starts':
|
||||
$tags = $this->tagRepository->tagStartsWith($value);
|
||||
$tags = $this->tagRepository->tagStartsWith($value);
|
||||
if (0 === $tags->count()) {
|
||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||
$this->collector->findNothing();
|
||||
@ -1157,7 +1155,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case 'tag_ends':
|
||||
$tags = $this->tagRepository->tagEndsWith($value);
|
||||
$tags = $this->tagRepository->tagEndsWith($value);
|
||||
if (0 === $tags->count()) {
|
||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||
$this->collector->findNothing();
|
||||
@ -1170,7 +1168,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-tag_ends':
|
||||
$tags = $this->tagRepository->tagEndsWith($value);
|
||||
$tags = $this->tagRepository->tagEndsWith($value);
|
||||
if (0 === $tags->count()) {
|
||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||
$this->collector->findNothing();
|
||||
@ -1183,7 +1181,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
break;
|
||||
|
||||
case '-tag_contains':
|
||||
$tags = $this->tagRepository->searchTag($value)->keyBy('id');
|
||||
$tags = $this->tagRepository->searchTag($value)->keyBy('id');
|
||||
|
||||
if (0 === $tags->count()) {
|
||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||
@ -1198,7 +1196,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
case '-tag_is':
|
||||
case 'tag_is_not':
|
||||
$result = $this->tagRepository->findByTag($value);
|
||||
$result = $this->tagRepository->findByTag($value);
|
||||
if (null !== $result) {
|
||||
$this->excludeTags[] = $result->id;
|
||||
$this->excludeTags = array_unique($this->excludeTags);
|
||||
@ -1206,9 +1204,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// notes
|
||||
//
|
||||
//
|
||||
// notes
|
||||
//
|
||||
case 'notes_contains':
|
||||
$this->collector->notesContain($value);
|
||||
|
||||
@ -1271,14 +1269,14 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// amount
|
||||
//
|
||||
//
|
||||
// amount
|
||||
//
|
||||
case 'amount_is':
|
||||
// strip comma's, make dots.
|
||||
app('log')->debug(sprintf('Original value "%s"', $value));
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->amountIs($amount);
|
||||
|
||||
@ -1287,8 +1285,8 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case '-amount_is':
|
||||
// strip comma's, make dots.
|
||||
app('log')->debug(sprintf('Original value "%s"', $value));
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->amountIsNot($amount);
|
||||
|
||||
@ -1296,9 +1294,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
case 'foreign_amount_is':
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', $value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
|
||||
$amount = app('steam')->positive($value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->foreignAmountIs($amount);
|
||||
|
||||
@ -1306,9 +1304,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
case '-foreign_amount_is':
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', $value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
|
||||
$amount = app('steam')->positive($value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->foreignAmountIsNot($amount);
|
||||
|
||||
@ -1317,9 +1315,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case '-amount_more':
|
||||
case 'amount_less':
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', $value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
|
||||
$amount = app('steam')->positive($value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->amountLess($amount);
|
||||
|
||||
@ -1328,9 +1326,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case '-foreign_amount_more':
|
||||
case 'foreign_amount_less':
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', $value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
|
||||
$amount = app('steam')->positive($value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->foreignAmountLess($amount);
|
||||
|
||||
@ -1340,8 +1338,8 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'amount_more':
|
||||
app('log')->debug(sprintf('Now handling operator "%s"', $operator));
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->amountMore($amount);
|
||||
|
||||
@ -1351,16 +1349,16 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'foreign_amount_more':
|
||||
app('log')->debug(sprintf('Now handling operator "%s"', $operator));
|
||||
// strip comma's, make dots.
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
$value = str_replace(',', '.', $value);
|
||||
$amount = app('steam')->positive($value);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||
$this->collector->foreignAmountMore($amount);
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// transaction type
|
||||
//
|
||||
//
|
||||
// transaction type
|
||||
//
|
||||
case 'transaction_type':
|
||||
$this->collector->setTypes([ucfirst($value)]);
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
@ -1373,152 +1371,152 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// dates
|
||||
//
|
||||
//
|
||||
// dates
|
||||
//
|
||||
case '-date_on':
|
||||
case 'date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactDateParams($range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'date_before':
|
||||
case '-date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setDateBeforeParams($range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'date_after':
|
||||
case '-date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setDateAfterParams($range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'interest_date_on':
|
||||
case '-interest_date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactMetaDateParams('interest_date', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'interest_date_before':
|
||||
case '-interest_date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateBeforeParams('interest_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'interest_date_after':
|
||||
case '-interest_date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateAfterParams('interest_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'book_date_on':
|
||||
case '-book_date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactMetaDateParams('book_date', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'book_date_before':
|
||||
case '-book_date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateBeforeParams('book_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'book_date_after':
|
||||
case '-book_date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateAfterParams('book_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'process_date_on':
|
||||
case '-process_date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactMetaDateParams('process_date', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'process_date_before':
|
||||
case '-process_date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateBeforeParams('process_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'process_date_after':
|
||||
case '-process_date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateAfterParams('process_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'due_date_on':
|
||||
case '-due_date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactMetaDateParams('due_date', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'due_date_before':
|
||||
case '-due_date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateBeforeParams('due_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'due_date_after':
|
||||
case '-due_date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateAfterParams('due_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'payment_date_on':
|
||||
case '-payment_date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactMetaDateParams('payment_date', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'payment_date_before':
|
||||
case '-payment_date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateBeforeParams('payment_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'payment_date_after':
|
||||
case '-payment_date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateAfterParams('payment_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'invoice_date_on':
|
||||
case '-invoice_date_on':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactMetaDateParams('invoice_date', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
|
||||
case 'invoice_date_before':
|
||||
case '-invoice_date_after':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateBeforeParams('invoice_date', $range);
|
||||
|
||||
return false;
|
||||
|
||||
case 'invoice_date_after':
|
||||
case '-invoice_date_before':
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setMetaDateAfterParams('invoice_date', $range);
|
||||
|
||||
return false;
|
||||
@ -1526,7 +1524,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'created_at_on':
|
||||
case '-created_at_on':
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactObjectDateParams('created_at', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
@ -1534,7 +1532,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'created_at_before':
|
||||
case '-created_at_after':
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setObjectDateBeforeParams('created_at', $range);
|
||||
|
||||
return false;
|
||||
@ -1542,7 +1540,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'created_at_after':
|
||||
case '-created_at_before':
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setObjectDateAfterParams('created_at', $range);
|
||||
|
||||
return false;
|
||||
@ -1550,7 +1548,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'updated_at_on':
|
||||
case '-updated_at_on':
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setExactObjectDateParams('updated_at', $range, $prohibited);
|
||||
|
||||
return false;
|
||||
@ -1558,7 +1556,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'updated_at_before':
|
||||
case '-updated_at_after':
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setObjectDateBeforeParams('updated_at', $range);
|
||||
|
||||
return false;
|
||||
@ -1566,14 +1564,14 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'updated_at_after':
|
||||
case '-updated_at_before':
|
||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$range = $this->parseDateRange($operator, $value);
|
||||
$this->setObjectDateAfterParams('updated_at', $range);
|
||||
|
||||
return false;
|
||||
|
||||
//
|
||||
// external URL
|
||||
//
|
||||
//
|
||||
// external URL
|
||||
//
|
||||
case '-any_external_url':
|
||||
case 'no_external_url':
|
||||
$this->collector->withoutExternalUrl();
|
||||
@ -1638,9 +1636,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// other fields
|
||||
//
|
||||
//
|
||||
// other fields
|
||||
//
|
||||
case 'external_id_is':
|
||||
$this->collector->setExternalId($value);
|
||||
|
||||
@ -1842,7 +1840,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
$operator = substr($operator, 1);
|
||||
}
|
||||
|
||||
$config = config(sprintf('search.operators.%s', $operator));
|
||||
$config = config(sprintf('search.operators.%s', $operator));
|
||||
if (null === $config) {
|
||||
throw new FireflyException(sprintf('No configuration for search operator "%s"', $operator));
|
||||
}
|
||||
@ -1896,7 +1894,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
}
|
||||
// string position (default): starts with:
|
||||
$stringMethod = 'str_starts_with';
|
||||
$stringMethod = 'str_starts_with';
|
||||
|
||||
// string position: ends with:
|
||||
if (StringPosition::ENDS === $stringPosition) {
|
||||
@ -1910,7 +1908,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
|
||||
// get accounts:
|
||||
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 1337);
|
||||
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 1337);
|
||||
if (0 === $accounts->count() && false === $prohibited) {
|
||||
app('log')->debug('Found zero accounts, search for non existing account, NO results will be returned.');
|
||||
$this->collector->findNothing();
|
||||
@ -1923,7 +1921,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
return;
|
||||
}
|
||||
app('log')->debug(sprintf('Found %d accounts, will filter.', $accounts->count()));
|
||||
$filtered = $accounts->filter(
|
||||
$filtered = $accounts->filter(
|
||||
static function (Account $account) use ($value, $stringMethod) {
|
||||
return $stringMethod(strtolower($account->name), strtolower($value));
|
||||
}
|
||||
@ -1978,7 +1976,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
|
||||
// string position (default): starts with:
|
||||
$stringMethod = 'str_starts_with';
|
||||
$stringMethod = 'str_starts_with';
|
||||
|
||||
// string position: ends with:
|
||||
if (StringPosition::ENDS === $stringPosition) {
|
||||
@ -1992,7 +1990,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
|
||||
// search for accounts:
|
||||
$accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 1337);
|
||||
$accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 1337);
|
||||
if (0 === $accounts->count()) {
|
||||
app('log')->debug('Found zero accounts, search for invalid account.');
|
||||
$this->collector->findNothing();
|
||||
@ -2002,7 +2000,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
// if found, do filter
|
||||
app('log')->debug(sprintf('Found %d accounts, will filter.', $accounts->count()));
|
||||
$filtered = $accounts->filter(
|
||||
$filtered = $accounts->filter(
|
||||
static function (Account $account) use ($value, $stringMethod) {
|
||||
// either IBAN or account number
|
||||
$ibanMatch = $stringMethod(strtolower((string) $account->iban), strtolower($value));
|
||||
|
@ -24,18 +24,12 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use stdClass;
|
||||
use Str;
|
||||
use ValueError;
|
||||
|
||||
/**
|
||||
* Class Steam.
|
||||
@ -44,8 +38,8 @@ class Steam
|
||||
{
|
||||
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
||||
{
|
||||
$type = $account->accountType->type;
|
||||
$list = config('firefly.valid_currency_account_types');
|
||||
$type = $account->accountType->type;
|
||||
$list = config('firefly.valid_currency_account_types');
|
||||
|
||||
// return null if not in this list.
|
||||
if (!in_array($type, $list, true)) {
|
||||
@ -55,6 +49,7 @@ class Steam
|
||||
if (null === $result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return TransactionCurrency::find((int) $result->data);
|
||||
}
|
||||
|
||||
@ -72,7 +67,6 @@ class Steam
|
||||
return $sum;
|
||||
}
|
||||
|
||||
|
||||
public function finalAccountBalanceInRange(Account $account, Carbon $start, Carbon $end): array
|
||||
{
|
||||
// expand period.
|
||||
@ -80,7 +74,7 @@ class Steam
|
||||
$end->addDay()->endOfDay();
|
||||
|
||||
// set up cache
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty('final-balance-in-range');
|
||||
$cache->addProperty($start);
|
||||
@ -89,51 +83,52 @@ class Steam
|
||||
// return $cache->get();
|
||||
}
|
||||
|
||||
$balances = [];
|
||||
$formatted = $start->format('Y-m-d');
|
||||
$startBalance = $this->finalAccountBalance($account, $start);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||
$currency = $this->getAccountCurrency($account) ?? $defaultCurrency;
|
||||
$currencies = [
|
||||
$balances = [];
|
||||
$formatted = $start->format('Y-m-d');
|
||||
$startBalance = $this->finalAccountBalance($account, $start);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||
$currency = $this->getAccountCurrency($account) ?? $defaultCurrency;
|
||||
$currencies = [
|
||||
$currency->id => $currency,
|
||||
$defaultCurrency->id => $defaultCurrency,
|
||||
];
|
||||
$startBalance[$defaultCurrency->code] ??= '0';
|
||||
$startBalance[$currency->code] ??= '0';
|
||||
$balances[$formatted] = $startBalance;
|
||||
$balances[$formatted] = $startBalance;
|
||||
|
||||
|
||||
// sums up the balance changes per day, for foreign, native and normal amounts.
|
||||
$set = $account->transactions()
|
||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
||||
->groupBy('transaction_journals.date')
|
||||
->groupBy('transactions.transaction_currency_id')
|
||||
->groupBy('transactions.foreign_currency_id')
|
||||
->orderBy('transaction_journals.date', 'ASC')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->get(
|
||||
[ // @phpstan-ignore-line
|
||||
'transaction_journals.date',
|
||||
'transactions.transaction_currency_id',
|
||||
DB::raw('SUM(transactions.amount) AS modified'),
|
||||
'transactions.foreign_currency_id',
|
||||
DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
|
||||
DB::raw('SUM(transactions.native_amount) AS modified_native'),
|
||||
]
|
||||
);
|
||||
$set = $account->transactions()
|
||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
||||
->groupBy('transaction_journals.date')
|
||||
->groupBy('transactions.transaction_currency_id')
|
||||
->groupBy('transactions.foreign_currency_id')
|
||||
->orderBy('transaction_journals.date', 'ASC')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->get(
|
||||
[ // @phpstan-ignore-line
|
||||
'transaction_journals.date',
|
||||
'transactions.transaction_currency_id',
|
||||
\DB::raw('SUM(transactions.amount) AS modified'),
|
||||
'transactions.foreign_currency_id',
|
||||
\DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
|
||||
\DB::raw('SUM(transactions.native_amount) AS modified_native'),
|
||||
]
|
||||
)
|
||||
;
|
||||
|
||||
$currentBalance = $startBalance;
|
||||
$currentBalance = $startBalance;
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
|
||||
// normal, native and foreign amount
|
||||
$carbon = new Carbon($entry->date, $entry->date_tz);
|
||||
$modified = (string) (null === $entry->modified ? '0' : $entry->modified);
|
||||
$foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign);
|
||||
$nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native);
|
||||
$carbon = new Carbon($entry->date, $entry->date_tz);
|
||||
$modified = (string) (null === $entry->modified ? '0' : $entry->modified);
|
||||
$foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign);
|
||||
$nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native);
|
||||
|
||||
// add "modified" to amount if the currency id matches the account currency id.
|
||||
if ($entry->transaction_currency_id === $currency->id) {
|
||||
@ -142,7 +137,7 @@ class Steam
|
||||
}
|
||||
|
||||
// always add the native balance, even if it ends up at zero.
|
||||
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeModified);
|
||||
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeModified);
|
||||
|
||||
// add modified foreign to the array
|
||||
if (null !== $entry->foreign_currency_id) {
|
||||
@ -159,11 +154,13 @@ class Steam
|
||||
return $balances;
|
||||
}
|
||||
|
||||
public function finalAccountsBalance(Collection $accounts, Carbon $date): array {
|
||||
public function finalAccountsBalance(Collection $accounts, Carbon $date): array
|
||||
{
|
||||
$balances = [];
|
||||
foreach ($accounts as $account) {
|
||||
$balances[$account->id] = $this->finalAccountBalance($account, $date);
|
||||
}
|
||||
|
||||
return $balances;
|
||||
}
|
||||
|
||||
@ -186,10 +183,10 @@ class Steam
|
||||
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
|
||||
if (str_contains($number, '.')) {
|
||||
if ('-' !== $number[0]) {
|
||||
return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision);
|
||||
return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision);
|
||||
}
|
||||
|
||||
return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
|
||||
return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision);
|
||||
}
|
||||
|
||||
return $number;
|
||||
@ -261,26 +258,22 @@ class Steam
|
||||
* THAT currency.
|
||||
* "native_balance" the balance according to the "native_amount" + "native_foreign_amount" fields.
|
||||
* "ABC" the balance in this particular currency code (may repeat for each found currency).
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function finalAccountBalance(Account $account, Carbon $date): array
|
||||
{
|
||||
$native = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||
$currency = $this->getAccountCurrency($account) ?? $native;
|
||||
$return = [
|
||||
$native = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||
$currency = $this->getAccountCurrency($account) ?? $native;
|
||||
$return = [
|
||||
'native_balance' => '0',
|
||||
];
|
||||
Log::debug(sprintf('Now in finalAccountBalance("%s", "%s")', $account->name, $date->format('Y-m-d H:i:s')));
|
||||
// first, the "balance", as described earlier.
|
||||
$array = $account->transactions()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||
->where('transactions.transaction_currency_id', $currency->id)
|
||||
->get(['transactions.amount'])->toArray();
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||
->where('transactions.transaction_currency_id', $currency->id)
|
||||
->get(['transactions.amount'])->toArray()
|
||||
;
|
||||
$return['balance'] = $this->sumTransactions($array, 'amount');
|
||||
//Log::debug(sprintf('balance is %s', $return['balance']));
|
||||
// add virtual balance:
|
||||
@ -290,9 +283,10 @@ class Steam
|
||||
// then, native balance (if necessary(
|
||||
if ($native->id !== $currency->id) {
|
||||
$array = $account->transactions()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||
->get(['transactions.native_amount'])->toArray();
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||
->get(['transactions.native_amount'])->toArray()
|
||||
;
|
||||
$return['native_balance'] = $this->sumTransactions($array, 'native_amount');
|
||||
// Log::debug(sprintf('native_balance is %s', $return['native_balance']));
|
||||
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['balance']);
|
||||
@ -307,6 +301,7 @@ class Steam
|
||||
->get(['transaction_currencies.code', 'transactions.amount'])->toArray();
|
||||
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
||||
// Log::debug('All others are (joined)', $others);
|
||||
|
||||
return array_merge($return, $others);
|
||||
}
|
||||
|
||||
@ -318,6 +313,7 @@ class Steam
|
||||
$groupKey = $item[$group] ?? 'unknown';
|
||||
$return[$groupKey] = bcadd($return[$groupKey] ?? '0', $item[$field]);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@ -330,7 +326,7 @@ class Steam
|
||||
|
||||
try {
|
||||
$hostName = gethostbyaddr($ipAddress);
|
||||
} catch (Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
app('log')->error($e->getMessage());
|
||||
$hostName = $ipAddress;
|
||||
}
|
||||
@ -346,15 +342,15 @@ class Steam
|
||||
{
|
||||
$list = [];
|
||||
|
||||
$set = auth()->user()->transactions()
|
||||
->whereIn('transactions.account_id', $accounts)
|
||||
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
|
||||
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
|
||||
$set = auth()->user()->transactions()
|
||||
->whereIn('transactions.account_id', $accounts)
|
||||
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
|
||||
->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
|
||||
;
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
$date = new Carbon($entry->max_date, config('app.timezone'));
|
||||
$date = new Carbon($entry->max_date, config('app.timezone'));
|
||||
$date->setTimezone(config('app.timezone'));
|
||||
$list[(int)$entry->account_id] = $date;
|
||||
}
|
||||
@ -429,9 +425,9 @@ class Steam
|
||||
public function getSafeUrl(string $unknownUrl, string $safeUrl): string
|
||||
{
|
||||
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
|
||||
$returnUrl = $safeUrl;
|
||||
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
|
||||
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
|
||||
$returnUrl = $safeUrl;
|
||||
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
|
||||
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
|
||||
|
||||
if (null !== $unknownHost && $unknownHost === $safeHost) {
|
||||
$returnUrl = $unknownUrl;
|
||||
@ -439,7 +435,7 @@ class Steam
|
||||
|
||||
// URL must not lead to weird pages
|
||||
$forbiddenWords = ['jscript', 'json', 'debug', 'serviceworker', 'offline', 'delete', '/login', '/attachments/view'];
|
||||
if (Str::contains($returnUrl, $forbiddenWords)) {
|
||||
if (\Str::contains($returnUrl, $forbiddenWords)) {
|
||||
$returnUrl = $safeUrl;
|
||||
}
|
||||
|
||||
@ -468,7 +464,7 @@ class Steam
|
||||
*/
|
||||
public function floatalize(string $value): string
|
||||
{
|
||||
$value = strtoupper($value);
|
||||
$value = strtoupper($value);
|
||||
if (!str_contains($value, 'E')) {
|
||||
return $value;
|
||||
}
|
||||
@ -537,7 +533,7 @@ class Steam
|
||||
if (-1 === bccomp($amount, '0')) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
} catch (ValueError $e) {
|
||||
} catch (\ValueError $e) {
|
||||
Log::error(sprintf('ValueError in Steam::positive("%s"): %s', $amount, $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
|
@ -24,8 +24,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\System;
|
||||
|
||||
use Artisan;
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Laravel\Passport\Console\KeysCommand;
|
||||
@ -67,7 +65,7 @@ class OAuthKeys
|
||||
try {
|
||||
$privateKey = (string) app('fireflyconfig')->get(self::PRIVATE_KEY)?->data;
|
||||
$publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_KEY)?->data;
|
||||
} catch (ContainerExceptionInterface | FireflyException | NotFoundExceptionInterface $e) {
|
||||
} catch (ContainerExceptionInterface|FireflyException|NotFoundExceptionInterface $e) {
|
||||
app('log')->error(sprintf('Could not validate keysInDatabase(): %s', $e->getMessage()));
|
||||
app('log')->error($e->getTraceAsString());
|
||||
}
|
||||
@ -89,16 +87,16 @@ class OAuthKeys
|
||||
|
||||
public static function generateKeys(): void
|
||||
{
|
||||
Artisan::registerCommand(new KeysCommand());
|
||||
Artisan::call('firefly-iii:laravel-passport-keys');
|
||||
\Artisan::registerCommand(new KeysCommand());
|
||||
\Artisan::call('firefly-iii:laravel-passport-keys');
|
||||
}
|
||||
|
||||
public static function storeKeysInDB(): void
|
||||
{
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
app('fireflyconfig')->set(self::PRIVATE_KEY, Crypt::encrypt(file_get_contents($private)));
|
||||
app('fireflyconfig')->set(self::PUBLIC_KEY, Crypt::encrypt(file_get_contents($public)));
|
||||
app('fireflyconfig')->set(self::PRIVATE_KEY, \Crypt::encrypt(file_get_contents($private)));
|
||||
app('fireflyconfig')->set(self::PUBLIC_KEY, \Crypt::encrypt(file_get_contents($public)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,8 +108,8 @@ class OAuthKeys
|
||||
$publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_KEY)?->data;
|
||||
|
||||
try {
|
||||
$privateContent = Crypt::decrypt($privateKey);
|
||||
$publicContent = Crypt::decrypt($publicKey);
|
||||
$privateContent = \Crypt::decrypt($privateKey);
|
||||
$publicContent = \Crypt::decrypt($publicKey);
|
||||
} catch (DecryptException $e) {
|
||||
app('log')->error('Could not decrypt pub/private keypair.');
|
||||
app('log')->error($e->getMessage());
|
||||
@ -122,8 +120,8 @@ class OAuthKeys
|
||||
|
||||
return false;
|
||||
}
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
file_put_contents($private, $privateContent);
|
||||
file_put_contents($public, $publicContent);
|
||||
|
||||
|
@ -108,8 +108,8 @@ class AmountFormat extends AbstractExtension
|
||||
return new TwigFunction(
|
||||
'formatAmountBySymbol',
|
||||
static function (string $amount, string $symbol, ?int $decimalPlaces = null, ?bool $coloured = null): string {
|
||||
$decimalPlaces ??= 2;
|
||||
$coloured ??= true;
|
||||
$decimalPlaces ??= 2;
|
||||
$coloured ??= true;
|
||||
$currency = new TransactionCurrency();
|
||||
$currency->symbol = $symbol;
|
||||
$currency->decimal_places = $decimalPlaces;
|
||||
|
@ -78,6 +78,7 @@ class General extends AbstractExtension
|
||||
if (!$convertToNative || $currency->code === $native->code) {
|
||||
$strings[] = app('amount')->formatAnything($currency, $balance, false);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if ('native_balance' === $key) {
|
||||
@ -85,6 +86,7 @@ class General extends AbstractExtension
|
||||
if ($convertToNative) {
|
||||
$strings[] = app('amount')->formatAnything($native, $balance, false);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($key !== $currency->code) {
|
||||
@ -108,15 +110,15 @@ class General extends AbstractExtension
|
||||
static function (int $size): string {
|
||||
// less than one GB, more than one MB
|
||||
if ($size < (1024 * 1024 * 2014) && $size >= (1024 * 1024)) {
|
||||
return round($size / (1024 * 1024), 2) . ' MB';
|
||||
return round($size / (1024 * 1024), 2).' MB';
|
||||
}
|
||||
|
||||
// less than one MB
|
||||
if ($size < (1024 * 1024)) {
|
||||
return round($size / 1024, 2) . ' KB';
|
||||
return round($size / 1024, 2).' KB';
|
||||
}
|
||||
|
||||
return $size . ' bytes';
|
||||
return $size.' bytes';
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -138,7 +140,7 @@ class General extends AbstractExtension
|
||||
case 'application/pdf':
|
||||
return 'fa-file-pdf-o';
|
||||
|
||||
// image
|
||||
// image
|
||||
case 'image/png':
|
||||
case 'image/jpeg':
|
||||
case 'image/svg+xml':
|
||||
@ -147,7 +149,7 @@ class General extends AbstractExtension
|
||||
case 'application/vnd.oasis.opendocument.image':
|
||||
return 'fa-file-image-o';
|
||||
|
||||
// MS word
|
||||
// MS word
|
||||
case 'application/msword':
|
||||
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
||||
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template':
|
||||
@ -163,7 +165,7 @@ class General extends AbstractExtension
|
||||
case 'application/vnd.oasis.opendocument.text-master':
|
||||
return 'fa-file-word-o';
|
||||
|
||||
// MS excel
|
||||
// MS excel
|
||||
case 'application/vnd.ms-excel':
|
||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template':
|
||||
@ -174,7 +176,7 @@ class General extends AbstractExtension
|
||||
case 'application/vnd.oasis.opendocument.spreadsheet-template':
|
||||
return 'fa-file-excel-o';
|
||||
|
||||
// MS powerpoint
|
||||
// MS powerpoint
|
||||
case 'application/vnd.ms-powerpoint':
|
||||
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
|
||||
case 'application/vnd.openxmlformats-officedocument.presentationml.template':
|
||||
@ -186,7 +188,7 @@ class General extends AbstractExtension
|
||||
case 'application/vnd.oasis.opendocument.presentation-template':
|
||||
return 'fa-file-powerpoint-o';
|
||||
|
||||
// calc
|
||||
// calc
|
||||
case 'application/vnd.sun.xml.draw':
|
||||
case 'application/vnd.sun.xml.draw.template':
|
||||
case 'application/vnd.stardivision.draw':
|
||||
@ -282,7 +284,7 @@ class General extends AbstractExtension
|
||||
$args = func_get_args();
|
||||
$route = $args[0]; // name of the route.
|
||||
|
||||
if (Route::getCurrentRoute()->getName() === $route) {
|
||||
if (\Route::getCurrentRoute()->getName() === $route) {
|
||||
return 'active';
|
||||
}
|
||||
|
||||
@ -302,7 +304,7 @@ class General extends AbstractExtension
|
||||
static function (): string {
|
||||
$args = func_get_args();
|
||||
$route = $args[0]; // name of the route.
|
||||
$name = Route::getCurrentRoute()->getName() ?? '';
|
||||
$name = \Route::getCurrentRoute()->getName() ?? '';
|
||||
if (str_contains($name, $route)) {
|
||||
return 'active';
|
||||
}
|
||||
@ -322,11 +324,11 @@ class General extends AbstractExtension
|
||||
'activeRoutePartialObjectType',
|
||||
static function ($context): string {
|
||||
[, $route, $objectType] = func_get_args();
|
||||
$activeObjectType = $context['objectType'] ?? false;
|
||||
$activeObjectType = $context['objectType'] ?? false;
|
||||
|
||||
if ($objectType === $activeObjectType
|
||||
&& false !== stripos(
|
||||
Route::getCurrentRoute()->getName(),
|
||||
\Route::getCurrentRoute()->getName(),
|
||||
$route
|
||||
)) {
|
||||
return 'active';
|
||||
@ -349,7 +351,7 @@ class General extends AbstractExtension
|
||||
static function (): string {
|
||||
$args = func_get_args();
|
||||
$route = $args[0]; // name of the route.
|
||||
$name = Route::getCurrentRoute()->getName() ?? '';
|
||||
$name = \Route::getCurrentRoute()->getName() ?? '';
|
||||
if (str_contains($name, $route)) {
|
||||
return 'menu-open';
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Twig;
|
||||
|
||||
use Config;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
@ -64,7 +63,7 @@ class Rule extends AbstractExtension
|
||||
$possibleTriggers = [];
|
||||
foreach ($ruleTriggers as $key) {
|
||||
if ('user_action' !== $key) {
|
||||
$possibleTriggers[$key] = (string) trans('firefly.rule_trigger_' . $key . '_choice');
|
||||
$possibleTriggers[$key] = (string) trans('firefly.rule_trigger_'.$key.'_choice');
|
||||
}
|
||||
}
|
||||
unset($ruleTriggers);
|
||||
@ -81,10 +80,10 @@ class Rule extends AbstractExtension
|
||||
'allRuleActions',
|
||||
static function () {
|
||||
// array of valid values for actions
|
||||
$ruleActions = array_keys(Config::get('firefly.rule-actions'));
|
||||
$ruleActions = array_keys(\Config::get('firefly.rule-actions'));
|
||||
$possibleActions = [];
|
||||
foreach ($ruleActions as $key) {
|
||||
$possibleActions[$key] = (string) trans('firefly.rule_action_' . $key . '_choice');
|
||||
$possibleActions[$key] = (string) trans('firefly.rule_action_'.$key.'_choice');
|
||||
}
|
||||
unset($ruleActions);
|
||||
asort($possibleActions);
|
||||
|
@ -25,7 +25,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support\Twig;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@ -87,7 +86,7 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
$colored = false;
|
||||
}
|
||||
|
||||
$result = app('amount')->formatFlat($array['currency_symbol'], (int) $array['currency_decimal_places'], $amount, $colored);
|
||||
$result = app('amount')->formatFlat($array['currency_symbol'], (int) $array['currency_decimal_places'], $amount, $colored);
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
||||
}
|
||||
@ -120,9 +119,9 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
*/
|
||||
private function foreignJournalArrayAmount(array $array): string
|
||||
{
|
||||
$type = $array['transaction_type_type'] ?? TransactionType::WITHDRAWAL;
|
||||
$amount = $array['foreign_amount'] ?? '0';
|
||||
$colored = true;
|
||||
$type = $array['transaction_type_type'] ?? TransactionType::WITHDRAWAL;
|
||||
$amount = $array['foreign_amount'] ?? '0';
|
||||
$colored = true;
|
||||
|
||||
$sourceType = $array['source_account_type'] ?? 'invalid';
|
||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||
@ -130,7 +129,7 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$colored = false;
|
||||
}
|
||||
$result = app('amount')->formatFlat($array['foreign_currency_symbol'], (int) $array['foreign_currency_decimal_places'], $amount, $colored);
|
||||
$result = app('amount')->formatFlat($array['foreign_currency_symbol'], (int) $array['foreign_currency_decimal_places'], $amount, $colored);
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
||||
}
|
||||
@ -171,12 +170,12 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
$colored = true;
|
||||
$sourceType = $first->account()->first()->accountType()->first()->type;
|
||||
|
||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$colored = false;
|
||||
}
|
||||
$result = app('amount')->formatFlat($currency->symbol, $currency->decimal_places, $amount, $colored);
|
||||
$result = app('amount')->formatFlat($currency->symbol, $currency->decimal_places, $amount, $colored);
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
||||
}
|
||||
@ -197,7 +196,7 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
*/
|
||||
private function foreignJournalObjectAmount(TransactionJournal $journal): string
|
||||
{
|
||||
$type = $journal->transactionType->type;
|
||||
$type = $journal->transactionType->type;
|
||||
|
||||
/** @var Transaction $first */
|
||||
$first = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
@ -206,12 +205,12 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
$colored = true;
|
||||
$sourceType = $first->account()->first()->accountType()->first()->type;
|
||||
|
||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$colored = false;
|
||||
}
|
||||
$result = app('amount')->formatFlat($currency->symbol, $currency->decimal_places, $amount, $colored);
|
||||
$result = app('amount')->formatFlat($currency->symbol, $currency->decimal_places, $amount, $colored);
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
||||
}
|
||||
@ -224,11 +223,12 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
return new TwigFunction(
|
||||
'journalHasMeta',
|
||||
static function (int $journalId, string $metaField) {
|
||||
$count = DB::table('journal_meta')
|
||||
->where('name', $metaField)
|
||||
->where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->count();
|
||||
$count = \DB::table('journal_meta')
|
||||
->where('name', $metaField)
|
||||
->where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->count()
|
||||
;
|
||||
|
||||
return 1 === $count;
|
||||
}
|
||||
@ -241,11 +241,12 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
'journalGetMetaDate',
|
||||
static function (int $journalId, string $metaField) {
|
||||
/** @var null|TransactionJournalMeta $entry */
|
||||
$entry = DB::table('journal_meta')
|
||||
->where('name', $metaField)
|
||||
->where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->first();
|
||||
$entry = \DB::table('journal_meta')
|
||||
->where('name', $metaField)
|
||||
->where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->first()
|
||||
;
|
||||
if (null === $entry) {
|
||||
return today(config('app.timezone'));
|
||||
}
|
||||
@ -261,11 +262,12 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
'journalGetMetaField',
|
||||
static function (int $journalId, string $metaField) {
|
||||
/** @var null|TransactionJournalMeta $entry */
|
||||
$entry = DB::table('journal_meta')
|
||||
->where('name', $metaField)
|
||||
->where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->first();
|
||||
$entry = \DB::table('journal_meta')
|
||||
->where('name', $metaField)
|
||||
->where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->first()
|
||||
;
|
||||
if (null === $entry) {
|
||||
return '';
|
||||
}
|
||||
|
@ -14,17 +14,14 @@
|
||||
"/public/v1/js/app.js.LICENSE.txt": "/public/v1/js/app.js.LICENSE.txt",
|
||||
"/public/v1/js/app_vue.js": "/public/v1/js/app_vue.js",
|
||||
"/public/v1/js/app_vue.js.LICENSE.txt": "/public/v1/js/app_vue.js.LICENSE.txt",
|
||||
"/public/v1/js/create.js": "/public/v1/js/create.js",
|
||||
"/public/v1/js/create.js.LICENSE.txt": "/public/v1/js/create.js.LICENSE.txt",
|
||||
"/public/v1/js/create_transaction.js": "/public/v1/js/create_transaction.js",
|
||||
"/public/v1/js/create_transaction.js.LICENSE.txt": "/public/v1/js/create_transaction.js.LICENSE.txt",
|
||||
"/public/v1/js/edit.js": "/public/v1/js/edit.js",
|
||||
"/public/v1/js/edit.js.LICENSE.txt": "/public/v1/js/edit.js.LICENSE.txt",
|
||||
"/public/v1/js/edit_transaction.js": "/public/v1/js/edit_transaction.js",
|
||||
"/public/v1/js/edit_transaction.js.LICENSE.txt": "/public/v1/js/edit_transaction.js.LICENSE.txt",
|
||||
"/public/v1/js/exchange-rates/index.js": "/public/v1/js/exchange-rates/index.js",
|
||||
"/public/v1/js/exchange-rates/index.js.LICENSE.txt": "/public/v1/js/exchange-rates/index.js.LICENSE.txt",
|
||||
"/public/v1/js/exchange-rates/rates.js": "/public/v1/js/exchange-rates/rates.js",
|
||||
"/public/v1/js/exchange-rates/rates.js.LICENSE.txt": "/public/v1/js/exchange-rates/rates.js.LICENSE.txt",
|
||||
"/public/v1/js/ff/accounts/create.js": "/public/v1/js/ff/accounts/create.js",
|
||||
"/public/v1/js/ff/accounts/edit-reconciliation.js": "/public/v1/js/ff/accounts/edit-reconciliation.js",
|
||||
"/public/v1/js/ff/accounts/edit.js": "/public/v1/js/ff/accounts/edit.js",
|
||||
@ -93,8 +90,6 @@
|
||||
"/public/v1/js/ff/transactions/mass/edit-bulk.js": "/public/v1/js/ff/transactions/mass/edit-bulk.js",
|
||||
"/public/v1/js/ff/transactions/mass/edit.js": "/public/v1/js/ff/transactions/mass/edit.js",
|
||||
"/public/v1/js/ff/transactions/show.js": "/public/v1/js/ff/transactions/show.js",
|
||||
"/public/v1/js/index.js": "/public/v1/js/index.js",
|
||||
"/public/v1/js/index.js.LICENSE.txt": "/public/v1/js/index.js.LICENSE.txt",
|
||||
"/public/v1/js/lib/Chart.bundle.min.js": "/public/v1/js/lib/Chart.bundle.min.js",
|
||||
"/public/v1/js/lib/accounting.min.js": "/public/v1/js/lib/accounting.min.js",
|
||||
"/public/v1/js/lib/bootstrap-multiselect.js": "/public/v1/js/lib/bootstrap-multiselect.js",
|
||||
@ -153,8 +148,6 @@
|
||||
"/public/v1/js/lib/vue.js": "/public/v1/js/lib/vue.js",
|
||||
"/public/v1/js/profile.js": "/public/v1/js/profile.js",
|
||||
"/public/v1/js/profile.js.LICENSE.txt": "/public/v1/js/profile.js.LICENSE.txt",
|
||||
"/public/v1/js/show.js": "/public/v1/js/show.js",
|
||||
"/public/v1/js/show.js.LICENSE.txt": "/public/v1/js/show.js.LICENSE.txt",
|
||||
"/public/v1/js/webhooks/create.js": "/public/v1/js/webhooks/create.js",
|
||||
"/public/v1/js/webhooks/create.js.LICENSE.txt": "/public/v1/js/webhooks/create.js.LICENSE.txt",
|
||||
"/public/v1/js/webhooks/edit.js": "/public/v1/js/webhooks/edit.js",
|
||||
|
@ -136,9 +136,9 @@
|
||||
"exchange_rates_intro_rates": "Firefly III bla bla bla exchange rates. Inverse is automatically calculated if not provided. Will go back to last found rate.",
|
||||
"header_exchange_rates_rates": "Wechselkurse",
|
||||
"header_exchange_rates_table": "Tabelle mit Wechselkursen",
|
||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
||||
"add_new_rate": "Add a new exchange rate",
|
||||
"save_new_rate": "Save new rate"
|
||||
"help_rate_form": "An diesem Tag, wie viele {to} werden Sie f\u00fcr einen {from} bekommen?",
|
||||
"add_new_rate": "Neuen Wechselkurs hinzuf\u00fcgen",
|
||||
"save_new_rate": "Neuen Kurs speichern"
|
||||
},
|
||||
"form": {
|
||||
"url": "URL",
|
||||
@ -158,7 +158,7 @@
|
||||
"webhook_delivery": "Zustellung",
|
||||
"from_currency_to_currency": "{from} → {to}",
|
||||
"to_currency_from_currency": "{to} → {from}",
|
||||
"rate": "Rate"
|
||||
"rate": "Kurs"
|
||||
},
|
||||
"list": {
|
||||
"active": "Aktiv?",
|
||||
|
@ -130,15 +130,15 @@
|
||||
"response": "Odpowied\u017a",
|
||||
"visit_webhook_url": "Odwied\u017a adres URL webhooka",
|
||||
"reset_webhook_secret": "Resetuj sekret webhooka",
|
||||
"header_exchange_rates": "Exchange rates",
|
||||
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/LOL_NOT_FINISHED_YET_TODO\">the documentation<\/a>.",
|
||||
"exchange_rates_from_to": "Between {from} and {to} (and the other way around)",
|
||||
"exchange_rates_intro_rates": "Firefly III bla bla bla exchange rates. Inverse is automatically calculated if not provided. Will go back to last found rate.",
|
||||
"header_exchange_rates_rates": "Exchange rates",
|
||||
"header_exchange_rates_table": "Table with exchange rates",
|
||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
||||
"add_new_rate": "Add a new exchange rate",
|
||||
"save_new_rate": "Save new rate"
|
||||
"header_exchange_rates": "Kursy wymiany",
|
||||
"exchange_rates_intro": "Firefly III obs\u0142uguje pobieranie i korzystanie z kurs\u00f3w wymiany walut. Wi\u0119cej informacji na ten temat w <a href=\"https:\/\/docs.firefly-iii.org\/LOL_NOT_FINISHED_YET_TODO\">dokumentacji<\/a>.",
|
||||
"exchange_rates_from_to": "Pomi\u0119dzy {from} i {to} (i odwrotnie)",
|
||||
"exchange_rates_intro_rates": "Firefly III bla bla bla kurs wymiany. Odwrotno\u015b\u0107 jest obliczana automatycznie, je\u015bli nie zosta\u0142a podana. Zostanie u\u017cyty ostatni znaleziony kurs.",
|
||||
"header_exchange_rates_rates": "Kursy wymiany",
|
||||
"header_exchange_rates_table": "Tabela z kursami wymiany walut",
|
||||
"help_rate_form": "W tym dniu, ile {to} otrzymasz za jeden {from}?",
|
||||
"add_new_rate": "Dodaj nowy kurs wymiany",
|
||||
"save_new_rate": "Zapisz nowy kurs"
|
||||
},
|
||||
"form": {
|
||||
"url": "URL",
|
||||
@ -158,7 +158,7 @@
|
||||
"webhook_delivery": "Dor\u0119czenie",
|
||||
"from_currency_to_currency": "{from} → {to}",
|
||||
"to_currency_from_currency": "{to} → {from}",
|
||||
"rate": "Rate"
|
||||
"rate": "Kurs"
|
||||
},
|
||||
"list": {
|
||||
"active": "Jest aktywny?",
|
||||
|
@ -1320,9 +1320,9 @@ return [
|
||||
'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
|
||||
'pref_locale_help' => 'Firefly III allows you to set other local settings, like how currencies, numbers and dates are formatted. Entries in this list may not be supported by your system. Firefly III doesn\'t have the correct date settings for every locale; contact me for improvements.',
|
||||
'pref_locale_no_demo' => 'This feature won\'t work for the demo user.',
|
||||
'pref_convert_to_native' => 'Display amounts in your native currency',
|
||||
'pref_convert_to_native_help' => 'This option will make Firefly III try to display and show your native currency in as many places as possible, converting amounts where necessary. This sacrifices accuracy for ease of use, because conversion is not always exact. Please verify that Firefly III has the necessary conversion rates on the "exchange rates"-page.',
|
||||
'pref_convert_native_help' => 'Display native amounts',
|
||||
'pref_convert_to_native' => 'Display amounts in your native currency',
|
||||
'pref_convert_to_native_help' => 'This option will make Firefly III try to display and show your native currency in as many places as possible, converting amounts where necessary. This sacrifices accuracy for ease of use, because conversion is not always exact. Please verify that Firefly III has the necessary conversion rates on the "exchange rates"-page.',
|
||||
'pref_convert_native_help' => 'Display native amounts',
|
||||
'pref_custom_fiscal_year' => 'Fiscal year settings',
|
||||
'pref_custom_fiscal_year_label' => 'Enabled',
|
||||
'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year',
|
||||
|
Loading…
Reference in New Issue
Block a user