mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-23 22:35:03 +00:00
Auto commit for release 'branch-v6.2' on 2024-12-22
This commit is contained in:
@@ -56,8 +56,8 @@ class AccountController extends Controller
|
|||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||||
$this->chartData = new ChartData();
|
$this->chartData = new ChartData();
|
||||||
$this->default = app('amount')->getDefaultCurrency();
|
$this->default = app('amount')->getDefaultCurrency();
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@@ -92,11 +92,11 @@ class AccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function renderAccountData(array $params, Account $account): void
|
private function renderAccountData(array $params, Account $account): void
|
||||||
{
|
{
|
||||||
$currency = $this->repository->getAccountCurrency($account);
|
$currency = $this->repository->getAccountCurrency($account);
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
$currency = $this->default;
|
$currency = $this->default;
|
||||||
}
|
}
|
||||||
$currentSet = [
|
$currentSet = [
|
||||||
'label' => $account->name,
|
'label' => $account->name,
|
||||||
|
|
||||||
// the currency that belongs to the account.
|
// the currency that belongs to the account.
|
||||||
@@ -117,18 +117,18 @@ class AccountController extends Controller
|
|||||||
'entries' => [],
|
'entries' => [],
|
||||||
'native_entries' => [],
|
'native_entries' => [],
|
||||||
];
|
];
|
||||||
$currentStart = clone $params['start'];
|
$currentStart = clone $params['start'];
|
||||||
$range = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $currency);
|
$range = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $currency);
|
||||||
|
|
||||||
$previous = array_values($range)[0]['balance'];
|
$previous = array_values($range)[0]['balance'];
|
||||||
$previousNative = array_values($range)[0]['native_balance'];
|
$previousNative = array_values($range)[0]['native_balance'];
|
||||||
while ($currentStart <= $params['end']) {
|
while ($currentStart <= $params['end']) {
|
||||||
$format = $currentStart->format('Y-m-d');
|
$format = $currentStart->format('Y-m-d');
|
||||||
$label = $currentStart->toAtomString();
|
$label = $currentStart->toAtomString();
|
||||||
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
|
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
|
||||||
$balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
|
$balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
|
||||||
$previous = $balance;
|
$previous = $balance;
|
||||||
$previousNative = $balanceNative;
|
$previousNative = $balanceNative;
|
||||||
|
|
||||||
$currentStart->addDay();
|
$currentStart->addDay();
|
||||||
$currentSet['entries'][$label] = $balance;
|
$currentSet['entries'][$label] = $balance;
|
||||||
|
@@ -29,11 +29,9 @@ use FireflyIII\Events\RequestedVersionCheckStatus;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Http\Middleware\Installer;
|
use FireflyIII\Http\Middleware\Installer;
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
@@ -103,7 +103,7 @@ class PreferencesController extends Controller
|
|||||||
$darkMode = app('preferences')->get('darkMode', 'browser')->data;
|
$darkMode = app('preferences')->get('darkMode', 'browser')->data;
|
||||||
$customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data;
|
$customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data;
|
||||||
$fiscalYearStartStr = app('preferences')->get('fiscalYearStart', '01-01')->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)) {
|
if (is_array($fiscalYearStartStr)) {
|
||||||
$fiscalYearStartStr = '01-01';
|
$fiscalYearStartStr = '01-01';
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ class PreferencesController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convert native
|
// convert native
|
||||||
$convertToNative = 1 === (int) $request->get('convertToNative');
|
$convertToNative = 1 === (int) $request->get('convertToNative');
|
||||||
app('preferences')->set('convert_to_native', $convertToNative);
|
app('preferences')->set('convert_to_native', $convertToNative);
|
||||||
|
|
||||||
// custom fiscal year
|
// custom fiscal year
|
||||||
|
@@ -28,7 +28,6 @@ use FireflyIII\Models\TransactionCurrency;
|
|||||||
use FireflyIII\Models\UserGroup;
|
use FireflyIII\Models\UserGroup;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use NumberFormatter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Amount.
|
* Class Amount.
|
||||||
@@ -56,15 +55,15 @@ class Amount
|
|||||||
*/
|
*/
|
||||||
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
|
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
|
||||||
{
|
{
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
$rounded = app('steam')->bcround($amount, $decimalPlaces);
|
$rounded = app('steam')->bcround($amount, $decimalPlaces);
|
||||||
$coloured ??= true;
|
$coloured ??= true;
|
||||||
|
|
||||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
||||||
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
$fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
||||||
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
$fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
||||||
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
$fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
||||||
$result = (string) $fmt->format((float) $rounded); // intentional float
|
$result = (string) $fmt->format((float) $rounded); // intentional float
|
||||||
|
|
||||||
if (true === $coloured) {
|
if (true === $coloured) {
|
||||||
if (1 === bccomp($rounded, '0')) {
|
if (1 === bccomp($rounded, '0')) {
|
||||||
@@ -110,7 +109,7 @@ class Amount
|
|||||||
|
|
||||||
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
||||||
{
|
{
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty('getDefaultCurrencyByGroup');
|
$cache->addProperty('getDefaultCurrencyByGroup');
|
||||||
$cache->addProperty($userGroup->id);
|
$cache->addProperty($userGroup->id);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
@@ -173,23 +172,23 @@ class Amount
|
|||||||
private function getLocaleInfo(): array
|
private function getLocaleInfo(): array
|
||||||
{
|
{
|
||||||
// get config from preference, not from translation:
|
// get config from preference, not from translation:
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
$array = app('steam')->getLocaleArray($locale);
|
$array = app('steam')->getLocaleArray($locale);
|
||||||
|
|
||||||
setlocale(LC_MONETARY, $array);
|
setlocale(LC_MONETARY, $array);
|
||||||
$info = localeconv();
|
$info = localeconv();
|
||||||
|
|
||||||
// correct variables
|
// correct variables
|
||||||
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
||||||
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_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['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
||||||
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_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_decimal_point'] = $fmt->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL);
|
||||||
$info['mon_thousands_sep'] = $fmt->getSymbol(NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
$info['mon_thousands_sep'] = $fmt->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
||||||
|
|
||||||
return $info;
|
return $info;
|
||||||
}
|
}
|
||||||
@@ -209,7 +208,7 @@ class Amount
|
|||||||
public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string
|
public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string
|
||||||
{
|
{
|
||||||
// negative first:
|
// negative first:
|
||||||
$space = ' ';
|
$space = ' ';
|
||||||
|
|
||||||
// require space between symbol and amount?
|
// require space between symbol and amount?
|
||||||
if (false === $sepBySpace) {
|
if (false === $sepBySpace) {
|
||||||
@@ -218,11 +217,11 @@ class Amount
|
|||||||
|
|
||||||
// there are five possible positions for the "+" or "-" sign (if it is even used)
|
// there are five possible positions for the "+" or "-" sign (if it is even used)
|
||||||
// pos_a and pos_e could be the ( and ) symbol.
|
// pos_a and pos_e could be the ( and ) symbol.
|
||||||
$posA = ''; // before everything
|
$posA = ''; // before everything
|
||||||
$posB = ''; // before currency symbol
|
$posB = ''; // before currency symbol
|
||||||
$posC = ''; // after currency symbol
|
$posC = ''; // after currency symbol
|
||||||
$posD = ''; // before amount
|
$posD = ''; // before amount
|
||||||
$posE = ''; // after everything
|
$posE = ''; // after everything
|
||||||
|
|
||||||
// format would be (currency before amount)
|
// format would be (currency before amount)
|
||||||
// AB%sC_D%vE
|
// AB%sC_D%vE
|
||||||
@@ -264,11 +263,11 @@ class Amount
|
|||||||
}
|
}
|
||||||
|
|
||||||
// default is amount before currency
|
// 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) {
|
if ($csPrecedes) {
|
||||||
// alternative is currency before amount
|
// 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;
|
return $format;
|
||||||
|
@@ -47,7 +47,7 @@ class RemoteUserGuard implements Guard
|
|||||||
public function __construct(UserProvider $provider, Application $app)
|
public function __construct(UserProvider $provider, Application $app)
|
||||||
{
|
{
|
||||||
/** @var null|Request $request */
|
/** @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()));
|
app('log')->debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
|
||||||
$this->application = $app;
|
$this->application = $app;
|
||||||
$this->provider = $provider;
|
$this->provider = $provider;
|
||||||
@@ -63,8 +63,8 @@ class RemoteUserGuard implements Guard
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Get the user identifier from $_SERVER or apache filtered headers
|
// Get the user identifier from $_SERVER or apache filtered headers
|
||||||
$header = config('auth.guard_header', 'REMOTE_USER');
|
$header = config('auth.guard_header', 'REMOTE_USER');
|
||||||
$userID = request()->server($header) ?? null;
|
$userID = request()->server($header) ?? null;
|
||||||
|
|
||||||
if (function_exists('apache_request_headers')) {
|
if (function_exists('apache_request_headers')) {
|
||||||
app('log')->debug('Use apache_request_headers to find user ID.');
|
app('log')->debug('Use apache_request_headers to find user ID.');
|
||||||
@@ -83,7 +83,7 @@ class RemoteUserGuard implements Guard
|
|||||||
$retrievedUser = $this->provider->retrieveById($userID);
|
$retrievedUser = $this->provider->retrieveById($userID);
|
||||||
|
|
||||||
// store email address if present in header and not already set.
|
// store email address if present in header and not already set.
|
||||||
$header = config('auth.guard_email');
|
$header = config('auth.guard_email');
|
||||||
|
|
||||||
if (null !== $header) {
|
if (null !== $header) {
|
||||||
$emailAddress = (string) (request()->server($header) ?? apache_request_headers()[$header] ?? null);
|
$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));
|
app('log')->debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email));
|
||||||
$this->user = $retrievedUser;
|
$this->user = $retrievedUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function guest(): bool
|
public function guest(): bool
|
||||||
@@ -139,14 +139,14 @@ class RemoteUserGuard implements Guard
|
|||||||
/**
|
/**
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
* @SuppressWarnings(PHPMD.ShortMethodName)
|
||||||
*/
|
*/
|
||||||
public function id(): null | int | string
|
public function id(): null|int|string
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||||
|
|
||||||
return $this->user?->id;
|
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__));
|
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||||
if ($user instanceof User) {
|
if ($user instanceof User) {
|
||||||
|
@@ -30,15 +30,13 @@ use FireflyIII\Models\Role;
|
|||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\Auth\Authenticatable;
|
use Illuminate\Contracts\Auth\Authenticatable;
|
||||||
use Illuminate\Contracts\Auth\UserProvider;
|
use Illuminate\Contracts\Auth\UserProvider;
|
||||||
use Override;
|
|
||||||
use Str;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RemoteUserProvider
|
* Class RemoteUserProvider
|
||||||
*/
|
*/
|
||||||
class RemoteUserProvider implements UserProvider
|
class RemoteUserProvider implements UserProvider
|
||||||
{
|
{
|
||||||
#[Override]
|
#[\Override]
|
||||||
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
|
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||||
@@ -74,7 +72,7 @@ class RemoteUserProvider implements UserProvider
|
|||||||
'blocked' => false,
|
'blocked' => false,
|
||||||
'blocked_code' => null,
|
'blocked_code' => null,
|
||||||
'email' => $identifier,
|
'email' => $identifier,
|
||||||
'password' => bcrypt(Str::random(64)),
|
'password' => bcrypt(\Str::random(64)),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
// if this is the first user, give them admin as well.
|
// if this is the first user, give them admin as well.
|
||||||
|
@@ -48,18 +48,19 @@ class Balance
|
|||||||
return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = Transaction::whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
|
$query = Transaction::whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
|
||||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
->orderBy('transaction_journals.date', 'desc')
|
->orderBy('transaction_journals.date', 'desc')
|
||||||
->orderBy('transaction_journals.order', 'asc')
|
->orderBy('transaction_journals.order', 'asc')
|
||||||
->orderBy('transaction_journals.description', 'desc')
|
->orderBy('transaction_journals.description', 'desc')
|
||||||
->orderBy('transactions.amount', 'desc')
|
->orderBy('transactions.amount', 'desc')
|
||||||
->where('transaction_journals.date', '<=', $date);
|
->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) {
|
foreach ($result as $entry) {
|
||||||
$accountId = (int) $entry->account_id;
|
$accountId = (int) $entry->account_id;
|
||||||
$currencyId = (int) $entry->transaction_currency_id;
|
$currencyId = (int) $entry->transaction_currency_id;
|
||||||
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
|
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
|
||||||
$return[$accountId] ??= [];
|
$return[$accountId] ??= [];
|
||||||
if (array_key_exists($currencyId, $return[$accountId])) {
|
if (array_key_exists($currencyId, $return[$accountId])) {
|
||||||
|
@@ -43,21 +43,23 @@ class AccountList implements BinderInterface
|
|||||||
if ('allAssetAccounts' === $value) {
|
if ('allAssetAccounts' === $value) {
|
||||||
/** @var Collection $collection */
|
/** @var Collection $collection */
|
||||||
$collection = auth()->user()->accounts()
|
$collection = auth()->user()->accounts()
|
||||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||||
->whereIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE])
|
->whereIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE])
|
||||||
->orderBy('accounts.name', 'ASC')
|
->orderBy('accounts.name', 'ASC')
|
||||||
->get(['accounts.*']);
|
->get(['accounts.*'])
|
||||||
|
;
|
||||||
}
|
}
|
||||||
if ('allAssetAccounts' !== $value) {
|
if ('allAssetAccounts' !== $value) {
|
||||||
$incoming = array_map('\intval', explode(',', $value));
|
$incoming = array_map('\intval', explode(',', $value));
|
||||||
$list = array_merge(array_unique($incoming), [0]);
|
$list = array_merge(array_unique($incoming), [0]);
|
||||||
|
|
||||||
/** @var Collection $collection */
|
/** @var Collection $collection */
|
||||||
$collection = auth()->user()->accounts()
|
$collection = auth()->user()->accounts()
|
||||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||||
->whereIn('accounts.id', $list)
|
->whereIn('accounts.id', $list)
|
||||||
->orderBy('accounts.name', 'ASC')
|
->orderBy('accounts.name', 'ASC')
|
||||||
->get(['accounts.*']);
|
->get(['accounts.*'])
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($collection->count() > 0) {
|
if ($collection->count() > 0) {
|
||||||
|
@@ -41,12 +41,13 @@ class BudgetList implements BinderInterface
|
|||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ('allBudgets' === $value) {
|
if ('allBudgets' === $value) {
|
||||||
return auth()->user()->budgets()->where('active', true)
|
return auth()->user()->budgets()->where('active', true)
|
||||||
->orderBy('order', 'ASC')
|
->orderBy('order', 'ASC')
|
||||||
->orderBy('name', 'ASC')
|
->orderBy('name', 'ASC')
|
||||||
->get();
|
->get()
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||||
|
|
||||||
if (0 === count($list)) { // @phpstan-ignore-line
|
if (0 === count($list)) { // @phpstan-ignore-line
|
||||||
app('log')->warning('Budget list count is zero, return 404.');
|
app('log')->warning('Budget list count is zero, return 404.');
|
||||||
@@ -56,9 +57,10 @@ class BudgetList implements BinderInterface
|
|||||||
|
|
||||||
/** @var Collection $collection */
|
/** @var Collection $collection */
|
||||||
$collection = auth()->user()->budgets()
|
$collection = auth()->user()->budgets()
|
||||||
->where('active', true)
|
->where('active', true)
|
||||||
->whereIn('id', $list)
|
->whereIn('id', $list)
|
||||||
->get();
|
->get()
|
||||||
|
;
|
||||||
|
|
||||||
// add empty budget if applicable.
|
// add empty budget if applicable.
|
||||||
if (in_array(0, $list, true)) {
|
if (in_array(0, $list, true)) {
|
||||||
|
@@ -41,19 +41,21 @@ class CategoryList implements BinderInterface
|
|||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ('allCategories' === $value) {
|
if ('allCategories' === $value) {
|
||||||
return auth()->user()->categories()
|
return auth()->user()->categories()
|
||||||
->orderBy('name', 'ASC')
|
->orderBy('name', 'ASC')
|
||||||
->get();
|
->get()
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
$list = array_unique(array_map('\intval', explode(',', $value)));
|
$list = array_unique(array_map('\intval', explode(',', $value)));
|
||||||
if (0 === count($list)) { // @phpstan-ignore-line
|
if (0 === count($list)) { // @phpstan-ignore-line
|
||||||
throw new NotFoundHttpException();
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Collection $collection */
|
/** @var Collection $collection */
|
||||||
$collection = auth()->user()->categories()
|
$collection = auth()->user()->categories()
|
||||||
->whereIn('id', $list)
|
->whereIn('id', $list)
|
||||||
->get();
|
->get()
|
||||||
|
;
|
||||||
|
|
||||||
// add empty category if applicable.
|
// add empty category if applicable.
|
||||||
if (in_array(0, $list, true)) {
|
if (in_array(0, $list, true)) {
|
||||||
|
@@ -43,16 +43,16 @@ class Date implements BinderInterface
|
|||||||
/** @var FiscalHelperInterface $fiscalHelper */
|
/** @var FiscalHelperInterface $fiscalHelper */
|
||||||
$fiscalHelper = app(FiscalHelperInterface::class);
|
$fiscalHelper = app(FiscalHelperInterface::class);
|
||||||
|
|
||||||
$magicWords = [
|
$magicWords = [
|
||||||
'currentMonthStart' => today(config('app.timezone'))->startOfMonth(),
|
'currentMonthStart' => today(config('app.timezone'))->startOfMonth(),
|
||||||
'currentMonthEnd' => today(config('app.timezone'))->endOfMonth(),
|
'currentMonthEnd' => today(config('app.timezone'))->endOfMonth(),
|
||||||
'currentYearStart' => today(config('app.timezone'))->startOfYear(),
|
'currentYearStart' => today(config('app.timezone'))->startOfYear(),
|
||||||
'currentYearEnd' => today(config('app.timezone'))->endOfYear(),
|
'currentYearEnd' => today(config('app.timezone'))->endOfYear(),
|
||||||
|
|
||||||
'previousMonthStart' => today(config('app.timezone'))->startOfMonth()->subDay()->startOfMonth(),
|
'previousMonthStart' => today(config('app.timezone'))->startOfMonth()->subDay()->startOfMonth(),
|
||||||
'previousMonthEnd' => today(config('app.timezone'))->startOfMonth()->subDay()->endOfMonth(),
|
'previousMonthEnd' => today(config('app.timezone'))->startOfMonth()->subDay()->endOfMonth(),
|
||||||
'previousYearStart' => today(config('app.timezone'))->startOfYear()->subDay()->startOfYear(),
|
'previousYearStart' => today(config('app.timezone'))->startOfYear()->subDay()->startOfYear(),
|
||||||
'previousYearEnd' => today(config('app.timezone'))->startOfYear()->subDay()->endOfYear(),
|
'previousYearEnd' => today(config('app.timezone'))->startOfYear()->subDay()->endOfYear(),
|
||||||
|
|
||||||
'currentFiscalYearStart' => $fiscalHelper->startOfFiscalYear(today(config('app.timezone'))),
|
'currentFiscalYearStart' => $fiscalHelper->startOfFiscalYear(today(config('app.timezone'))),
|
||||||
'currentFiscalYearEnd' => $fiscalHelper->endOfFiscalYear(today(config('app.timezone'))),
|
'currentFiscalYearEnd' => $fiscalHelper->endOfFiscalYear(today(config('app.timezone'))),
|
||||||
@@ -68,7 +68,7 @@ class Date implements BinderInterface
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$result = new Carbon($value);
|
$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());
|
$message = sprintf('Could not parse date "%s" for user #%d: %s', $value, auth()->user()->id, $e->getMessage());
|
||||||
app('log')->error($message);
|
app('log')->error($message);
|
||||||
|
|
||||||
|
@@ -39,7 +39,7 @@ class JournalList implements BinderInterface
|
|||||||
public static function routeBinder(string $value, Route $route): array
|
public static function routeBinder(string $value, Route $route): array
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$list = self::parseList($value);
|
$list = self::parseList($value);
|
||||||
|
|
||||||
// get the journals by using the collector.
|
// get the journals by using the collector.
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
@@ -47,7 +47,7 @@ class JournalList implements BinderInterface
|
|||||||
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::RECONCILIATION]);
|
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::RECONCILIATION]);
|
||||||
$collector->withCategoryInformation()->withBudgetInformation()->withTagInformation()->withAccountInformation();
|
$collector->withCategoryInformation()->withBudgetInformation()->withTagInformation()->withAccountInformation();
|
||||||
$collector->setJournalIds($list);
|
$collector->setJournalIds($list);
|
||||||
$result = $collector->getExtractedJournals();
|
$result = $collector->getExtractedJournals();
|
||||||
if (0 === count($result)) {
|
if (0 === count($result)) {
|
||||||
throw new NotFoundHttpException();
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
|
@@ -43,10 +43,11 @@ class TagList implements BinderInterface
|
|||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
if ('allTags' === $value) {
|
if ('allTags' === $value) {
|
||||||
return auth()->user()->tags()
|
return auth()->user()->tags()
|
||||||
->orderBy('tag', 'ASC')
|
->orderBy('tag', 'ASC')
|
||||||
->get();
|
->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);
|
app('log')->debug('List of tags is', $list);
|
||||||
|
|
||||||
if (0 === count($list)) { // @phpstan-ignore-line
|
if (0 === count($list)) { // @phpstan-ignore-line
|
||||||
@@ -58,7 +59,7 @@ class TagList implements BinderInterface
|
|||||||
/** @var TagRepositoryInterface $repository */
|
/** @var TagRepositoryInterface $repository */
|
||||||
$repository = app(TagRepositoryInterface::class);
|
$repository = app(TagRepositoryInterface::class);
|
||||||
$repository->setUser(auth()->user());
|
$repository->setUser(auth()->user());
|
||||||
$allTags = $repository->get();
|
$allTags = $repository->get();
|
||||||
|
|
||||||
$collection = $allTags->filter(
|
$collection = $allTags->filter(
|
||||||
static function (Tag $tag) use ($list) {
|
static function (Tag $tag) use ($list) {
|
||||||
|
@@ -40,7 +40,7 @@ class TagOrId implements BinderInterface
|
|||||||
$repository = app(TagRepositoryInterface::class);
|
$repository = app(TagRepositoryInterface::class);
|
||||||
$repository->setUser(auth()->user());
|
$repository->setUser(auth()->user());
|
||||||
|
|
||||||
$result = $repository->findByTag($value);
|
$result = $repository->findByTag($value);
|
||||||
if (null === $result) {
|
if (null === $result) {
|
||||||
$result = $repository->find((int) $value);
|
$result = $repository->find((int) $value);
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,9 @@ class UserGroupAccount implements BinderInterface
|
|||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$account = Account::where('id', (int) $value)
|
$account = Account::where('id', (int) $value)
|
||||||
->where('user_group_id', $user->user_group_id)
|
->where('user_group_id', $user->user_group_id)
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,9 @@ class UserGroupBill implements BinderInterface
|
|||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$currency = Bill::where('id', (int) $value)
|
$currency = Bill::where('id', (int) $value)
|
||||||
->where('user_group_id', $user->user_group_id)
|
->where('user_group_id', $user->user_group_id)
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
return $currency;
|
return $currency;
|
||||||
}
|
}
|
||||||
|
@@ -39,8 +39,9 @@ class UserGroupExchangeRate implements BinderInterface
|
|||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$rate = CurrencyExchangeRate::where('id', (int) $value)
|
$rate = CurrencyExchangeRate::where('id', (int) $value)
|
||||||
->where('user_group_id', $user->user_group_id)
|
->where('user_group_id', $user->user_group_id)
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
return $rate;
|
return $rate;
|
||||||
}
|
}
|
||||||
|
@@ -39,8 +39,9 @@ class UserGroupTransaction implements BinderInterface
|
|||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$group = TransactionGroup::where('id', (int) $value)
|
$group = TransactionGroup::where('id', (int) $value)
|
||||||
->where('user_group_id', $user->user_group_id)
|
->where('user_group_id', $user->user_group_id)
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
if (null !== $group) {
|
if (null !== $group) {
|
||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
@@ -23,9 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support;
|
namespace FireflyIII\Support;
|
||||||
|
|
||||||
use Cache;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use JsonException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CacheProperties.
|
* Class CacheProperties.
|
||||||
@@ -57,7 +55,7 @@ class CacheProperties
|
|||||||
*/
|
*/
|
||||||
public function get()
|
public function get()
|
||||||
{
|
{
|
||||||
return Cache::get($this->hash);
|
return \Cache::get($this->hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHash(): string
|
public function getHash(): string
|
||||||
@@ -72,16 +70,16 @@ class CacheProperties
|
|||||||
}
|
}
|
||||||
$this->hash();
|
$this->hash();
|
||||||
|
|
||||||
return Cache::has($this->hash);
|
return \Cache::has($this->hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function hash(): void
|
private function hash(): void
|
||||||
{
|
{
|
||||||
$content = '';
|
$content = '';
|
||||||
foreach ($this->properties as $property) {
|
foreach ($this->properties as $property) {
|
||||||
try {
|
try {
|
||||||
$content .= json_encode($property, JSON_THROW_ON_ERROR);
|
$content .= json_encode($property, JSON_THROW_ON_ERROR);
|
||||||
} catch (JsonException $e) {
|
} catch (\JsonException $e) {
|
||||||
// @ignoreException
|
// @ignoreException
|
||||||
$content .= hash('sha256', (string) time());
|
$content .= hash('sha256', (string) time());
|
||||||
}
|
}
|
||||||
@@ -94,6 +92,6 @@ class CacheProperties
|
|||||||
*/
|
*/
|
||||||
public function store($data): void
|
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 Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\IntervalException;
|
use FireflyIII\Exceptions\IntervalException;
|
||||||
use SplObjectStorage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Calculator
|
* Class Calculator
|
||||||
*/
|
*/
|
||||||
class Calculator
|
class Calculator
|
||||||
{
|
{
|
||||||
public const int DEFAULT_INTERVAL = 1;
|
public const int DEFAULT_INTERVAL = 1;
|
||||||
private static ?SplObjectStorage $intervalMap = null;
|
private static ?\SplObjectStorage $intervalMap = null;
|
||||||
private static array $intervals = [];
|
private static array $intervals = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws IntervalException
|
* @throws IntervalException
|
||||||
@@ -66,14 +65,14 @@ class Calculator
|
|||||||
/**
|
/**
|
||||||
* @SuppressWarnings(PHPMD.MissingImport)
|
* @SuppressWarnings(PHPMD.MissingImport)
|
||||||
*/
|
*/
|
||||||
private static function loadIntervalMap(): SplObjectStorage
|
private static function loadIntervalMap(): \SplObjectStorage
|
||||||
{
|
{
|
||||||
if (null !== self::$intervalMap) {
|
if (null !== self::$intervalMap) {
|
||||||
return self::$intervalMap;
|
return self::$intervalMap;
|
||||||
}
|
}
|
||||||
self::$intervalMap = new SplObjectStorage();
|
self::$intervalMap = new \SplObjectStorage();
|
||||||
foreach (Periodicity::cases() as $interval) {
|
foreach (Periodicity::cases() as $interval) {
|
||||||
$periodicityClass = __NAMESPACE__ . "\\Periodicity\\{$interval->name}";
|
$periodicityClass = __NAMESPACE__."\\Periodicity\\{$interval->name}";
|
||||||
self::$intervals[] = $interval->name;
|
self::$intervals[] = $interval->name;
|
||||||
self::$intervalMap->attach($interval, new $periodicityClass());
|
self::$intervalMap->attach($interval, new $periodicityClass());
|
||||||
}
|
}
|
||||||
|
@@ -155,7 +155,7 @@ class FrontpageChartGenerator
|
|||||||
*/
|
*/
|
||||||
private function processRow(array $data, Budget $budget, BudgetLimit $limit, array $entry): array
|
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())) {
|
if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) {
|
||||||
$title = sprintf(
|
$title = sprintf(
|
||||||
'%s (%s) (%s - %s)',
|
'%s (%s) (%s - %s)',
|
||||||
@@ -165,7 +165,7 @@ class FrontpageChartGenerator
|
|||||||
$limit->end_date->isoFormat($this->monthAndDayFormat)
|
$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[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
|
$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
|
public function generate(): array
|
||||||
{
|
{
|
||||||
$categories = $this->repository->getCategories();
|
$categories = $this->repository->getCategories();
|
||||||
$accounts = $this->accountRepos->getAccountsByType(
|
$accounts = $this->accountRepos->getAccountsByType(
|
||||||
[AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::ASSET, AccountType::DEFAULT]
|
[AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::ASSET, AccountType::DEFAULT]
|
||||||
);
|
);
|
||||||
|
|
||||||
// get expenses + income per category:
|
// get expenses + income per category:
|
||||||
$collection = [];
|
$collection = [];
|
||||||
|
|
||||||
/** @var Category $category */
|
/** @var Category $category */
|
||||||
foreach ($categories as $category) {
|
foreach ($categories as $category) {
|
||||||
@@ -82,10 +82,10 @@ class FrontpageChartGenerator
|
|||||||
// collect for no-category:
|
// collect for no-category:
|
||||||
$collection[] = $this->collectNoCatExpenses($accounts);
|
$collection[] = $this->collectNoCatExpenses($accounts);
|
||||||
|
|
||||||
$tempData = array_merge(...$collection);
|
$tempData = array_merge(...$collection);
|
||||||
|
|
||||||
// sort temp array by amount.
|
// sort temp array by amount.
|
||||||
$amounts = array_column($tempData, 'sum_float');
|
$amounts = array_column($tempData, 'sum_float');
|
||||||
array_multisort($amounts, SORT_ASC, $tempData);
|
array_multisort($amounts, SORT_ASC, $tempData);
|
||||||
|
|
||||||
$currencyData = $this->createCurrencyGroups($tempData);
|
$currencyData = $this->createCurrencyGroups($tempData);
|
||||||
|
@@ -38,22 +38,22 @@ class WholePeriodChartGenerator
|
|||||||
{
|
{
|
||||||
public function generate(Category $category, Carbon $start, Carbon $end): array
|
public function generate(Category $category, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$collection = new Collection([$category]);
|
$collection = new Collection([$category]);
|
||||||
|
|
||||||
/** @var OperationsRepositoryInterface $opsRepository */
|
/** @var OperationsRepositoryInterface $opsRepository */
|
||||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $accountRepository */
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
$accountRepository = app(AccountRepositoryInterface::class);
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
$types = [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
$types = [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
||||||
$accounts = $accountRepository->getAccountsByType($types);
|
$accounts = $accountRepository->getAccountsByType($types);
|
||||||
$step = $this->calculateStep($start, $end);
|
$step = $this->calculateStep($start, $end);
|
||||||
$chartData = [];
|
$chartData = [];
|
||||||
$spent = [];
|
$spent = [];
|
||||||
$earned = [];
|
$earned = [];
|
||||||
|
|
||||||
$current = clone $start;
|
$current = clone $start;
|
||||||
|
|
||||||
while ($current <= $end) {
|
while ($current <= $end) {
|
||||||
$key = $current->format('Y-m-d');
|
$key = $current->format('Y-m-d');
|
||||||
@@ -63,14 +63,14 @@ class WholePeriodChartGenerator
|
|||||||
$current = app('navigation')->addPeriod($current, $step, 0);
|
$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)
|
// generate chart data (for each currency)
|
||||||
/** @var array $currency */
|
/** @var array $currency */
|
||||||
foreach ($currencies as $currency) {
|
foreach ($currencies as $currency) {
|
||||||
$code = $currency['currency_code'];
|
$code = $currency['currency_code'];
|
||||||
$name = $currency['currency_name'];
|
$name = $currency['currency_name'];
|
||||||
$chartData[sprintf('spent-in-%s', $code)] = [
|
$chartData[sprintf('spent-in-%s', $code)] = [
|
||||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $name]),
|
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $name]),
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
'type' => 'bar',
|
'type' => 'bar',
|
||||||
@@ -85,11 +85,11 @@ class WholePeriodChartGenerator
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$current = clone $start;
|
$current = clone $start;
|
||||||
|
|
||||||
while ($current <= $end) {
|
while ($current <= $end) {
|
||||||
$key = $current->format('Y-m-d');
|
$key = $current->format('Y-m-d');
|
||||||
$label = app('navigation')->periodShow($current, $step);
|
$label = app('navigation')->periodShow($current, $step);
|
||||||
|
|
||||||
/** @var array $currency */
|
/** @var array $currency */
|
||||||
foreach ($currencies as $currency) {
|
foreach ($currencies as $currency) {
|
||||||
|
@@ -46,7 +46,7 @@ class ChartData
|
|||||||
if (array_key_exists('native_currency_id', $data)) {
|
if (array_key_exists('native_currency_id', $data)) {
|
||||||
$data['native_currency_id'] = (string) $data['native_currency_id'];
|
$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) {
|
foreach ($required as $field) {
|
||||||
if (!array_key_exists($field, $data)) {
|
if (!array_key_exists($field, $data)) {
|
||||||
throw new FireflyException(sprintf('Data-set is missing the "%s"-variable.', $field));
|
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
|
public static function getColour(int $index): string
|
||||||
{
|
{
|
||||||
$index %= count(self::$colours);
|
$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]);
|
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')));
|
app('log')->info(sprintf('Will now fire auto budget cron job task for date "%s".', $this->date->format('Y-m-d')));
|
||||||
|
|
||||||
/** @var CreateAutoBudgetLimits $job */
|
/** @var CreateAutoBudgetLimits $job */
|
||||||
$job = app(CreateAutoBudgetLimits::class, [$this->date]);
|
$job = app(CreateAutoBudgetLimits::class, [$this->date]);
|
||||||
$job->setDate($this->date);
|
$job->setDate($this->date);
|
||||||
$job->handle();
|
$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')));
|
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 */
|
/** @var WarnAboutBills $job */
|
||||||
$job = app(WarnAboutBills::class);
|
$job = app(WarnAboutBills::class);
|
||||||
$job->setDate($this->date);
|
$job->setDate($this->date);
|
||||||
$job->setForce($this->force);
|
$job->setForce($this->force);
|
||||||
$job->handle();
|
$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')));
|
app('log')->info(sprintf('Will now fire exchange rates cron job task for date "%s".', $this->date->format('Y-m-d')));
|
||||||
|
|
||||||
/** @var DownloadExchangeRates $job */
|
/** @var DownloadExchangeRates $job */
|
||||||
$job = app(DownloadExchangeRates::class);
|
$job = app(DownloadExchangeRates::class);
|
||||||
$job->setDate($this->date);
|
$job->setDate($this->date);
|
||||||
$job->handle();
|
$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')));
|
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->setForce($this->force);
|
||||||
$job->handle();
|
$job->handle();
|
||||||
|
|
||||||
|
@@ -27,7 +27,6 @@ use Eloquent;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Support\Form\FormSupport;
|
use FireflyIII\Support\Form\FormSupport;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ExpandedForm.
|
* Class ExpandedForm.
|
||||||
@@ -43,7 +42,7 @@ class ExpandedForm
|
|||||||
*/
|
*/
|
||||||
public function amountNoCurrency(string $name, $value = null, ?array $options = null): string
|
public function amountNoCurrency(string $name, $value = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
@@ -57,7 +56,7 @@ class ExpandedForm
|
|||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
$html = view('form.amount-no-currency', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->error(sprintf('Could not render amountNoCurrency(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render amountNoCurrency.';
|
$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
|
public function checkbox(string $name, ?int $value = null, $checked = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
$value ??= 1;
|
$value ??= 1;
|
||||||
$options['checked'] = true === $checked;
|
$options['checked'] = true === $checked;
|
||||||
|
|
||||||
if (app('session')->has('preFilled')) {
|
if (app('session')->has('preFilled')) {
|
||||||
@@ -83,16 +82,16 @@ class ExpandedForm
|
|||||||
$options['checked'] = $preFilled[$name] ?? $options['checked'];
|
$options['checked'] = $preFilled[$name] ?? $options['checked'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
$value = $this->fillFieldValue($name, $value);
|
$value = $this->fillFieldValue($name, $value);
|
||||||
|
|
||||||
unset($options['placeholder'], $options['autocomplete'], $options['class']);
|
unset($options['placeholder'], $options['autocomplete'], $options['class']);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.checkbox', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render checkbox(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render checkbox.';
|
$html = 'Could not render checkbox.';
|
||||||
|
|
||||||
@@ -117,7 +116,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render date(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render date.';
|
$html = 'Could not render date.';
|
||||||
|
|
||||||
@@ -139,7 +138,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.file', compact('classes', 'name', 'label', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render file(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render file.';
|
$html = 'Could not render file.';
|
||||||
|
|
||||||
@@ -157,15 +156,15 @@ class ExpandedForm
|
|||||||
public function integer(string $name, $value = null, ?array $options = null): string
|
public function integer(string $name, $value = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
$value = $this->fillFieldValue($name, $value);
|
$value = $this->fillFieldValue($name, $value);
|
||||||
$options['step'] ??= '1';
|
$options['step'] ??= '1';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render integer(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render integer.';
|
$html = 'Could not render integer.';
|
||||||
|
|
||||||
@@ -190,7 +189,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.location', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render location(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render location.';
|
$html = 'Could not render location.';
|
||||||
|
|
||||||
@@ -206,12 +205,12 @@ class ExpandedForm
|
|||||||
$selectList[0] = '(none)';
|
$selectList[0] = '(none)';
|
||||||
$fields = ['title', 'name', 'description'];
|
$fields = ['title', 'name', 'description'];
|
||||||
|
|
||||||
/** @var Eloquent $entry */
|
/** @var \Eloquent $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
// All Eloquent models have an ID
|
// All Eloquent models have an ID
|
||||||
$entryId = $entry->id; // @phpstan-ignore-line
|
$entryId = $entry->id; // @phpstan-ignore-line
|
||||||
$current = $entry->toArray();
|
$current = $entry->toArray();
|
||||||
$title = null;
|
$title = null;
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
if (array_key_exists($field, $current) && null === $title) {
|
if (array_key_exists($field, $current) && null === $title) {
|
||||||
$title = $current[$field];
|
$title = $current[$field];
|
||||||
@@ -243,7 +242,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.object_group', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render objectGroup(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render objectGroup.';
|
$html = 'Could not render objectGroup.';
|
||||||
|
|
||||||
@@ -260,7 +259,7 @@ class ExpandedForm
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$html = view('form.options', compact('type', 'name'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render select(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render optionsList.';
|
$html = 'Could not render optionsList.';
|
||||||
|
|
||||||
@@ -281,7 +280,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.password', compact('classes', 'name', 'label', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render password(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render password.';
|
$html = 'Could not render password.';
|
||||||
|
|
||||||
@@ -302,7 +301,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.password', compact('classes', 'value', 'name', 'label', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render passwordWithValue(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render passwordWithValue.';
|
$html = 'Could not render passwordWithValue.';
|
||||||
|
|
||||||
@@ -330,7 +329,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.percentage', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render percentage(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render percentage.';
|
$html = 'Could not render percentage.';
|
||||||
|
|
||||||
@@ -353,7 +352,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.static', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render staticText(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render staticText.';
|
$html = 'Could not render staticText.';
|
||||||
|
|
||||||
@@ -377,7 +376,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.text', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render text(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render text.';
|
$html = 'Could not render text.';
|
||||||
|
|
||||||
@@ -406,7 +405,7 @@ class ExpandedForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.textarea', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render textarea(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render textarea.';
|
$html = 'Could not render textarea.';
|
||||||
|
|
||||||
|
@@ -82,8 +82,8 @@ class ExportDataGenerator
|
|||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->accounts = new Collection();
|
$this->accounts = new Collection();
|
||||||
$this->start = today(config('app.timezone'));
|
$this->start = today(config('app.timezone'));
|
||||||
$this->start->subYear();
|
$this->start->subYear();
|
||||||
$this->end = today(config('app.timezone'));
|
$this->end = today(config('app.timezone'));
|
||||||
$this->exportTransactions = false;
|
$this->exportTransactions = false;
|
||||||
@@ -141,7 +141,7 @@ class ExportDataGenerator
|
|||||||
*/
|
*/
|
||||||
private function exportAccounts(): string
|
private function exportAccounts(): string
|
||||||
{
|
{
|
||||||
$header = [
|
$header = [
|
||||||
'user_id',
|
'user_id',
|
||||||
'account_id',
|
'account_id',
|
||||||
'created_at',
|
'created_at',
|
||||||
@@ -162,7 +162,7 @@ class ExportDataGenerator
|
|||||||
];
|
];
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$repository->setUser($this->user);
|
$repository->setUser($this->user);
|
||||||
$allAccounts = $repository->getAccountsByType([]);
|
$allAccounts = $repository->getAccountsByType([]);
|
||||||
$records = [];
|
$records = [];
|
||||||
@@ -192,7 +192,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -230,8 +230,8 @@ class ExportDataGenerator
|
|||||||
/** @var BillRepositoryInterface $repository */
|
/** @var BillRepositoryInterface $repository */
|
||||||
$repository = app(BillRepositoryInterface::class);
|
$repository = app(BillRepositoryInterface::class);
|
||||||
$repository->setUser($this->user);
|
$repository->setUser($this->user);
|
||||||
$bills = $repository->getBills();
|
$bills = $repository->getBills();
|
||||||
$header = [
|
$header = [
|
||||||
'user_id',
|
'user_id',
|
||||||
'bill_id',
|
'bill_id',
|
||||||
'created_at',
|
'created_at',
|
||||||
@@ -245,7 +245,7 @@ class ExportDataGenerator
|
|||||||
'skip',
|
'skip',
|
||||||
'active',
|
'active',
|
||||||
];
|
];
|
||||||
$records = [];
|
$records = [];
|
||||||
|
|
||||||
/** @var Bill $bill */
|
/** @var Bill $bill */
|
||||||
foreach ($bills as $bill) {
|
foreach ($bills as $bill) {
|
||||||
@@ -266,7 +266,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -296,7 +296,7 @@ class ExportDataGenerator
|
|||||||
*/
|
*/
|
||||||
private function exportBudgets(): string
|
private function exportBudgets(): string
|
||||||
{
|
{
|
||||||
$header = [
|
$header = [
|
||||||
'user_id',
|
'user_id',
|
||||||
'budget_id',
|
'budget_id',
|
||||||
'name',
|
'name',
|
||||||
@@ -310,9 +310,9 @@ class ExportDataGenerator
|
|||||||
|
|
||||||
$budgetRepos = app(BudgetRepositoryInterface::class);
|
$budgetRepos = app(BudgetRepositoryInterface::class);
|
||||||
$budgetRepos->setUser($this->user);
|
$budgetRepos->setUser($this->user);
|
||||||
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
||||||
$budgets = $budgetRepos->getBudgets();
|
$budgets = $budgetRepos->getBudgets();
|
||||||
$records = [];
|
$records = [];
|
||||||
|
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
@@ -335,7 +335,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -365,10 +365,10 @@ class ExportDataGenerator
|
|||||||
*/
|
*/
|
||||||
private function exportCategories(): string
|
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 */
|
/** @var CategoryRepositoryInterface $catRepos */
|
||||||
$catRepos = app(CategoryRepositoryInterface::class);
|
$catRepos = app(CategoryRepositoryInterface::class);
|
||||||
$catRepos->setUser($this->user);
|
$catRepos->setUser($this->user);
|
||||||
|
|
||||||
$records = [];
|
$records = [];
|
||||||
@@ -386,7 +386,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -417,14 +417,14 @@ class ExportDataGenerator
|
|||||||
private function exportPiggies(): string
|
private function exportPiggies(): string
|
||||||
{
|
{
|
||||||
/** @var PiggyBankRepositoryInterface $piggyRepos */
|
/** @var PiggyBankRepositoryInterface $piggyRepos */
|
||||||
$piggyRepos = app(PiggyBankRepositoryInterface::class);
|
$piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||||
$piggyRepos->setUser($this->user);
|
$piggyRepos->setUser($this->user);
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $accountRepos */
|
/** @var AccountRepositoryInterface $accountRepos */
|
||||||
$accountRepos = app(AccountRepositoryInterface::class);
|
$accountRepos = app(AccountRepositoryInterface::class);
|
||||||
$accountRepos->setUser($this->user);
|
$accountRepos->setUser($this->user);
|
||||||
|
|
||||||
$header = [
|
$header = [
|
||||||
'user_id',
|
'user_id',
|
||||||
'piggy_bank_id',
|
'piggy_bank_id',
|
||||||
'created_at',
|
'created_at',
|
||||||
@@ -440,8 +440,8 @@ class ExportDataGenerator
|
|||||||
'order',
|
'order',
|
||||||
'active',
|
'active',
|
||||||
];
|
];
|
||||||
$records = [];
|
$records = [];
|
||||||
$piggies = $piggyRepos->getPiggyBanks();
|
$piggies = $piggyRepos->getPiggyBanks();
|
||||||
|
|
||||||
/** @var PiggyBank $piggy */
|
/** @var PiggyBank $piggy */
|
||||||
foreach ($piggies as $piggy) {
|
foreach ($piggies as $piggy) {
|
||||||
@@ -466,7 +466,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -499,7 +499,7 @@ class ExportDataGenerator
|
|||||||
/** @var RecurringRepositoryInterface $recurringRepos */
|
/** @var RecurringRepositoryInterface $recurringRepos */
|
||||||
$recurringRepos = app(RecurringRepositoryInterface::class);
|
$recurringRepos = app(RecurringRepositoryInterface::class);
|
||||||
$recurringRepos->setUser($this->user);
|
$recurringRepos->setUser($this->user);
|
||||||
$header = [
|
$header = [
|
||||||
// recurrence:
|
// recurrence:
|
||||||
'user_id', 'recurrence_id', 'row_contains', 'created_at', 'updated_at', 'type', 'title', 'description', 'first_date', 'repeat_until', 'latest_date', 'repetitions', 'apply_rules', 'active',
|
'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:
|
// transactions + meta:
|
||||||
'currency_code', 'foreign_currency_code', 'source_name', 'source_type', 'destination_name', 'destination_type', 'amount', 'foreign_amount', 'category', 'budget', 'piggy_bank', 'tags',
|
'currency_code', 'foreign_currency_code', 'source_name', 'source_type', 'destination_name', 'destination_type', 'amount', 'foreign_amount', 'category', 'budget', 'piggy_bank', 'tags',
|
||||||
];
|
];
|
||||||
$records = [];
|
$records = [];
|
||||||
$recurrences = $recurringRepos->getAll();
|
$recurrences = $recurringRepos->getAll();
|
||||||
|
|
||||||
/** @var Recurrence $recurrence */
|
/** @var Recurrence $recurrence */
|
||||||
foreach ($recurrences as $recurrence) {
|
foreach ($recurrences as $recurrence) {
|
||||||
@@ -542,7 +542,7 @@ class ExportDataGenerator
|
|||||||
$piggyBankId = $recurringRepos->getPiggyBank($transaction);
|
$piggyBankId = $recurringRepos->getPiggyBank($transaction);
|
||||||
$tags = $recurringRepos->getTags($transaction);
|
$tags = $recurringRepos->getTags($transaction);
|
||||||
|
|
||||||
$records[] = [
|
$records[] = [
|
||||||
// recurrence
|
// recurrence
|
||||||
$this->user->id,
|
$this->user->id,
|
||||||
$recurrence->id,
|
$recurrence->id,
|
||||||
@@ -558,7 +558,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -595,8 +595,8 @@ class ExportDataGenerator
|
|||||||
'action_type', 'action_value', 'action_order', 'action_active', 'action_stop_processing'];
|
'action_type', 'action_value', 'action_order', 'action_active', 'action_stop_processing'];
|
||||||
$ruleRepos = app(RuleRepositoryInterface::class);
|
$ruleRepos = app(RuleRepositoryInterface::class);
|
||||||
$ruleRepos->setUser($this->user);
|
$ruleRepos->setUser($this->user);
|
||||||
$rules = $ruleRepos->getAll();
|
$rules = $ruleRepos->getAll();
|
||||||
$records = [];
|
$records = [];
|
||||||
|
|
||||||
/** @var Rule $rule */
|
/** @var Rule $rule */
|
||||||
foreach ($rules as $rule) {
|
foreach ($rules as $rule) {
|
||||||
@@ -635,7 +635,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -665,12 +665,12 @@ class ExportDataGenerator
|
|||||||
*/
|
*/
|
||||||
private function exportTags(): string
|
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 = app(TagRepositoryInterface::class);
|
||||||
$tagRepos->setUser($this->user);
|
$tagRepos->setUser($this->user);
|
||||||
$tags = $tagRepos->get();
|
$tags = $tagRepos->get();
|
||||||
$records = [];
|
$records = [];
|
||||||
|
|
||||||
/** @var Tag $tag */
|
/** @var Tag $tag */
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
@@ -689,7 +689,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
@@ -728,26 +728,27 @@ class ExportDataGenerator
|
|||||||
private function exportTransactions(): string
|
private function exportTransactions(): string
|
||||||
{
|
{
|
||||||
// TODO better place for keys?
|
// 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');
|
$metaFields = config('firefly.journal_meta_fields');
|
||||||
$header = array_merge($header, $metaFields);
|
$header = array_merge($header, $metaFields);
|
||||||
|
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setUser($this->user);
|
$collector->setUser($this->user);
|
||||||
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
|
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
|
||||||
->withBudgetInformation()->withTagInformation()->withNotes();
|
->withBudgetInformation()->withTagInformation()->withNotes()
|
||||||
|
;
|
||||||
if (0 !== $this->accounts->count()) {
|
if (0 !== $this->accounts->count()) {
|
||||||
$collector->setAccounts($this->accounts);
|
$collector->setAccounts($this->accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// get repository for meta data:
|
// get repository for meta data:
|
||||||
$repository = app(TransactionGroupRepositoryInterface::class);
|
$repository = app(TransactionGroupRepositoryInterface::class);
|
||||||
$repository->setUser($this->user);
|
$repository->setUser($this->user);
|
||||||
|
|
||||||
$records = [];
|
$records = [];
|
||||||
|
|
||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
@@ -772,7 +773,7 @@ class ExportDataGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the CSV document from a string
|
// load the CSV document from a string
|
||||||
$csv = Writer::createFromString();
|
$csv = Writer::createFromString();
|
||||||
|
|
||||||
// insert the header
|
// insert the header
|
||||||
try {
|
try {
|
||||||
|
@@ -23,8 +23,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support;
|
namespace FireflyIII\Support;
|
||||||
|
|
||||||
use Cache;
|
|
||||||
use Exception;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Configuration;
|
use FireflyIII\Models\Configuration;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
@@ -39,9 +37,9 @@ class FireflyConfig
|
|||||||
{
|
{
|
||||||
public function delete(string $name): void
|
public function delete(string $name): void
|
||||||
{
|
{
|
||||||
$fullName = 'ff-config-' . $name;
|
$fullName = 'ff-config-'.$name;
|
||||||
if (Cache::has($fullName)) {
|
if (\Cache::has($fullName)) {
|
||||||
Cache::forget($fullName);
|
\Cache::forget($fullName);
|
||||||
}
|
}
|
||||||
Configuration::where('name', $name)->forceDelete();
|
Configuration::where('name', $name)->forceDelete();
|
||||||
}
|
}
|
||||||
@@ -81,20 +79,20 @@ class FireflyConfig
|
|||||||
*/
|
*/
|
||||||
public function get(string $name, $default = null): ?Configuration
|
public function get(string $name, $default = null): ?Configuration
|
||||||
{
|
{
|
||||||
$fullName = 'ff-config-' . $name;
|
$fullName = 'ff-config-'.$name;
|
||||||
if (Cache::has($fullName)) {
|
if (\Cache::has($fullName)) {
|
||||||
return Cache::get($fullName);
|
return \Cache::get($fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/** @var null|Configuration $config */
|
/** @var null|Configuration $config */
|
||||||
$config = Configuration::where('name', $name)->first(['id', 'name', 'data']);
|
$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);
|
throw new FireflyException(sprintf('Could not poll the database: %s', $e->getMessage()), 0, $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $config) {
|
if (null !== $config) {
|
||||||
Cache::forever($fullName, $config);
|
\Cache::forever($fullName, $config);
|
||||||
|
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
@@ -124,13 +122,13 @@ class FireflyConfig
|
|||||||
$item->name = $name;
|
$item->name = $name;
|
||||||
$item->data = $value;
|
$item->data = $value;
|
||||||
$item->save();
|
$item->save();
|
||||||
Cache::forget('ff-config-' . $name);
|
\Cache::forget('ff-config-'.$name);
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
$config->data = $value;
|
$config->data = $value;
|
||||||
$config->save();
|
$config->save();
|
||||||
Cache::forget('ff-config-' . $name);
|
\Cache::forget('ff-config-'.$name);
|
||||||
|
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,6 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AccountForm
|
* Class AccountForm
|
||||||
@@ -69,7 +68,7 @@ class AccountForm
|
|||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accountList as $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)) {
|
if (in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||||
$role = sprintf('l_%s', $account->accountType->type);
|
$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
|
public function activeWithdrawalDestinations(string $name, mixed $value = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$types = [AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN, AccountType::EXPENSE];
|
$types = [AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN, AccountType::EXPENSE];
|
||||||
$repository = $this->getAccountRepository();
|
$repository = $this->getAccountRepository();
|
||||||
$grouped = $this->getAccountsGrouped($types, $repository);
|
$grouped = $this->getAccountsGrouped($types, $repository);
|
||||||
|
|
||||||
$cash = $repository->getCashAccount();
|
$cash = $repository->getCashAccount();
|
||||||
$key = (string) trans('firefly.cash_account_type');
|
$key = (string) trans('firefly.cash_account_type');
|
||||||
@@ -112,21 +111,21 @@ class AccountForm
|
|||||||
*/
|
*/
|
||||||
public function assetAccountCheckList(string $name, ?array $options = null): string
|
public function assetAccountCheckList(string $name, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
$selected = request()->old($name) ?? [];
|
$selected = request()->old($name) ?? [];
|
||||||
|
|
||||||
// get all asset accounts:
|
// get all asset accounts:
|
||||||
$types = [AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT];
|
$types = [AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT];
|
||||||
$grouped = $this->getAccountsGrouped($types);
|
$grouped = $this->getAccountsGrouped($types);
|
||||||
|
|
||||||
unset($options['class']);
|
unset($options['class']);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.assetAccountCheckList', compact('classes', 'selected', 'name', 'label', 'options', 'grouped'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render assetAccountCheckList(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render assetAccountCheckList.';
|
$html = 'Could not render assetAccountCheckList.';
|
||||||
|
|
||||||
|
@@ -28,7 +28,6 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CurrencyForm
|
* Class CurrencyForm
|
||||||
@@ -62,15 +61,15 @@ class CurrencyForm
|
|||||||
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
|
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
|
||||||
|
|
||||||
/** @var Collection $currencies */
|
/** @var Collection $currencies */
|
||||||
$currencies = app('amount')->getCurrencies();
|
$currencies = app('amount')->getCurrencies();
|
||||||
unset($options['currency'], $options['placeholder']);
|
unset($options['currency'], $options['placeholder']);
|
||||||
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
|
// 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)) {
|
if (!is_array($preFilled)) {
|
||||||
$preFilled = [];
|
$preFilled = [];
|
||||||
}
|
}
|
||||||
$key = 'amount_currency_id_' . $name;
|
$key = 'amount_currency_id_'.$name;
|
||||||
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
||||||
|
|
||||||
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
||||||
|
|
||||||
@@ -90,8 +89,8 @@ class CurrencyForm
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
$html = view('form.'.$view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render currencyField.';
|
$html = 'Could not render currencyField.';
|
||||||
|
|
||||||
@@ -130,16 +129,16 @@ class CurrencyForm
|
|||||||
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
|
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
|
||||||
|
|
||||||
/** @var Collection $currencies */
|
/** @var Collection $currencies */
|
||||||
$currencies = app('amount')->getAllCurrencies();
|
$currencies = app('amount')->getAllCurrencies();
|
||||||
unset($options['currency'], $options['placeholder']);
|
unset($options['currency'], $options['placeholder']);
|
||||||
|
|
||||||
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
|
// 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)) {
|
if (!is_array($preFilled)) {
|
||||||
$preFilled = [];
|
$preFilled = [];
|
||||||
}
|
}
|
||||||
$key = 'amount_currency_id_' . $name;
|
$key = 'amount_currency_id_'.$name;
|
||||||
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id;
|
||||||
|
|
||||||
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
|
||||||
|
|
||||||
@@ -159,8 +158,8 @@ class CurrencyForm
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
$html = view('form.'.$view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render currencyField.';
|
$html = 'Could not render currencyField.';
|
||||||
|
|
||||||
@@ -181,12 +180,12 @@ class CurrencyForm
|
|||||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||||
|
|
||||||
// get all currencies:
|
// get all currencies:
|
||||||
$list = $currencyRepos->get();
|
$list = $currencyRepos->get();
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
/** @var TransactionCurrency $currency */
|
/** @var TransactionCurrency $currency */
|
||||||
foreach ($list as $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);
|
return $this->select($name, $array, $value, $options);
|
||||||
@@ -203,14 +202,14 @@ class CurrencyForm
|
|||||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||||
|
|
||||||
// get all currencies:
|
// get all currencies:
|
||||||
$list = $currencyRepos->get();
|
$list = $currencyRepos->get();
|
||||||
$array = [
|
$array = [
|
||||||
0 => (string) trans('firefly.no_currency'),
|
0 => (string) trans('firefly.no_currency'),
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var TransactionCurrency $currency */
|
/** @var TransactionCurrency $currency */
|
||||||
foreach ($list as $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);
|
return $this->select($name, $array, $value, $options);
|
||||||
|
@@ -28,7 +28,6 @@ use Carbon\Carbon;
|
|||||||
use Carbon\Exceptions\InvalidDateException;
|
use Carbon\Exceptions\InvalidDateException;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use Illuminate\Support\MessageBag;
|
use Illuminate\Support\MessageBag;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait FormSupport
|
* Trait FormSupport
|
||||||
@@ -37,7 +36,7 @@ trait FormSupport
|
|||||||
{
|
{
|
||||||
public function multiSelect(string $name, ?array $list = null, $selected = null, ?array $options = null): string
|
public function multiSelect(string $name, ?array $list = null, $selected = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$list ??= [];
|
$list ??= [];
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
@@ -47,7 +46,7 @@ trait FormSupport
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.multi-select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render multi-select(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render multi-select.';
|
$html = 'Could not render multi-select.';
|
||||||
}
|
}
|
||||||
@@ -63,7 +62,7 @@ trait FormSupport
|
|||||||
}
|
}
|
||||||
$name = str_replace('[]', '', $name);
|
$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
|
protected function expandOptionArray(string $name, $label, ?array $options = null): array
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
$name = str_replace('[]', '', $name);
|
$name = str_replace('[]', '', $name);
|
||||||
$options['class'] = 'form-control';
|
$options['class'] = 'form-control';
|
||||||
$options['id'] = 'ffInput_' . $name;
|
$options['id'] = 'ffInput_'.$name;
|
||||||
$options['autocomplete'] = 'off';
|
$options['autocomplete'] = 'off';
|
||||||
$options['placeholder'] = ucfirst($label);
|
$options['placeholder'] = ucfirst($label);
|
||||||
|
|
||||||
@@ -123,7 +122,7 @@ trait FormSupport
|
|||||||
*/
|
*/
|
||||||
public function select(string $name, ?array $list = null, $selected = null, ?array $options = null): string
|
public function select(string $name, ?array $list = null, $selected = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$list ??= [];
|
$list ??= [];
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
@@ -132,7 +131,7 @@ trait FormSupport
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$html = view('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
$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()));
|
app('log')->debug(sprintf('Could not render select(): %s', $e->getMessage()));
|
||||||
$html = 'Could not render select.';
|
$html = 'Could not render select.';
|
||||||
}
|
}
|
||||||
|
@@ -62,14 +62,14 @@ class PiggyBankForm
|
|||||||
|
|
||||||
/** @var PiggyBank $piggy */
|
/** @var PiggyBank $piggy */
|
||||||
foreach ($piggyBanks as $piggy) {
|
foreach ($piggyBanks as $piggy) {
|
||||||
$group = $piggy->objectGroups->first();
|
$group = $piggy->objectGroups->first();
|
||||||
$groupTitle = null;
|
$groupTitle = null;
|
||||||
$groupOrder = 0;
|
$groupOrder = 0;
|
||||||
if (null !== $group) {
|
if (null !== $group) {
|
||||||
$groupTitle = $group->title;
|
$groupTitle = $group->title;
|
||||||
$groupOrder = $group->order;
|
$groupOrder = $group->order;
|
||||||
}
|
}
|
||||||
$subList[$groupOrder] ??= [
|
$subList[$groupOrder] ??= [
|
||||||
'group' => [
|
'group' => [
|
||||||
'title' => $groupTitle,
|
'title' => $groupTitle,
|
||||||
],
|
],
|
||||||
|
@@ -41,8 +41,8 @@ class RuleForm
|
|||||||
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
||||||
|
|
||||||
// get all currencies:
|
// get all currencies:
|
||||||
$list = $groupRepos->get();
|
$list = $groupRepos->get();
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
/** @var RuleGroup $group */
|
/** @var RuleGroup $group */
|
||||||
foreach ($list as $group) {
|
foreach ($list as $group) {
|
||||||
@@ -57,15 +57,15 @@ class RuleForm
|
|||||||
*/
|
*/
|
||||||
public function ruleGroupListWithEmpty(string $name, $value = null, ?array $options = null): string
|
public function ruleGroupListWithEmpty(string $name, $value = null, ?array $options = null): string
|
||||||
{
|
{
|
||||||
$options ??= [];
|
$options ??= [];
|
||||||
$options['class'] = 'form-control';
|
$options['class'] = 'form-control';
|
||||||
|
|
||||||
/** @var RuleGroupRepositoryInterface $groupRepos */
|
/** @var RuleGroupRepositoryInterface $groupRepos */
|
||||||
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
$groupRepos = app(RuleGroupRepositoryInterface::class);
|
||||||
|
|
||||||
// get all currencies:
|
// get all currencies:
|
||||||
$list = $groupRepos->get();
|
$list = $groupRepos->get();
|
||||||
$array = [
|
$array = [
|
||||||
0 => (string) trans('firefly.none_in_select_list'),
|
0 => (string) trans('firefly.none_in_select_list'),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ class AccountBalanceGrouped
|
|||||||
/** @var array $currency */
|
/** @var array $currency */
|
||||||
foreach ($this->data as $currency) {
|
foreach ($this->data as $currency) {
|
||||||
// income and expense array prepped:
|
// income and expense array prepped:
|
||||||
$income = [
|
$income = [
|
||||||
'label' => 'earned',
|
'label' => 'earned',
|
||||||
'currency_id' => (string) $currency['currency_id'],
|
'currency_id' => (string) $currency['currency_id'],
|
||||||
'currency_symbol' => $currency['currency_symbol'],
|
'currency_symbol' => $currency['currency_symbol'],
|
||||||
@@ -81,7 +81,7 @@ class AccountBalanceGrouped
|
|||||||
'entries' => [],
|
'entries' => [],
|
||||||
'native_entries' => [],
|
'native_entries' => [],
|
||||||
];
|
];
|
||||||
$expense = [
|
$expense = [
|
||||||
'label' => 'spent',
|
'label' => 'spent',
|
||||||
'currency_id' => (string) $currency['currency_id'],
|
'currency_id' => (string) $currency['currency_id'],
|
||||||
'currency_symbol' => $currency['currency_symbol'],
|
'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.
|
// loop all possible periods between $start and $end, and add them to the correct dataset.
|
||||||
$currentStart = clone $this->start;
|
$currentStart = clone $this->start;
|
||||||
while ($currentStart <= $this->end) {
|
while ($currentStart <= $this->end) {
|
||||||
$key = $currentStart->format($this->carbonFormat);
|
$key = $currentStart->format($this->carbonFormat);
|
||||||
$label = $currentStart->toAtomString();
|
$label = $currentStart->toAtomString();
|
||||||
// normal entries
|
// normal entries
|
||||||
$income['entries'][$label] = app('steam')->bcround($currency[$key]['earned'] ?? '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']);
|
$expense['entries'][$label] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
|
||||||
|
|
||||||
// converted entries
|
// converted entries
|
||||||
$income['native_entries'][$label] = app('steam')->bcround($currency[$key]['native_earned'] ?? '0', $currency['native_currency_decimal_places']);
|
$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']);
|
$expense['native_entries'][$label] = app('steam')->bcround($currency[$key]['native_spent'] ?? '0', $currency['native_currency_decimal_places']);
|
||||||
|
|
||||||
// next loop
|
// next loop
|
||||||
$currentStart = app('navigation')->addPeriod($currentStart, $this->preferredRange, 0);
|
$currentStart = app('navigation')->addPeriod($currentStart, $this->preferredRange, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
$chartData[] = $income;
|
$chartData[] = $income;
|
||||||
$chartData[] = $expense;
|
$chartData[] = $expense;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $chartData;
|
return $chartData;
|
||||||
@@ -142,9 +142,9 @@ class AccountBalanceGrouped
|
|||||||
private function processJournal(array $journal): void
|
private function processJournal(array $journal): void
|
||||||
{
|
{
|
||||||
// format the date according to the period
|
// format the date according to the period
|
||||||
$period = $journal['date']->format($this->carbonFormat);
|
$period = $journal['date']->format($this->carbonFormat);
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$currency = $this->findCurrency($currencyId);
|
$currency = $this->findCurrency($currencyId);
|
||||||
|
|
||||||
// set the array with monetary info, if it does not exist.
|
// set the array with monetary info, if it does not exist.
|
||||||
$this->createDefaultDataEntry($journal);
|
$this->createDefaultDataEntry($journal);
|
||||||
@@ -152,12 +152,12 @@ class AccountBalanceGrouped
|
|||||||
$this->createDefaultPeriodEntry($journal);
|
$this->createDefaultPeriodEntry($journal);
|
||||||
|
|
||||||
// is this journal's amount in- our outgoing?
|
// is this journal's amount in- our outgoing?
|
||||||
$key = $this->getDataKey($journal);
|
$key = $this->getDataKey($journal);
|
||||||
$amount = 'spent' === $key ? app('steam')->negative($journal['amount']) : app('steam')->positive($journal['amount']);
|
$amount = 'spent' === $key ? app('steam')->negative($journal['amount']) : app('steam')->positive($journal['amount']);
|
||||||
|
|
||||||
// get conversion rate
|
// get conversion rate
|
||||||
$rate = $this->getRate($currency, $journal['date']);
|
$rate = $this->getRate($currency, $journal['date']);
|
||||||
$amountConverted = bcmul($amount, $rate);
|
$amountConverted = bcmul($amount, $rate);
|
||||||
|
|
||||||
// perhaps transaction already has the foreign amount in the native currency.
|
// perhaps transaction already has the foreign amount in the native currency.
|
||||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||||
@@ -166,7 +166,7 @@ class AccountBalanceGrouped
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add normal entry
|
// 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
|
// add converted entry
|
||||||
$convertedKey = sprintf('native_%s', $key);
|
$convertedKey = sprintf('native_%s', $key);
|
||||||
@@ -185,7 +185,7 @@ class AccountBalanceGrouped
|
|||||||
|
|
||||||
private function createDefaultDataEntry(array $journal): void
|
private function createDefaultDataEntry(array $journal): void
|
||||||
{
|
{
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$this->data[$currencyId] ??= [
|
$this->data[$currencyId] ??= [
|
||||||
'currency_id' => (string) $currencyId,
|
'currency_id' => (string) $currencyId,
|
||||||
'currency_symbol' => $journal['currency_symbol'],
|
'currency_symbol' => $journal['currency_symbol'],
|
||||||
@@ -202,8 +202,8 @@ class AccountBalanceGrouped
|
|||||||
|
|
||||||
private function createDefaultPeriodEntry(array $journal): void
|
private function createDefaultPeriodEntry(array $journal): void
|
||||||
{
|
{
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$period = $journal['date']->format($this->carbonFormat);
|
$period = $journal['date']->format($this->carbonFormat);
|
||||||
$this->data[$currencyId][$period] ??= [
|
$this->data[$currencyId][$period] ??= [
|
||||||
'period' => $period,
|
'period' => $period,
|
||||||
'spent' => '0',
|
'spent' => '0',
|
||||||
|
@@ -25,7 +25,6 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support\Http\Api;
|
namespace FireflyIII\Support\Http\Api;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DateTimeInterface;
|
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +45,7 @@ trait ConvertsExchangeRates
|
|||||||
|
|
||||||
// if not enabled, return the same array but without conversion:
|
// if not enabled, return the same array but without conversion:
|
||||||
return $set;
|
return $set;
|
||||||
$this->enabled = false;
|
$this->enabled = false;
|
||||||
if (false === $this->enabled) {
|
if (false === $this->enabled) {
|
||||||
$set['converted'] = false;
|
$set['converted'] = false;
|
||||||
|
|
||||||
@@ -56,8 +55,8 @@ trait ConvertsExchangeRates
|
|||||||
$set['converted'] = true;
|
$set['converted'] = true;
|
||||||
|
|
||||||
/** @var TransactionCurrency $native */
|
/** @var TransactionCurrency $native */
|
||||||
$native = app('amount')->getDefaultCurrency();
|
$native = app('amount')->getDefaultCurrency();
|
||||||
$currency = $this->getCurrency((int) $set['currency_id']);
|
$currency = $this->getCurrency((int) $set['currency_id']);
|
||||||
if ($native->id === $currency->id) {
|
if ($native->id === $currency->id) {
|
||||||
$set['native_currency_id'] = (string) $currency->id;
|
$set['native_currency_id'] = (string) $currency->id;
|
||||||
$set['native_currency_code'] = $currency->code;
|
$set['native_currency_code'] = $currency->code;
|
||||||
@@ -67,9 +66,9 @@ trait ConvertsExchangeRates
|
|||||||
return $set;
|
return $set;
|
||||||
}
|
}
|
||||||
foreach ($set['entries'] as $date => $entry) {
|
foreach ($set['entries'] as $date => $entry) {
|
||||||
$carbon = Carbon::createFromFormat(DateTimeInterface::ATOM, $date);
|
$carbon = Carbon::createFromFormat(\DateTimeInterface::ATOM, $date);
|
||||||
$rate = $this->getRate($currency, $native, $carbon);
|
$rate = $this->getRate($currency, $native, $carbon);
|
||||||
$rate = '0' === $rate ? '1' : $rate;
|
$rate = '0' === $rate ? '1' : $rate;
|
||||||
app('log')->debug(sprintf('bcmul("%s", "%s")', (string) $entry, $rate));
|
app('log')->debug(sprintf('bcmul("%s", "%s")', (string) $entry, $rate));
|
||||||
$set['entries'][$date] = (float) bcmul((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
|
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||||
{
|
{
|
||||||
$key = $this->getCacheKey($from, $to, $date);
|
$key = $this->getCacheKey($from, $to, $date);
|
||||||
$res = Cache::get($key, null);
|
$res = Cache::get($key, null);
|
||||||
|
|
||||||
// find in cache
|
// find in cache
|
||||||
if (null !== $res) {
|
if (null !== $res) {
|
||||||
@@ -96,7 +96,7 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find in database
|
// 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) {
|
if (null !== $rate) {
|
||||||
Cache::forever($key, $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')));
|
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
|
// 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) {
|
if (null !== $rate) {
|
||||||
$rate = bcdiv('1', $rate);
|
$rate = bcdiv('1', $rate);
|
||||||
Cache::forever($key, $rate);
|
Cache::forever($key, $rate);
|
||||||
@@ -143,7 +143,7 @@ class ExchangeRateConverter
|
|||||||
if ($from === $to) {
|
if ($from === $to) {
|
||||||
return '1';
|
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
|
// perhaps the rate has been cached during this particular run
|
||||||
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
||||||
@@ -153,7 +153,7 @@ class ExchangeRateConverter
|
|||||||
return $preparedRate;
|
return $preparedRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($key);
|
$cache->addProperty($key);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
$rate = $cache->get();
|
$rate = $cache->get();
|
||||||
@@ -166,15 +166,16 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var null|CurrencyExchangeRate $result */
|
/** @var null|CurrencyExchangeRate $result */
|
||||||
$result = auth()->user()
|
$result = auth()->user()
|
||||||
?->currencyExchangeRates()
|
?->currencyExchangeRates()
|
||||||
->where('from_currency_id', $from)
|
->where('from_currency_id', $from)
|
||||||
->where('to_currency_id', $to)
|
->where('to_currency_id', $to)
|
||||||
->where('date', '<=', $date)
|
->where('date', '<=', $date)
|
||||||
->orderBy('date', 'DESC')
|
->orderBy('date', 'DESC')
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
$rate = (string) $result?->rate;
|
$rate = (string) $result?->rate;
|
||||||
|
|
||||||
if ('' === $rate) {
|
if ('' === $rate) {
|
||||||
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
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) {
|
if ($euroId === $currency->id) {
|
||||||
return '1';
|
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) {
|
if (null !== $rate) {
|
||||||
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
|
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
|
||||||
return $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) {
|
if (null !== $rate) {
|
||||||
return bcdiv('1', $rate);
|
return bcdiv('1', $rate);
|
||||||
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $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()) {
|
if ($cache->has()) {
|
||||||
return (int) $cache->get();
|
return (int) $cache->get();
|
||||||
}
|
}
|
||||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
if (null === $euro) {
|
if (null === $euro) {
|
||||||
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
||||||
@@ -271,13 +272,14 @@ class ExchangeRateConverter
|
|||||||
$start->startOfDay();
|
$start->startOfDay();
|
||||||
$end->endOfDay();
|
$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')));
|
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()
|
$set = auth()->user()
|
||||||
->currencyExchangeRates()
|
->currencyExchangeRates()
|
||||||
->where('from_currency_id', $from->id)
|
->where('from_currency_id', $from->id)
|
||||||
->where('to_currency_id', $to->id)
|
->where('to_currency_id', $to->id)
|
||||||
->where('date', '<=', $end->format('Y-m-d'))
|
->where('date', '<=', $end->format('Y-m-d'))
|
||||||
->where('date', '>=', $start->format('Y-m-d'))
|
->where('date', '>=', $start->format('Y-m-d'))
|
||||||
->orderBy('date', 'DESC')->get();
|
->orderBy('date', 'DESC')->get()
|
||||||
|
;
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
if (0 === $set->count()) {
|
if (0 === $set->count()) {
|
||||||
Log::debug('No prepared rates found in this period, use the fallback');
|
Log::debug('No prepared rates found in this period, use the fallback');
|
||||||
@@ -291,10 +293,10 @@ class ExchangeRateConverter
|
|||||||
$this->isPrepared = true;
|
$this->isPrepared = true;
|
||||||
|
|
||||||
// so there is a fallback just in case. Now loop the set of rates we DO have.
|
// so there is a fallback just in case. Now loop the set of rates we DO have.
|
||||||
$temp = [];
|
$temp = [];
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($set as $rate) {
|
foreach ($set as $rate) {
|
||||||
$date = $rate->date->format('Y-m-d');
|
$date = $rate->date->format('Y-m-d');
|
||||||
$temp[$date] ??= [
|
$temp[$date] ??= [
|
||||||
$from->id => [
|
$from->id => [
|
||||||
$to->id => $rate->rate,
|
$to->id => $rate->rate,
|
||||||
@@ -303,11 +305,11 @@ class ExchangeRateConverter
|
|||||||
++$count;
|
++$count;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Found %d rates in this period.', $count));
|
Log::debug(sprintf('Found %d rates in this period.', $count));
|
||||||
$currentStart = clone $start;
|
$currentStart = clone $start;
|
||||||
while ($currentStart->lte($end)) {
|
while ($currentStart->lte($end)) {
|
||||||
$currentDate = $currentStart->format('Y-m-d');
|
$currentDate = $currentStart->format('Y-m-d');
|
||||||
$this->prepared[$currentDate] ??= [];
|
$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)) {
|
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
|
||||||
// fill from temp or fallback or from temp (see before)
|
// fill from temp or fallback or from temp (see before)
|
||||||
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
|
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
|
||||||
|
@@ -40,7 +40,7 @@ trait ParsesQueryFilters
|
|||||||
|
|
||||||
private function dateOrToday(QueryParameters $parameters, string $field): Carbon
|
private function dateOrToday(QueryParameters $parameters, string $field): Carbon
|
||||||
{
|
{
|
||||||
$date = today();
|
$date = today();
|
||||||
|
|
||||||
$value = $parameters->filter()?->value($field, date('Y-m-d'));
|
$value = $parameters->filter()?->value($field, date('Y-m-d'));
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class SummaryBalanceGrouped
|
class SummaryBalanceGrouped
|
||||||
{
|
{
|
||||||
private const string SUM = 'sum';
|
private const string SUM = 'sum';
|
||||||
private array $amounts = [];
|
private array $amounts = [];
|
||||||
private array $currencies;
|
private array $currencies;
|
||||||
private CurrencyRepositoryInterface $currencyRepository;
|
private CurrencyRepositoryInterface $currencyRepository;
|
||||||
@@ -47,9 +47,9 @@ class SummaryBalanceGrouped
|
|||||||
public function groupData(): array
|
public function groupData(): array
|
||||||
{
|
{
|
||||||
Log::debug('Now going to group data.');
|
Log::debug('Now going to group data.');
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($this->keys as $key) {
|
foreach ($this->keys as $key) {
|
||||||
$title = match ($key) {
|
$title = match ($key) {
|
||||||
'sum' => 'balance',
|
'sum' => 'balance',
|
||||||
'expense' => 'spent',
|
'expense' => 'spent',
|
||||||
'income' => 'earned',
|
'income' => 'earned',
|
||||||
@@ -108,11 +108,11 @@ class SummaryBalanceGrouped
|
|||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
// transaction info:
|
// transaction info:
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$amount = bcmul($journal['amount'], $multiplier);
|
$amount = bcmul($journal['amount'], $multiplier);
|
||||||
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
||||||
$this->currencies[$currencyId] = $currency;
|
$this->currencies[$currencyId] = $currency;
|
||||||
$nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
$nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
||||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||||
// use foreign amount instead
|
// use foreign amount instead
|
||||||
$nativeAmount = $journal['foreign_amount'];
|
$nativeAmount = $journal['foreign_amount'];
|
||||||
|
@@ -56,8 +56,8 @@ trait ValidatesUserGroupTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$groupId = 0;
|
$groupId = 0;
|
||||||
if (!$request->has('user_group_id')) {
|
if (!$request->has('user_group_id')) {
|
||||||
$groupId = $user->user_group_id;
|
$groupId = $user->user_group_id;
|
||||||
Log::debug(sprintf('validateUserGroup: no user group submitted, use default group #%d.', $groupId));
|
Log::debug(sprintf('validateUserGroup: no user group submitted, use default group #%d.', $groupId));
|
||||||
@@ -68,7 +68,7 @@ trait ValidatesUserGroupTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var UserGroupRepositoryInterface $repository */
|
/** @var UserGroupRepositoryInterface $repository */
|
||||||
$repository = app(UserGroupRepositoryInterface::class);
|
$repository = app(UserGroupRepositoryInterface::class);
|
||||||
$repository->setUser($user);
|
$repository->setUser($user);
|
||||||
$memberships = $repository->getMembershipsFromGroupId($groupId);
|
$memberships = $repository->getMembershipsFromGroupId($groupId);
|
||||||
|
|
||||||
@@ -79,14 +79,14 @@ trait ValidatesUserGroupTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
// need to get the group from the membership:
|
// need to get the group from the membership:
|
||||||
$group = $repository->getById($groupId);
|
$group = $repository->getById($groupId);
|
||||||
if (null === $group) {
|
if (null === $group) {
|
||||||
Log::debug(sprintf('validateUserGroup: group #%d does not exist.', $groupId));
|
Log::debug(sprintf('validateUserGroup: group #%d does not exist.', $groupId));
|
||||||
|
|
||||||
throw new AuthorizationException((string) trans('validation.belongs_user_or_user_group'));
|
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));
|
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)) {
|
if (0 === count($roles)) {
|
||||||
Log::debug('validateUserGroup: no roles defined, so no access.');
|
Log::debug('validateUserGroup: no roles defined, so no access.');
|
||||||
|
|
||||||
|
@@ -55,10 +55,10 @@ trait AugumentData
|
|||||||
|
|
||||||
/** @var Account $expenseAccount */
|
/** @var Account $expenseAccount */
|
||||||
foreach ($accounts as $expenseAccount) {
|
foreach ($accounts as $expenseAccount) {
|
||||||
$collection = new Collection();
|
$collection = new Collection();
|
||||||
$collection->push($expenseAccount);
|
$collection->push($expenseAccount);
|
||||||
|
|
||||||
$revenue = $repository->findByName($expenseAccount->name, [AccountType::REVENUE]);
|
$revenue = $repository->findByName($expenseAccount->name, [AccountType::REVENUE]);
|
||||||
if (null !== $revenue) {
|
if (null !== $revenue) {
|
||||||
$collection->push($revenue);
|
$collection->push($revenue);
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ trait AugumentData
|
|||||||
$return[$accountId] = $grouped[$accountId][0]['name'];
|
$return[$accountId] = $grouped[$accountId][0]['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$return[0] = '(no name)';
|
$return[0] = '(no name)';
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ trait AugumentData
|
|||||||
$return[$budgetId] = $grouped[$budgetId][0]['name'];
|
$return[$budgetId] = $grouped[$budgetId][0]['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$return[0] = (string) trans('firefly.no_budget');
|
$return[0] = (string) trans('firefly.no_budget');
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ trait AugumentData
|
|||||||
$return[$categoryId] = $grouped[$categoryId][0]['name'];
|
$return[$categoryId] = $grouped[$categoryId][0]['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$return[0] = (string) trans('firefly.no_category');
|
$return[0] = (string) trans('firefly.no_category');
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -168,14 +168,14 @@ trait AugumentData
|
|||||||
protected function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection // get data + augment with info
|
protected function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection // get data + augment with info
|
||||||
{
|
{
|
||||||
/** @var OperationsRepositoryInterface $opsRepository */
|
/** @var OperationsRepositoryInterface $opsRepository */
|
||||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||||
|
|
||||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||||
|
|
||||||
$end->endOfMonth();
|
$end->endOfMonth();
|
||||||
// properties for cache
|
// properties for cache
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty($budget->id);
|
$cache->addProperty($budget->id);
|
||||||
@@ -191,7 +191,7 @@ trait AugumentData
|
|||||||
|
|
||||||
/** @var BudgetLimit $entry */
|
/** @var BudgetLimit $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$currency = $entry->transactionCurrency;
|
$currency = $entry->transactionCurrency;
|
||||||
|
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
$currency = app('amount')->getDefaultCurrency();
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
@@ -227,7 +227,7 @@ trait AugumentData
|
|||||||
|
|
||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($array as $journal) {
|
foreach ($array as $journal) {
|
||||||
$name = '(no name)';
|
$name = '(no name)';
|
||||||
if (TransactionType::WITHDRAWAL === $journal['transaction_type_type']) {
|
if (TransactionType::WITHDRAWAL === $journal['transaction_type_type']) {
|
||||||
$name = $journal['destination_account_name'];
|
$name = $journal['destination_account_name'];
|
||||||
}
|
}
|
||||||
@@ -250,16 +250,16 @@ trait AugumentData
|
|||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
|
|
||||||
$total = $assets->merge($opposing);
|
$total = $assets->merge($opposing);
|
||||||
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($total);
|
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($total);
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
$sum = [
|
$sum = [
|
||||||
'grand_sum' => '0',
|
'grand_sum' => '0',
|
||||||
'per_currency' => [],
|
'per_currency' => [],
|
||||||
];
|
];
|
||||||
// loop to support multi currency
|
// loop to support multi currency
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
|
|
||||||
// if not set, set to zero:
|
// if not set, set to zero:
|
||||||
if (!array_key_exists($currencyId, $sum['per_currency'])) {
|
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.
|
protected function accountBalanceChart(Collection $accounts, Carbon $start, Carbon $end): array // chart helper method.
|
||||||
{
|
{
|
||||||
// chart properties for cache:
|
// chart properties for cache:
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('chart.account.account-balance-chart');
|
$cache->addProperty('chart.account.account-balance-chart');
|
||||||
@@ -56,21 +56,21 @@ trait ChartGeneration
|
|||||||
// return $cache->get();
|
// return $cache->get();
|
||||||
}
|
}
|
||||||
app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.');
|
app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.');
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
|
|
||||||
/** @var GeneratorInterface $generator */
|
/** @var GeneratorInterface $generator */
|
||||||
$generator = app(GeneratorInterface::class);
|
$generator = app(GeneratorInterface::class);
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $accountRepos */
|
/** @var AccountRepositoryInterface $accountRepos */
|
||||||
$accountRepos = app(AccountRepositoryInterface::class);
|
$accountRepos = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
$default = app('amount')->getDefaultCurrency();
|
$default = app('amount')->getDefaultCurrency();
|
||||||
$chartData = [];
|
$chartData = [];
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
// TODO we can use getAccountCurrency instead.
|
// TODO we can use getAccountCurrency instead.
|
||||||
$currency = $accountRepos->getAccountCurrency($account);
|
$currency = $accountRepos->getAccountCurrency($account);
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
$currency = $default;
|
$currency = $default;
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ trait ChartGeneration
|
|||||||
$currency = $default;
|
$currency = $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
$currentSet = [
|
$currentSet = [
|
||||||
'label' => $account->name,
|
'label' => $account->name,
|
||||||
'currency_symbol' => $currency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
@@ -89,16 +89,16 @@ trait ChartGeneration
|
|||||||
$range = Steam::finalAccountBalanceInRange($account, $start, clone $end);
|
$range = Steam::finalAccountBalanceInRange($account, $start, clone $end);
|
||||||
$previous = array_values($range)[0];
|
$previous = array_values($range)[0];
|
||||||
while ($currentStart <= $end) {
|
while ($currentStart <= $end) {
|
||||||
$format = $currentStart->format('Y-m-d');
|
$format = $currentStart->format('Y-m-d');
|
||||||
$label = trim($currentStart->isoFormat((string) trans('config.month_and_day_js', [], $locale)));
|
$label = trim($currentStart->isoFormat((string) trans('config.month_and_day_js', [], $locale)));
|
||||||
$balance = $range[$format] ?? $previous;
|
$balance = $range[$format] ?? $previous;
|
||||||
$previous = $balance;
|
$previous = $balance;
|
||||||
$currentStart->addDay();
|
$currentStart->addDay();
|
||||||
$currentSet['entries'][$label] = $balance['balance']; // TODO or native_balance
|
$currentSet['entries'][$label] = $balance['balance']; // TODO or native_balance
|
||||||
}
|
}
|
||||||
$chartData[] = $currentSet;
|
$chartData[] = $currentSet;
|
||||||
}
|
}
|
||||||
$data = $generator->multiSet($chartData);
|
$data = $generator->multiSet($chartData);
|
||||||
$cache->store($data);
|
$cache->store($data);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
@@ -102,7 +102,7 @@ trait CreateStuff
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$key = RSA::createKey(4096);
|
$key = RSA::createKey(4096);
|
||||||
|
|
||||||
Log::alert('NO OAuth keys were found. They have been created.');
|
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
|
protected function getNextPeriods(Carbon $date, string $range): array
|
||||||
{
|
{
|
||||||
// select thing for next 12 periods:
|
// select thing for next 12 periods:
|
||||||
$loop = [];
|
$loop = [];
|
||||||
|
|
||||||
/** @var Carbon $current */
|
/** @var Carbon $current */
|
||||||
$current = app('navigation')->startOfPeriod($date, $range);
|
$current = app('navigation')->startOfPeriod($date, $range);
|
||||||
$current = app('navigation')->endOfPeriod($current, $range);
|
$current = app('navigation')->endOfPeriod($current, $range);
|
||||||
$current->addDay();
|
$current->addDay();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
|
|
||||||
while ($count < 12) {
|
while ($count < 12) {
|
||||||
$current = app('navigation')->endOfPeriod($current, $range);
|
$current = app('navigation')->endOfPeriod($current, $range);
|
||||||
$currentStart = app('navigation')->startOfPeriod($current, $range);
|
$currentStart = app('navigation')->startOfPeriod($current, $range);
|
||||||
|
|
||||||
$loop[] = [
|
$loop[] = [
|
||||||
'label' => $current->format('Y-m-d'),
|
'label' => $current->format('Y-m-d'),
|
||||||
'title' => app('navigation')->periodShow($current, $range),
|
'title' => app('navigation')->periodShow($current, $range),
|
||||||
'start' => clone $currentStart,
|
'start' => clone $currentStart,
|
||||||
@@ -122,7 +122,7 @@ trait DateCalculation
|
|||||||
protected function getPreviousPeriods(Carbon $date, string $range): array
|
protected function getPreviousPeriods(Carbon $date, string $range): array
|
||||||
{
|
{
|
||||||
// select thing for last 12 periods:
|
// select thing for last 12 periods:
|
||||||
$loop = [];
|
$loop = [];
|
||||||
|
|
||||||
/** @var Carbon $current */
|
/** @var Carbon $current */
|
||||||
$current = app('navigation')->startOfPeriod($date, $range);
|
$current = app('navigation')->startOfPeriod($date, $range);
|
||||||
|
@@ -61,13 +61,13 @@ trait GetConfigurationData
|
|||||||
$steps = [];
|
$steps = [];
|
||||||
if (is_array($elements) && count($elements) > 0) {
|
if (is_array($elements) && count($elements) > 0) {
|
||||||
foreach ($elements as $key => $options) {
|
foreach ($elements as $key => $options) {
|
||||||
$currentStep = $options;
|
$currentStep = $options;
|
||||||
|
|
||||||
// get the text:
|
// get the text:
|
||||||
$currentStep['intro'] = (string) trans('intro.' . $route . '_' . $key);
|
$currentStep['intro'] = (string) trans('intro.'.$route.'_'.$key);
|
||||||
|
|
||||||
// save in array:
|
// save in array:
|
||||||
$steps[] = $currentStep;
|
$steps[] = $currentStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Total basic steps for %s is %d', $routeKey, count($steps)));
|
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.
|
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));
|
Log::debug(sprintf('dateRange: the view range is "%s"', $viewRange));
|
||||||
|
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = session('start');
|
$start = session('start');
|
||||||
|
|
||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = session('end');
|
$end = session('end');
|
||||||
|
|
||||||
/** @var Carbon $first */
|
/** @var Carbon $first */
|
||||||
$first = session('first');
|
$first = session('first');
|
||||||
$title = sprintf('%s - %s', $start->isoFormat($this->monthAndDayFormat), $end->isoFormat($this->monthAndDayFormat));
|
$title = sprintf('%s - %s', $start->isoFormat($this->monthAndDayFormat), $end->isoFormat($this->monthAndDayFormat));
|
||||||
$isCustom = true === session('is_custom_range', false);
|
$isCustom = true === session('is_custom_range', false);
|
||||||
$today = today(config('app.timezone'));
|
$today = today(config('app.timezone'));
|
||||||
$ranges = [
|
$ranges = [
|
||||||
// first range is the current range:
|
// first range is the current range:
|
||||||
$title => [$start, $end],
|
$title => [$start, $end],
|
||||||
];
|
];
|
||||||
@@ -127,10 +127,10 @@ trait GetConfigurationData
|
|||||||
|
|
||||||
// today:
|
// today:
|
||||||
/** @var Carbon $todayStart */
|
/** @var Carbon $todayStart */
|
||||||
$todayStart = app('navigation')->startOfPeriod($today, $viewRange);
|
$todayStart = app('navigation')->startOfPeriod($today, $viewRange);
|
||||||
|
|
||||||
/** @var Carbon $todayEnd */
|
/** @var Carbon $todayEnd */
|
||||||
$todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange);
|
$todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange);
|
||||||
|
|
||||||
if ($todayStart->ne($start) || $todayEnd->ne($end)) {
|
if ($todayStart->ne($start) || $todayEnd->ne($end)) {
|
||||||
$ranges[ucfirst((string) trans('firefly.today'))] = [$todayStart, $todayEnd];
|
$ranges[ucfirst((string) trans('firefly.today'))] = [$todayStart, $todayEnd];
|
||||||
@@ -186,16 +186,16 @@ trait GetConfigurationData
|
|||||||
// user is on page with specific instructions:
|
// user is on page with specific instructions:
|
||||||
if ('' !== $specificPage) {
|
if ('' !== $specificPage) {
|
||||||
$routeKey = str_replace('.', '_', $route);
|
$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) {
|
if (is_array($elements) && count($elements) > 0) {
|
||||||
foreach ($elements as $key => $options) {
|
foreach ($elements as $key => $options) {
|
||||||
$currentStep = $options;
|
$currentStep = $options;
|
||||||
|
|
||||||
// get the text:
|
// get the text:
|
||||||
$currentStep['intro'] = (string) trans('intro.' . $route . '_' . $specificPage . '_' . $key);
|
$currentStep['intro'] = (string) trans('intro.'.$route.'_'.$specificPage.'_'.$key);
|
||||||
|
|
||||||
// save in array:
|
// save in array:
|
||||||
$steps[] = $currentStep;
|
$steps[] = $currentStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,6 @@ use FireflyIII\Models\Tag;
|
|||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait ModelInformation
|
* Trait ModelInformation
|
||||||
@@ -56,7 +55,7 @@ trait ModelInformation
|
|||||||
'count' => 1,
|
'count' => 1,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage()));
|
app('log')->error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
$result = 'Could not render view. See log files.';
|
$result = 'Could not render view. See log files.';
|
||||||
@@ -75,14 +74,14 @@ trait ModelInformation
|
|||||||
protected function getLiabilityTypes(): array
|
protected function getLiabilityTypes(): array
|
||||||
{
|
{
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
// types of liability:
|
// types of liability:
|
||||||
/** @var AccountType $debt */
|
/** @var AccountType $debt */
|
||||||
$debt = $repository->getAccountTypeByType(AccountType::DEBT);
|
$debt = $repository->getAccountTypeByType(AccountType::DEBT);
|
||||||
|
|
||||||
/** @var AccountType $loan */
|
/** @var AccountType $loan */
|
||||||
$loan = $repository->getAccountTypeByType(AccountType::LOAN);
|
$loan = $repository->getAccountTypeByType(AccountType::LOAN);
|
||||||
|
|
||||||
/** @var AccountType $mortgage */
|
/** @var AccountType $mortgage */
|
||||||
$mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE);
|
$mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE);
|
||||||
@@ -114,8 +113,8 @@ trait ModelInformation
|
|||||||
protected function getTriggersForBill(Bill $bill): array // get info and argument
|
protected function getTriggersForBill(Bill $bill): array // get info and argument
|
||||||
{
|
{
|
||||||
// TODO duplicate code
|
// TODO duplicate code
|
||||||
$operators = config('search.operators');
|
$operators = config('search.operators');
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
foreach ($operators as $key => $operator) {
|
foreach ($operators as $key => $operator) {
|
||||||
if ('user_action' !== $key && false === $operator['alias']) {
|
if ('user_action' !== $key && false === $operator['alias']) {
|
||||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||||
@@ -143,7 +142,7 @@ trait ModelInformation
|
|||||||
'triggers' => $triggers,
|
'triggers' => $triggers,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
|
||||||
app('log')->debug($e->getTraceAsString());
|
app('log')->debug($e->getTraceAsString());
|
||||||
|
|
||||||
@@ -165,8 +164,8 @@ trait ModelInformation
|
|||||||
private function getTriggersForJournal(TransactionJournal $journal): array
|
private function getTriggersForJournal(TransactionJournal $journal): array
|
||||||
{
|
{
|
||||||
// TODO duplicated code.
|
// TODO duplicated code.
|
||||||
$operators = config('search.operators');
|
$operators = config('search.operators');
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
foreach ($operators as $key => $operator) {
|
foreach ($operators as $key => $operator) {
|
||||||
if ('user_action' !== $key && false === $operator['alias']) {
|
if ('user_action' !== $key && false === $operator['alias']) {
|
||||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||||
@@ -174,18 +173,18 @@ trait ModelInformation
|
|||||||
}
|
}
|
||||||
asort($triggers);
|
asort($triggers);
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
$journalTriggers = [];
|
$journalTriggers = [];
|
||||||
$values = [];
|
$values = [];
|
||||||
$index = 0;
|
$index = 0;
|
||||||
|
|
||||||
// amount, description, category, budget, tags, source, destination, notes, currency type
|
// amount, description, category, budget, tags, source, destination, notes, currency type
|
||||||
// ,type
|
// ,type
|
||||||
/** @var null|Transaction $source */
|
/** @var null|Transaction $source */
|
||||||
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
|
|
||||||
/** @var null|Transaction $destination */
|
/** @var null|Transaction $destination */
|
||||||
$destination = $journal->transactions()->where('amount', '>', 0)->first();
|
$destination = $journal->transactions()->where('amount', '>', 0)->first();
|
||||||
if (null === $destination || null === $source) {
|
if (null === $destination || null === $source) {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -220,21 +219,21 @@ trait ModelInformation
|
|||||||
++$index;
|
++$index;
|
||||||
|
|
||||||
// category (if)
|
// category (if)
|
||||||
$category = $journal->categories()->first();
|
$category = $journal->categories()->first();
|
||||||
if (null !== $category) {
|
if (null !== $category) {
|
||||||
$journalTriggers[$index] = 'category_is';
|
$journalTriggers[$index] = 'category_is';
|
||||||
$values[$index] = $category->name;
|
$values[$index] = $category->name;
|
||||||
++$index;
|
++$index;
|
||||||
}
|
}
|
||||||
// budget (if)
|
// budget (if)
|
||||||
$budget = $journal->budgets()->first();
|
$budget = $journal->budgets()->first();
|
||||||
if (null !== $budget) {
|
if (null !== $budget) {
|
||||||
$journalTriggers[$index] = 'budget_is';
|
$journalTriggers[$index] = 'budget_is';
|
||||||
$values[$index] = $budget->name;
|
$values[$index] = $budget->name;
|
||||||
++$index;
|
++$index;
|
||||||
}
|
}
|
||||||
// tags (if)
|
// tags (if)
|
||||||
$tags = $journal->tags()->get();
|
$tags = $journal->tags()->get();
|
||||||
|
|
||||||
/** @var Tag $tag */
|
/** @var Tag $tag */
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
@@ -243,7 +242,7 @@ trait ModelInformation
|
|||||||
++$index;
|
++$index;
|
||||||
}
|
}
|
||||||
// notes (if)
|
// notes (if)
|
||||||
$notes = $journal->notes()->first();
|
$notes = $journal->notes()->first();
|
||||||
if (null !== $notes) {
|
if (null !== $notes) {
|
||||||
$journalTriggers[$index] = 'notes_are';
|
$journalTriggers[$index] = 'notes_are';
|
||||||
$values[$index] = $notes->text;
|
$values[$index] = $notes->text;
|
||||||
@@ -259,7 +258,7 @@ trait ModelInformation
|
|||||||
'triggers' => $triggers,
|
'triggers' => $triggers,
|
||||||
];
|
];
|
||||||
$string = view('rules.partials.trigger', $renderInfo)->render();
|
$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(sprintf('Throwable was thrown in getTriggersForJournal(): %s', $e->getMessage()));
|
||||||
app('log')->debug($e->getTraceAsString());
|
app('log')->debug($e->getTraceAsString());
|
||||||
|
|
||||||
|
@@ -75,11 +75,11 @@ trait PeriodOverview
|
|||||||
*/
|
*/
|
||||||
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
|
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];
|
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||||
|
|
||||||
// properties for cache
|
// properties for cache
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('account-show-period-entries');
|
$cache->addProperty('account-show-period-entries');
|
||||||
@@ -89,32 +89,32 @@ trait PeriodOverview
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
// collect all expenses in this period:
|
// collect all expenses in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts(new Collection([$account]));
|
$collector->setAccounts(new Collection([$account]));
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||||
$earnedSet = $collector->getExtractedJournals();
|
$earnedSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all income in this period:
|
// collect all income in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts(new Collection([$account]));
|
$collector->setAccounts(new Collection([$account]));
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
$spentSet = $collector->getExtractedJournals();
|
$spentSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all transfers in this period:
|
// collect all transfers in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts(new Collection([$account]));
|
$collector->setAccounts(new Collection([$account]));
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::TRANSFER]);
|
$collector->setTypes([TransactionType::TRANSFER]);
|
||||||
$transferSet = $collector->getExtractedJournals();
|
$transferSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// loop dates
|
// loop dates
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
@@ -125,15 +125,15 @@ trait PeriodOverview
|
|||||||
$transferredIn = $this->filterTransferredIn($account, $this->filterJournalsByDate($transferSet, $currentDate['start'], $currentDate['end']));
|
$transferredIn = $this->filterTransferredIn($account, $this->filterJournalsByDate($transferSet, $currentDate['start'], $currentDate['end']));
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'route' => route('accounts.show', [$account->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
'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),
|
'total_transactions' => count($spent) + count($earned) + count($transferredAway) + count($transferredIn),
|
||||||
'spent' => $this->groupByCurrency($spent),
|
'spent' => $this->groupByCurrency($spent),
|
||||||
'earned' => $this->groupByCurrency($earned),
|
'earned' => $this->groupByCurrency($earned),
|
||||||
'transferred_away' => $this->groupByCurrency($transferredAway),
|
'transferred_away' => $this->groupByCurrency($transferredAway),
|
||||||
'transferred_in' => $this->groupByCurrency($transferredIn),
|
'transferred_in' => $this->groupByCurrency($transferredIn),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$cache->store($entries);
|
$cache->store($entries);
|
||||||
|
|
||||||
@@ -197,8 +197,8 @@ trait PeriodOverview
|
|||||||
|
|
||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$currencyId = (int) $journal['currency_id'];
|
$currencyId = (int) $journal['currency_id'];
|
||||||
$foreignCurrencyId = $journal['foreign_currency_id'];
|
$foreignCurrencyId = $journal['foreign_currency_id'];
|
||||||
if (!array_key_exists($currencyId, $return)) {
|
if (!array_key_exists($currencyId, $return)) {
|
||||||
$return[$currencyId] = [
|
$return[$currencyId] = [
|
||||||
'amount' => '0',
|
'amount' => '0',
|
||||||
@@ -240,11 +240,11 @@ trait PeriodOverview
|
|||||||
*/
|
*/
|
||||||
protected function getCategoryPeriodOverview(Category $category, Carbon $start, Carbon $end): array
|
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];
|
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||||
|
|
||||||
// properties for entries with their amounts.
|
// properties for entries with their amounts.
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty($range);
|
$cache->addProperty($range);
|
||||||
@@ -256,32 +256,32 @@ trait PeriodOverview
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
// collect all expenses in this period:
|
// collect all expenses in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setCategory($category);
|
$collector->setCategory($category);
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||||
$earnedSet = $collector->getExtractedJournals();
|
$earnedSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all income in this period:
|
// collect all income in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setCategory($category);
|
$collector->setCategory($category);
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
$spentSet = $collector->getExtractedJournals();
|
$spentSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all transfers in this period:
|
// collect all transfers in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setCategory($category);
|
$collector->setCategory($category);
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::TRANSFER]);
|
$collector->setTypes([TransactionType::TRANSFER]);
|
||||||
$transferSet = $collector->getExtractedJournals();
|
$transferSet = $collector->getExtractedJournals();
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$spent = $this->filterJournalsByDate($spentSet, $currentDate['start'], $currentDate['end']);
|
$spent = $this->filterJournalsByDate($spentSet, $currentDate['start'], $currentDate['end']);
|
||||||
$earned = $this->filterJournalsByDate($earnedSet, $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']);
|
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'transactions' => 0,
|
'transactions' => 0,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'route' => route(
|
'route' => route(
|
||||||
'categories.show',
|
'categories.show',
|
||||||
[$category->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
[$category->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
||||||
),
|
),
|
||||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||||
'spent' => $this->groupByCurrency($spent),
|
'spent' => $this->groupByCurrency($spent),
|
||||||
'earned' => $this->groupByCurrency($earned),
|
'earned' => $this->groupByCurrency($earned),
|
||||||
'transferred' => $this->groupByCurrency($transferred),
|
'transferred' => $this->groupByCurrency($transferred),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$cache->store($entries);
|
$cache->store($entries);
|
||||||
|
|
||||||
@@ -315,11 +315,11 @@ trait PeriodOverview
|
|||||||
*/
|
*/
|
||||||
protected function getNoBudgetPeriodOverview(Carbon $start, Carbon $end): array
|
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];
|
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||||
|
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('no-budget-period-entries');
|
$cache->addProperty('no-budget-period-entries');
|
||||||
@@ -329,28 +329,28 @@ trait PeriodOverview
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
// get all expenses without a budget.
|
// get all expenses without a budget.
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setRange($start, $end)->withoutBudget()->withAccountInformation()->setTypes([TransactionType::WITHDRAWAL]);
|
$collector->setRange($start, $end)->withoutBudget()->withAccountInformation()->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$set = $this->filterJournalsByDate($journals, $currentDate['start'], $currentDate['end']);
|
$set = $this->filterJournalsByDate($journals, $currentDate['start'], $currentDate['end']);
|
||||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'route' => route('budgets.no-budget', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
'route' => route('budgets.no-budget', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
||||||
'total_transactions' => count($set),
|
'total_transactions' => count($set),
|
||||||
'spent' => $this->groupByCurrency($set),
|
'spent' => $this->groupByCurrency($set),
|
||||||
'earned' => [],
|
'earned' => [],
|
||||||
'transferred_away' => [],
|
'transferred_away' => [],
|
||||||
'transferred_in' => [],
|
'transferred_in' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$cache->store($entries);
|
$cache->store($entries);
|
||||||
|
|
||||||
@@ -367,38 +367,38 @@ trait PeriodOverview
|
|||||||
protected function getNoCategoryPeriodOverview(Carbon $theDate): array
|
protected function getNoCategoryPeriodOverview(Carbon $theDate): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d')));
|
app('log')->debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d')));
|
||||||
$range = app('navigation')->getViewRange(true);
|
$range = app('navigation')->getViewRange(true);
|
||||||
$first = $this->journalRepos->firstNull();
|
$first = $this->journalRepos->firstNull();
|
||||||
$start = null === $first ? new Carbon() : $first->date;
|
$start = null === $first ? new Carbon() : $first->date;
|
||||||
$end = clone $theDate;
|
$end = clone $theDate;
|
||||||
$end = app('navigation')->endOfPeriod($end, $range);
|
$end = app('navigation')->endOfPeriod($end, $range);
|
||||||
|
|
||||||
app('log')->debug(sprintf('Start for getNoCategoryPeriodOverview() is %s', $start->format('Y-m-d')));
|
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')));
|
app('log')->debug(sprintf('End for getNoCategoryPeriodOverview() is %s', $end->format('Y-m-d')));
|
||||||
|
|
||||||
// properties for cache
|
// properties for cache
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
// collect all expenses in this period:
|
// collect all expenses in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->withoutCategory();
|
$collector->withoutCategory();
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||||
$earnedSet = $collector->getExtractedJournals();
|
$earnedSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all income in this period:
|
// collect all income in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->withoutCategory();
|
$collector->withoutCategory();
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
$spentSet = $collector->getExtractedJournals();
|
$spentSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all transfers in this period:
|
// collect all transfers in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->withoutCategory();
|
$collector->withoutCategory();
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::TRANSFER]);
|
$collector->setTypes([TransactionType::TRANSFER]);
|
||||||
@@ -412,13 +412,13 @@ trait PeriodOverview
|
|||||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'route' => route('categories.no-category', [$currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
'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),
|
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||||
'spent' => $this->groupByCurrency($spent),
|
'spent' => $this->groupByCurrency($spent),
|
||||||
'earned' => $this->groupByCurrency($earned),
|
'earned' => $this->groupByCurrency($earned),
|
||||||
'transferred' => $this->groupByCurrency($transferred),
|
'transferred' => $this->groupByCurrency($transferred),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
app('log')->debug('End of loops');
|
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.
|
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];
|
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||||
|
|
||||||
// properties for cache
|
// properties for cache
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('tag-period-entries');
|
$cache->addProperty('tag-period-entries');
|
||||||
@@ -446,37 +446,37 @@ trait PeriodOverview
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
// collect all expenses in this period:
|
// collect all expenses in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setTag($tag);
|
$collector->setTag($tag);
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::DEPOSIT]);
|
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||||
$earnedSet = $collector->getExtractedJournals();
|
$earnedSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all income in this period:
|
// collect all income in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setTag($tag);
|
$collector->setTag($tag);
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
$spentSet = $collector->getExtractedJournals();
|
$spentSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// collect all transfers in this period:
|
// collect all transfers in this period:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setTag($tag);
|
$collector->setTag($tag);
|
||||||
$collector->setRange($start, $end);
|
$collector->setRange($start, $end);
|
||||||
$collector->setTypes([TransactionType::TRANSFER]);
|
$collector->setTypes([TransactionType::TRANSFER]);
|
||||||
$transferSet = $collector->getExtractedJournals();
|
$transferSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// filer all of them:
|
// filer all of them:
|
||||||
$earnedSet = $this->filterJournalsByTag($earnedSet, $tag);
|
$earnedSet = $this->filterJournalsByTag($earnedSet, $tag);
|
||||||
$spentSet = $this->filterJournalsByTag($spentSet, $tag);
|
$spentSet = $this->filterJournalsByTag($spentSet, $tag);
|
||||||
$transferSet = $this->filterJournalsByTag($transferSet, $tag);
|
$transferSet = $this->filterJournalsByTag($transferSet, $tag);
|
||||||
|
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$spent = $this->filterJournalsByDate($spentSet, $currentDate['start'], $currentDate['end']);
|
$spent = $this->filterJournalsByDate($spentSet, $currentDate['start'], $currentDate['end']);
|
||||||
@@ -485,17 +485,17 @@ trait PeriodOverview
|
|||||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'transactions' => 0,
|
'transactions' => 0,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'route' => route(
|
'route' => route(
|
||||||
'tags.show',
|
'tags.show',
|
||||||
[$tag->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
[$tag->id, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
|
||||||
),
|
),
|
||||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||||
'spent' => $this->groupByCurrency($spent),
|
'spent' => $this->groupByCurrency($spent),
|
||||||
'earned' => $this->groupByCurrency($earned),
|
'earned' => $this->groupByCurrency($earned),
|
||||||
'transferred' => $this->groupByCurrency($transferred),
|
'transferred' => $this->groupByCurrency($transferred),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
@@ -505,7 +505,7 @@ trait PeriodOverview
|
|||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$found = false;
|
$found = false;
|
||||||
|
|
||||||
/** @var array $localTag */
|
/** @var array $localTag */
|
||||||
foreach ($entry['tags'] as $localTag) {
|
foreach ($entry['tags'] as $localTag) {
|
||||||
@@ -527,12 +527,12 @@ trait PeriodOverview
|
|||||||
*/
|
*/
|
||||||
protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array
|
protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$range = app('navigation')->getViewRange(true);
|
$range = app('navigation')->getViewRange(true);
|
||||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
|
$types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
|
||||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||||
|
|
||||||
// properties for cache
|
// properties for cache
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('transactions-period-entries');
|
$cache->addProperty('transactions-period-entries');
|
||||||
@@ -542,13 +542,13 @@ trait PeriodOverview
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
// collect all journals in this period (regardless of type)
|
// collect all journals in this period (regardless of type)
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setTypes($types)->setRange($start, $end);
|
$collector->setTypes($types)->setRange($start, $end);
|
||||||
$genericSet = $collector->getExtractedJournals();
|
$genericSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$spent = [];
|
$spent = [];
|
||||||
@@ -567,14 +567,14 @@ trait PeriodOverview
|
|||||||
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||||
}
|
}
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'route' => route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
|
'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),
|
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||||
'spent' => $this->groupByCurrency($spent),
|
'spent' => $this->groupByCurrency($spent),
|
||||||
'earned' => $this->groupByCurrency($earned),
|
'earned' => $this->groupByCurrency($earned),
|
||||||
'transferred' => $this->groupByCurrency($transferred),
|
'transferred' => $this->groupByCurrency($transferred),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
|
@@ -37,7 +37,6 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait RenderPartialViews
|
* Trait RenderPartialViews
|
||||||
@@ -52,24 +51,24 @@ trait RenderPartialViews
|
|||||||
protected function budgetEntry(array $attributes): string // generate view for report.
|
protected function budgetEntry(array $attributes): string // generate view for report.
|
||||||
{
|
{
|
||||||
/** @var PopupReportInterface $popupHelper */
|
/** @var PopupReportInterface $popupHelper */
|
||||||
$popupHelper = app(PopupReportInterface::class);
|
$popupHelper = app(PopupReportInterface::class);
|
||||||
|
|
||||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||||
$budget = $budgetRepository->find((int) $attributes['budgetId']);
|
$budget = $budgetRepository->find((int) $attributes['budgetId']);
|
||||||
|
|
||||||
$accountRepos = app(AccountRepositoryInterface::class);
|
$accountRepos = app(AccountRepositoryInterface::class);
|
||||||
$account = $accountRepos->find((int) $attributes['accountId']);
|
$account = $accountRepos->find((int) $attributes['accountId']);
|
||||||
|
|
||||||
if (null === $budget || null === $account) {
|
if (null === $budget || null === $account) {
|
||||||
throw new FireflyException('Could not render popup.report.balance-amount because budget or account is null.');
|
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 {
|
try {
|
||||||
$view = view('popup.report.balance-amount', compact('journals', 'budget', 'account'))->render();
|
$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()));
|
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||||
|
|
||||||
@@ -92,7 +91,7 @@ trait RenderPartialViews
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$result = view('reports.options.budget', compact('budgets'))->render();
|
$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()));
|
app('log')->error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage()));
|
||||||
$result = 'Could not render view.';
|
$result = 'Could not render view.';
|
||||||
|
|
||||||
@@ -113,18 +112,18 @@ trait RenderPartialViews
|
|||||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
/** @var PopupReportInterface $popupHelper */
|
/** @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) {
|
if (null === $budget) {
|
||||||
// transactions without a budget.
|
// transactions without a budget.
|
||||||
$budget = new Budget();
|
$budget = new Budget();
|
||||||
}
|
}
|
||||||
$journals = $popupHelper->byBudget($budget, $attributes);
|
$journals = $popupHelper->byBudget($budget, $attributes);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render();
|
$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()));
|
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
$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.
|
protected function categoryEntry(array $attributes): string // generate view for report.
|
||||||
{
|
{
|
||||||
/** @var PopupReportInterface $popupHelper */
|
/** @var PopupReportInterface $popupHelper */
|
||||||
$popupHelper = app(PopupReportInterface::class);
|
$popupHelper = app(PopupReportInterface::class);
|
||||||
|
|
||||||
/** @var CategoryRepositoryInterface $categoryRepository */
|
/** @var CategoryRepositoryInterface $categoryRepository */
|
||||||
$categoryRepository = app(CategoryRepositoryInterface::class);
|
$categoryRepository = app(CategoryRepositoryInterface::class);
|
||||||
@@ -151,7 +150,7 @@ trait RenderPartialViews
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
|
$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()));
|
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||||
|
|
||||||
@@ -174,7 +173,7 @@ trait RenderPartialViews
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$result = view('reports.options.category', compact('categories'))->render();
|
$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()));
|
app('log')->error(sprintf('Cannot render reports.options.category: %s', $e->getMessage()));
|
||||||
$result = 'Could not render view.';
|
$result = 'Could not render view.';
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ trait RenderPartialViews
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$result = view('reports.options.double', compact('set'))->render();
|
$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()));
|
app('log')->error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage()));
|
||||||
$result = 'Could not render view.';
|
$result = 'Could not render view.';
|
||||||
|
|
||||||
@@ -237,19 +236,19 @@ trait RenderPartialViews
|
|||||||
$accountRepository = app(AccountRepositoryInterface::class);
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
/** @var PopupReportInterface $popupHelper */
|
/** @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) {
|
if (null === $account) {
|
||||||
return 'This is an unknown account. Apologies.';
|
return 'This is an unknown account. Apologies.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$journals = $popupHelper->byExpenses($account, $attributes);
|
$journals = $popupHelper->byExpenses($account, $attributes);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$view = view('popup.report.expense-entry', compact('journals', 'account'))->render();
|
$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()));
|
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
$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.
|
protected function getCurrentActions(Rule $rule): array // get info from object and present.
|
||||||
{
|
{
|
||||||
$index = 0;
|
$index = 0;
|
||||||
$actions = [];
|
$actions = [];
|
||||||
// must be repos
|
// must be repos
|
||||||
$currentActions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
$currentActions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
||||||
|
|
||||||
@@ -285,7 +284,7 @@ trait RenderPartialViews
|
|||||||
'count' => $count,
|
'count' => $count,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
|
|
||||||
@@ -306,8 +305,8 @@ trait RenderPartialViews
|
|||||||
protected function getCurrentTriggers(Rule $rule): array // get info from object and present.
|
protected function getCurrentTriggers(Rule $rule): array // get info from object and present.
|
||||||
{
|
{
|
||||||
// TODO duplicated code.
|
// TODO duplicated code.
|
||||||
$operators = config('search.operators');
|
$operators = config('search.operators');
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
foreach ($operators as $key => $operator) {
|
foreach ($operators as $key => $operator) {
|
||||||
if ('user_action' !== $key && false === $operator['alias']) {
|
if ('user_action' !== $key && false === $operator['alias']) {
|
||||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||||
@@ -325,7 +324,7 @@ trait RenderPartialViews
|
|||||||
$count = ($index + 1);
|
$count = ($index + 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$rootOperator = OperatorQuerySearch::getRootOperator((string) $entry->trigger_type);
|
$rootOperator = OperatorQuerySearch::getRootOperator((string) $entry->trigger_type);
|
||||||
if (str_starts_with($rootOperator, '-')) {
|
if (str_starts_with($rootOperator, '-')) {
|
||||||
$rootOperator = substr($rootOperator, 1);
|
$rootOperator = substr($rootOperator, 1);
|
||||||
}
|
}
|
||||||
@@ -340,7 +339,7 @@ trait RenderPartialViews
|
|||||||
'triggers' => $triggers,
|
'triggers' => $triggers,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
|
|
||||||
@@ -365,18 +364,18 @@ trait RenderPartialViews
|
|||||||
$accountRepository = app(AccountRepositoryInterface::class);
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
/** @var PopupReportInterface $popupHelper */
|
/** @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) {
|
if (null === $account) {
|
||||||
return 'This is an unknown category. Apologies.';
|
return 'This is an unknown category. Apologies.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$journals = $popupHelper->byIncome($account, $attributes);
|
$journals = $popupHelper->byIncome($account, $attributes);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$view = view('popup.report.income-entry', compact('journals', 'account'))->render();
|
$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()));
|
app('log')->error(sprintf('Could not render: %s', $e->getMessage()));
|
||||||
$view = 'Firefly III could not render the view. Please see the log files.';
|
$view = 'Firefly III could not render the view. Please see the log files.';
|
||||||
|
|
||||||
@@ -395,7 +394,7 @@ trait RenderPartialViews
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$result = view('reports.options.no-options')->render();
|
$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()));
|
app('log')->error(sprintf('Cannot render reports.options.no-options: %s', $e->getMessage()));
|
||||||
$result = 'Could not render view.';
|
$result = 'Could not render view.';
|
||||||
|
|
||||||
@@ -418,7 +417,7 @@ trait RenderPartialViews
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$result = view('reports.options.tag', compact('tags'))->render();
|
$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()));
|
app('log')->error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage()));
|
||||||
$result = 'Could not render view.';
|
$result = 'Could not render view.';
|
||||||
|
|
||||||
|
@@ -30,7 +30,6 @@ use FireflyIII\Http\Requests\RuleFormRequest;
|
|||||||
use FireflyIII\Http\Requests\TestRuleFormRequest;
|
use FireflyIII\Http\Requests\TestRuleFormRequest;
|
||||||
use FireflyIII\Support\Binder\AccountList;
|
use FireflyIII\Support\Binder\AccountList;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Hash;
|
|
||||||
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
|
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
|
||||||
use Illuminate\Routing\Route;
|
use Illuminate\Routing\Route;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
@@ -83,13 +82,13 @@ trait RequestInformation
|
|||||||
$page = $this->getPageName();
|
$page = $this->getPageName();
|
||||||
$specificPage = $this->getSpecificPageName();
|
$specificPage = $this->getSpecificPageName();
|
||||||
// indicator if user has seen the help for this page ( + special page):
|
// 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?
|
// is there an intro for this route?
|
||||||
$intro = config(sprintf('intro.%s', $page)) ?? [];
|
$intro = config(sprintf('intro.%s', $page)) ?? [];
|
||||||
$specialIntro = config(sprintf('intro.%s%s', $page, $specificPage)) ?? [];
|
$specialIntro = config(sprintf('intro.%s%s', $page, $specificPage)) ?? [];
|
||||||
// some routes have a "what" parameter, which indicates a special page:
|
// some routes have a "what" parameter, which indicates a special page:
|
||||||
|
|
||||||
$shownDemo = true;
|
$shownDemo = true;
|
||||||
// both must be array and either must be > 0
|
// both must be array and either must be > 0
|
||||||
if (count($intro) > 0 || count($specialIntro) > 0) {
|
if (count($intro) > 0 || count($specialIntro) > 0) {
|
||||||
$shownDemo = app('preferences')->get($key, false)->data;
|
$shownDemo = app('preferences')->get($key, false)->data;
|
||||||
@@ -123,7 +122,7 @@ trait RequestInformation
|
|||||||
final protected function notInSessionRange(Carbon $date): bool // Validate a preference
|
final protected function notInSessionRange(Carbon $date): bool // Validate a preference
|
||||||
{
|
{
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = session('start', today(config('app.timezone'))->startOfMonth());
|
$start = session('start', today(config('app.timezone'))->startOfMonth());
|
||||||
|
|
||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = session('end', today(config('app.timezone'))->endOfMonth());
|
$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
|
final protected function parseAttributes(array $attributes): array // parse input + return result
|
||||||
{
|
{
|
||||||
$attributes['location'] ??= '';
|
$attributes['location'] ??= '';
|
||||||
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', []));
|
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', []));
|
||||||
$date = Carbon::createFromFormat('Ymd', $attributes['startDate']);
|
$date = Carbon::createFromFormat('Ymd', $attributes['startDate']);
|
||||||
if (null === $date) {
|
if (null === $date) {
|
||||||
$date = today(config('app.timezone'));
|
$date = today(config('app.timezone'));
|
||||||
}
|
}
|
||||||
$date->startOfMonth();
|
$date->startOfMonth();
|
||||||
$attributes['startDate'] = $date;
|
$attributes['startDate'] = $date;
|
||||||
|
|
||||||
$date2 = Carbon::createFromFormat('Ymd', $attributes['endDate']);
|
$date2 = Carbon::createFromFormat('Ymd', $attributes['endDate']);
|
||||||
if (null === $date2) {
|
if (null === $date2) {
|
||||||
$date2 = today(config('app.timezone'));
|
$date2 = today(config('app.timezone'));
|
||||||
}
|
}
|
||||||
$date2->endOfDay();
|
$date2->endOfDay();
|
||||||
$attributes['endDate'] = $date2;
|
$attributes['endDate'] = $date2;
|
||||||
|
|
||||||
return $attributes;
|
return $attributes;
|
||||||
}
|
}
|
||||||
@@ -170,7 +169,7 @@ trait RequestInformation
|
|||||||
*/
|
*/
|
||||||
final protected function validatePassword(User $user, string $current, string $new): bool // get request info
|
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'));
|
throw new ValidationException((string) trans('firefly.invalid_current_password'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,7 +28,6 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait RuleManagement
|
* Trait RuleManagement
|
||||||
@@ -55,7 +54,7 @@ trait RuleManagement
|
|||||||
'count' => $index + 1,
|
'count' => $index + 1,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->error(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
|
app('log')->error(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
|
|
||||||
@@ -74,8 +73,8 @@ trait RuleManagement
|
|||||||
protected function getPreviousTriggers(Request $request): array
|
protected function getPreviousTriggers(Request $request): array
|
||||||
{
|
{
|
||||||
// TODO duplicated code.
|
// TODO duplicated code.
|
||||||
$operators = config('search.operators');
|
$operators = config('search.operators');
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
foreach ($operators as $key => $operator) {
|
foreach ($operators as $key => $operator) {
|
||||||
if ('user_action' !== $key && false === $operator['alias']) {
|
if ('user_action' !== $key && false === $operator['alias']) {
|
||||||
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||||
@@ -100,7 +99,7 @@ trait RuleManagement
|
|||||||
'triggers' => $triggers,
|
'triggers' => $triggers,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
|
|
||||||
@@ -129,7 +128,7 @@ trait RuleManagement
|
|||||||
}
|
}
|
||||||
asort($triggers);
|
asort($triggers);
|
||||||
|
|
||||||
$index = 0;
|
$index = 0;
|
||||||
foreach ($submittedOperators as $operator) {
|
foreach ($submittedOperators as $operator) {
|
||||||
$rootOperator = OperatorQuerySearch::getRootOperator($operator['type']);
|
$rootOperator = OperatorQuerySearch::getRootOperator($operator['type']);
|
||||||
$needsContext = (bool) config(sprintf('search.operators.%s.needs_context', $rootOperator));
|
$needsContext = (bool) config(sprintf('search.operators.%s.needs_context', $rootOperator));
|
||||||
@@ -146,7 +145,7 @@ trait RuleManagement
|
|||||||
'triggers' => $triggers,
|
'triggers' => $triggers,
|
||||||
]
|
]
|
||||||
)->render();
|
)->render();
|
||||||
} catch (Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
app('log')->debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
app('log')->debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
|
|
||||||
|
@@ -39,14 +39,15 @@ trait TransactionCalculation
|
|||||||
*/
|
*/
|
||||||
protected function getExpensesForOpposing(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): array
|
protected function getExpensesForOpposing(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$total = $accounts->merge($opposing);
|
$total = $accounts->merge($opposing);
|
||||||
|
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts($total)
|
$collector->setAccounts($total)
|
||||||
->setRange($start, $end)
|
->setRange($start, $end)
|
||||||
->withAccountInformation()
|
->withAccountInformation()
|
||||||
->setTypes([TransactionType::WITHDRAWAL]);
|
->setTypes([TransactionType::WITHDRAWAL])
|
||||||
|
;
|
||||||
|
|
||||||
return $collector->getExtractedJournals();
|
return $collector->getExtractedJournals();
|
||||||
}
|
}
|
||||||
@@ -60,7 +61,8 @@ trait TransactionCalculation
|
|||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
|
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||||
->setTags($tags)->withAccountInformation();
|
->setTags($tags)->withAccountInformation()
|
||||||
|
;
|
||||||
|
|
||||||
return $collector->getExtractedJournals();
|
return $collector->getExtractedJournals();
|
||||||
}
|
}
|
||||||
@@ -73,7 +75,8 @@ trait TransactionCalculation
|
|||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||||
->setBudgets($budgets)->withAccountInformation();
|
->setBudgets($budgets)->withAccountInformation()
|
||||||
|
;
|
||||||
|
|
||||||
return $collector->getExtractedJournals();
|
return $collector->getExtractedJournals();
|
||||||
}
|
}
|
||||||
@@ -90,7 +93,8 @@ trait TransactionCalculation
|
|||||||
->setRange($start, $end)
|
->setRange($start, $end)
|
||||||
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||||
->setCategories($categories)
|
->setCategories($categories)
|
||||||
->withAccountInformation();
|
->withAccountInformation()
|
||||||
|
;
|
||||||
|
|
||||||
return $collector->getExtractedJournals();
|
return $collector->getExtractedJournals();
|
||||||
}
|
}
|
||||||
@@ -103,7 +107,8 @@ trait TransactionCalculation
|
|||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||||
->setCategories($categories)->withAccountInformation();
|
->setCategories($categories)->withAccountInformation()
|
||||||
|
;
|
||||||
|
|
||||||
return $collector->getExtractedJournals();
|
return $collector->getExtractedJournals();
|
||||||
}
|
}
|
||||||
@@ -113,7 +118,7 @@ trait TransactionCalculation
|
|||||||
*/
|
*/
|
||||||
protected function getIncomeForOpposing(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): array
|
protected function getIncomeForOpposing(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$total = $accounts->merge($opposing);
|
$total = $accounts->merge($opposing);
|
||||||
|
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
@@ -130,7 +135,8 @@ trait TransactionCalculation
|
|||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||||
->setTags($tags)->withAccountInformation();
|
->setTags($tags)->withAccountInformation()
|
||||||
|
;
|
||||||
|
|
||||||
return $collector->getExtractedJournals();
|
return $collector->getExtractedJournals();
|
||||||
}
|
}
|
||||||
|
@@ -69,7 +69,7 @@ trait UserNavigation
|
|||||||
final protected function isEditableGroup(TransactionGroup $group): bool
|
final protected function isEditableGroup(TransactionGroup $group): bool
|
||||||
{
|
{
|
||||||
/** @var null|TransactionJournal $journal */
|
/** @var null|TransactionJournal $journal */
|
||||||
$journal = $group->transactionJournals()->first();
|
$journal = $group->transactionJournals()->first();
|
||||||
if (null === $journal) {
|
if (null === $journal) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -96,10 +96,10 @@ trait UserNavigation
|
|||||||
|
|
||||||
return redirect(route('index'));
|
return redirect(route('index'));
|
||||||
}
|
}
|
||||||
$journal = $transaction->transactionJournal;
|
$journal = $transaction->transactionJournal;
|
||||||
|
|
||||||
/** @var null|Transaction $other */
|
/** @var null|Transaction $other */
|
||||||
$other = $journal->transactions()->where('id', '!=', $transaction->id)->first();
|
$other = $journal->transactions()->where('id', '!=', $transaction->id)->first();
|
||||||
if (null === $other) {
|
if (null === $other) {
|
||||||
app('log')->error(sprintf('Account #%d has no valid journals. Dont know where it belongs.', $account->id));
|
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'));
|
session()->flash('error', trans('firefly.cant_find_redirect_account'));
|
||||||
@@ -119,7 +119,7 @@ trait UserNavigation
|
|||||||
final protected function redirectGroupToAccount(TransactionGroup $group)
|
final protected function redirectGroupToAccount(TransactionGroup $group)
|
||||||
{
|
{
|
||||||
/** @var null|TransactionJournal $journal */
|
/** @var null|TransactionJournal $journal */
|
||||||
$journal = $group->transactionJournals()->first();
|
$journal = $group->transactionJournals()->first();
|
||||||
if (null === $journal) {
|
if (null === $journal) {
|
||||||
app('log')->error(sprintf('No journals in group #%d', $group->id));
|
app('log')->error(sprintf('No journals in group #%d', $group->id));
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@ trait UserGroupDetectable
|
|||||||
public function detectUserGroup(): ?UserGroup
|
public function detectUserGroup(): ?UserGroup
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
app('log')->debug('Now in detectUserGroup()');
|
app('log')->debug('Now in detectUserGroup()');
|
||||||
|
|
||||||
/** @var null|UserGroup $userGroup */
|
/** @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));
|
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;
|
$userGroupId = (int) $user->user_group_id;
|
||||||
}
|
}
|
||||||
$userGroup = UserGroup::find($userGroupId);
|
$userGroup = UserGroup::find($userGroupId);
|
||||||
if (null === $userGroup) {
|
if (null === $userGroup) {
|
||||||
app('log')->error(sprintf('Request class has user_group_id (#%d), but group does not exist.', $userGroupId));
|
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;
|
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\ObjectGroup;
|
use FireflyIII\Models\ObjectGroup;
|
||||||
@@ -37,8 +36,6 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
|||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Override;
|
|
||||||
use stdClass;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AccountEnrichment
|
* Class AccountEnrichment
|
||||||
@@ -66,7 +63,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
$this->end = null;
|
$this->end = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Override]
|
#[\Override]
|
||||||
public function enrichSingle(Model $model): Account
|
public function enrichSingle(Model $model): Account
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
@@ -76,7 +73,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
return $collection->first();
|
return $collection->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Override]
|
#[\Override]
|
||||||
/**
|
/**
|
||||||
* Do the actual enrichment.
|
* 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']);
|
$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();
|
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
|
||||||
|
|
||||||
$currencies = [];
|
$currencies = [];
|
||||||
foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) {
|
foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) {
|
||||||
$id = $currency->id;
|
$id = $currency->id;
|
||||||
$currencies[$id] = $currency;
|
$currencies[$id] = $currency;
|
||||||
@@ -177,8 +174,8 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
$default = $this->default;
|
$default = $this->default;
|
||||||
|
|
||||||
// get start and end, so the balance difference can be generated.
|
// get start and end, so the balance difference can be generated.
|
||||||
$start = null;
|
$start = null;
|
||||||
$end = null;
|
$end = null;
|
||||||
if (null !== $this->start) {
|
if (null !== $this->start) {
|
||||||
$start = Balance::getAccountBalances($this->collection, $this->start);
|
$start = Balance::getAccountBalances($this->collection, $this->start);
|
||||||
}
|
}
|
||||||
@@ -200,7 +197,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
'balance_difference' => null,
|
'balance_difference' => null,
|
||||||
];
|
];
|
||||||
if (array_key_exists($account->id, $balances)) {
|
if (array_key_exists($account->id, $balances)) {
|
||||||
$set = [];
|
$set = [];
|
||||||
foreach ($balances[$account->id] as $currencyId => $entry) {
|
foreach ($balances[$account->id] as $currencyId => $entry) {
|
||||||
$left = $start[$account->id][$currencyId]['balance'] ?? null;
|
$left = $start[$account->id][$currencyId]['balance'] ?? null;
|
||||||
$right = $end[$account->id][$currencyId]['balance'] ?? null;
|
$right = $end[$account->id][$currencyId]['balance'] ?? null;
|
||||||
@@ -242,11 +239,12 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function getObjectGroups(): void
|
private function getObjectGroups(): void
|
||||||
{
|
{
|
||||||
$set = DB::table('object_groupables')
|
$set = \DB::table('object_groupables')
|
||||||
->where('object_groupable_type', Account::class)
|
->where('object_groupable_type', Account::class)
|
||||||
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
|
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
|
||||||
->distinct()
|
->distinct()
|
||||||
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id']);
|
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id'])
|
||||||
|
;
|
||||||
// get the groups:
|
// get the groups:
|
||||||
$groupIds = $set->pluck('object_group_id')->toArray();
|
$groupIds = $set->pluck('object_group_id')->toArray();
|
||||||
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
|
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
|
||||||
@@ -256,7 +254,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
$this->objectGroups[$group->id] = $group;
|
$this->objectGroups[$group->id] = $group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var stdClass $entry */
|
/** @var \stdClass $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$this->grouped[(int) $entry->object_groupable_id] = (int) $entry->object_group_id;
|
$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];
|
$config = config('api.valid_api_filters')[$class];
|
||||||
$parsed = [];
|
$parsed = [];
|
||||||
foreach ($filters->all() as $filter) {
|
foreach ($filters->all() as $filter) {
|
||||||
$key = $filter->key();
|
$key = $filter->key();
|
||||||
if (!in_array($key, $config, true)) {
|
if (!in_array($key, $config, true)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -39,8 +39,8 @@ trait FiltersPagination
|
|||||||
$pagination['number'] = min(65536, max($pagination['number'], 1));
|
$pagination['number'] = min(65536, max($pagination['number'], 1));
|
||||||
|
|
||||||
// clean up page size
|
// clean up page size
|
||||||
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
|
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
|
||||||
$pagination['size'] = min(1337, max($pagination['size'], 1));
|
$pagination['size'] = min(1337, max($pagination['size'], 1));
|
||||||
|
|
||||||
return $pagination;
|
return $pagination;
|
||||||
}
|
}
|
||||||
|
@@ -71,14 +71,15 @@ class AccountBalanceCalculator
|
|||||||
$balances = [];
|
$balances = [];
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->whereNull('transactions.deleted_at')
|
->whereNull('transactions.deleted_at')
|
||||||
->whereNull('transaction_journals.deleted_at')
|
->whereNull('transaction_journals.deleted_at')
|
||||||
// this order is the same as GroupCollector, but in the exact reverse.
|
// this order is the same as GroupCollector, but in the exact reverse.
|
||||||
->orderBy('transaction_journals.date', 'asc')
|
->orderBy('transaction_journals.date', 'asc')
|
||||||
->orderBy('transaction_journals.order', 'desc')
|
->orderBy('transaction_journals.order', 'desc')
|
||||||
->orderBy('transaction_journals.id', 'asc')
|
->orderBy('transaction_journals.id', 'asc')
|
||||||
->orderBy('transaction_journals.description', 'asc')
|
->orderBy('transaction_journals.description', 'asc')
|
||||||
->orderBy('transactions.amount', 'asc');
|
->orderBy('transactions.amount', 'asc')
|
||||||
|
;
|
||||||
if ($accounts->count() > 0) {
|
if ($accounts->count() > 0) {
|
||||||
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ class AccountBalanceCalculator
|
|||||||
$query->where('transaction_journals.date', '>=', $notBefore);
|
$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.
|
// the balance value is an array.
|
||||||
// first entry is the balance, second is the date.
|
// 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];
|
$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 and after are easy:
|
||||||
$before = $balances[$entry->account_id][$entry->transaction_currency_id][0];
|
$before = $balances[$entry->account_id][$entry->transaction_currency_id][0];
|
||||||
$after = bcadd($before, $entry->amount);
|
$after = bcadd($before, $entry->amount);
|
||||||
if (true === $entry->balance_dirty || $accounts->count() > 0) {
|
if (true === $entry->balance_dirty || $accounts->count() > 0) {
|
||||||
// update the transaction:
|
// update the transaction:
|
||||||
$entry->balance_before = $before;
|
$entry->balance_before = $before;
|
||||||
@@ -126,17 +127,18 @@ class AccountBalanceCalculator
|
|||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d')));
|
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')
|
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->whereNull('transactions.deleted_at')
|
->whereNull('transactions.deleted_at')
|
||||||
->where('transaction_journals.transaction_currency_id', $currencyId)
|
->where('transaction_journals.transaction_currency_id', $currencyId)
|
||||||
->whereNull('transaction_journals.deleted_at')
|
->whereNull('transaction_journals.deleted_at')
|
||||||
// this order is the same as GroupCollector
|
// this order is the same as GroupCollector
|
||||||
->orderBy('transaction_journals.date', 'DESC')
|
->orderBy('transaction_journals.date', 'DESC')
|
||||||
->orderBy('transaction_journals.order', 'ASC')
|
->orderBy('transaction_journals.order', 'ASC')
|
||||||
->orderBy('transaction_journals.id', 'DESC')
|
->orderBy('transaction_journals.id', 'DESC')
|
||||||
->orderBy('transaction_journals.description', 'DESC')
|
->orderBy('transaction_journals.description', 'DESC')
|
||||||
->orderBy('transactions.amount', 'DESC')
|
->orderBy('transactions.amount', 'DESC')
|
||||||
->where('transactions.account_id', $accountId);
|
->where('transactions.account_id', $accountId)
|
||||||
|
;
|
||||||
$notBefore->startOfDay();
|
$notBefore->startOfDay();
|
||||||
$query->where('transaction_journals.date', '<', $notBefore);
|
$query->where('transaction_journals.date', '<', $notBefore);
|
||||||
|
|
||||||
@@ -168,7 +170,7 @@ class AccountBalanceCalculator
|
|||||||
*/
|
*/
|
||||||
foreach ($currencies as $currencyId => $balance) {
|
foreach ($currencies as $currencyId => $balance) {
|
||||||
/** @var TransactionCurrency $currency */
|
/** @var TransactionCurrency $currency */
|
||||||
$currency = TransactionCurrency::find($currencyId);
|
$currency = TransactionCurrency::find($currencyId);
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
Log::error(sprintf('Could not find currency #%d, will not save account balance.', $currencyId));
|
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
|
public static function recalculateForJournal(TransactionJournal $transactionJournal): void
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$object = new self();
|
$object = new self();
|
||||||
|
|
||||||
// recalculate the involved accounts:
|
// recalculate the involved accounts:
|
||||||
$accounts = new Collection();
|
$accounts = new Collection();
|
||||||
@@ -208,9 +210,9 @@ class AccountBalanceCalculator
|
|||||||
|
|
||||||
private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance
|
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) {
|
if (null !== $entry) {
|
||||||
// Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
|
// 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
|
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) {
|
if (null !== $entry) {
|
||||||
return $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('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')));
|
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));
|
Log::debug(sprintf('For bill start, days until end of month is %d', $daysUntilEOM));
|
||||||
|
|
||||||
$set = new Collection();
|
$set = new Collection();
|
||||||
$currentStart = clone $earliest;
|
$currentStart = clone $earliest;
|
||||||
|
|
||||||
// 2023-06-23 subDay to fix 7655
|
// 2023-06-23 subDay to fix 7655
|
||||||
$currentStart->subDay();
|
$currentStart->subDay();
|
||||||
$loop = 0;
|
$loop = 0;
|
||||||
|
|
||||||
Log::debug('Start of loop');
|
Log::debug('Start of loop');
|
||||||
while ($currentStart <= $latest) {
|
while ($currentStart <= $latest) {
|
||||||
@@ -107,7 +107,7 @@ class BillDateCalculator
|
|||||||
// for the next loop, go to end of period, THEN add day.
|
// for the next loop, go to end of period, THEN add day.
|
||||||
Log::debug('Add one day to nextExpectedMatch/currentStart.');
|
Log::debug('Add one day to nextExpectedMatch/currentStart.');
|
||||||
$nextExpectedMatch->addDay();
|
$nextExpectedMatch->addDay();
|
||||||
$currentStart = clone $nextExpectedMatch;
|
$currentStart = clone $nextExpectedMatch;
|
||||||
|
|
||||||
++$loop;
|
++$loop;
|
||||||
if ($loop > 12) {
|
if ($loop > 12) {
|
||||||
@@ -117,7 +117,7 @@ class BillDateCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log::debug('end of loop');
|
Log::debug('end of loop');
|
||||||
$simple = $set->map(
|
$simple = $set->map(
|
||||||
static function (Carbon $date) {
|
static function (Carbon $date) {
|
||||||
return $date->format('Y-m-d');
|
return $date->format('Y-m-d');
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ class BillDateCalculator
|
|||||||
return $billStartDate;
|
return $billStartDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
$steps = app('navigation')->diffInPeriods($period, $skip, $earliest, $billStartDate);
|
$steps = app('navigation')->diffInPeriods($period, $skip, $earliest, $billStartDate);
|
||||||
if ($steps === $this->diffInMonths) {
|
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));
|
Log::debug(sprintf('Steps is %d, which is the same as diffInMonths (%d), so we add another 1.', $steps, $this->diffInMonths));
|
||||||
++$steps;
|
++$steps;
|
||||||
|
@@ -39,7 +39,7 @@ trait ReturnsIntegerIdTrait
|
|||||||
protected function id(): Attribute
|
protected function id(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
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
|
protected function userGroupId(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
get: static fn($value) => (int) $value,
|
get: static fn ($value) => (int) $value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function userId(): Attribute
|
protected function userId(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::make(
|
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\Calculator;
|
||||||
use FireflyIII\Support\Calendar\Periodicity;
|
use FireflyIII\Support\Calendar\Periodicity;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Navigation.
|
* Class Navigation.
|
||||||
@@ -77,10 +76,10 @@ class Navigation
|
|||||||
|
|
||||||
if (!array_key_exists($repeatFreq, $functionMap)) {
|
if (!array_key_exists($repeatFreq, $functionMap)) {
|
||||||
Log::error(sprintf(
|
Log::error(sprintf(
|
||||||
'The periodicity %s is unknown. Choose one of available periodicity: %s',
|
'The periodicity %s is unknown. Choose one of available periodicity: %s',
|
||||||
$repeatFreq,
|
$repeatFreq,
|
||||||
implode(', ', array_keys($functionMap))
|
implode(', ', array_keys($functionMap))
|
||||||
));
|
));
|
||||||
|
|
||||||
return $theDate;
|
return $theDate;
|
||||||
}
|
}
|
||||||
@@ -94,7 +93,7 @@ class Navigation
|
|||||||
return $this->calculator->nextDateByInterval($epoch, $periodicity, $skipInterval);
|
return $this->calculator->nextDateByInterval($epoch, $periodicity, $skipInterval);
|
||||||
} catch (IntervalException $exception) {
|
} catch (IntervalException $exception) {
|
||||||
Log::warning($exception->getMessage(), ['exception' => $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]);
|
Log::error($exception->getMessage(), ['exception' => $exception]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +110,7 @@ class Navigation
|
|||||||
if ($end < $start) {
|
if ($end < $start) {
|
||||||
[$start, $end] = [$end, $start];
|
[$start, $end] = [$end, $start];
|
||||||
}
|
}
|
||||||
$periods = [];
|
$periods = [];
|
||||||
// first, 13 periods of [range]
|
// first, 13 periods of [range]
|
||||||
$loopCount = 0;
|
$loopCount = 0;
|
||||||
$loopDate = clone $end;
|
$loopDate = clone $end;
|
||||||
@@ -161,9 +160,9 @@ class Navigation
|
|||||||
|
|
||||||
public function startOfPeriod(Carbon $theDate, string $repeatFreq): Carbon
|
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));
|
// Log::debug(sprintf('Now in startOfPeriod("%s", "%s")', $date->toIso8601String(), $repeatFreq));
|
||||||
$functionMap = [
|
$functionMap = [
|
||||||
'1D' => 'startOfDay',
|
'1D' => 'startOfDay',
|
||||||
'daily' => 'startOfDay',
|
'daily' => 'startOfDay',
|
||||||
'1W' => 'startOfWeek',
|
'1W' => 'startOfWeek',
|
||||||
@@ -210,7 +209,7 @@ class Navigation
|
|||||||
return $date;
|
return $date;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = match ($repeatFreq) {
|
$result = match ($repeatFreq) {
|
||||||
'last7' => $date->subDays(7)->startOfDay(),
|
'last7' => $date->subDays(7)->startOfDay(),
|
||||||
'last30' => $date->subDays(30)->startOfDay(),
|
'last30' => $date->subDays(30)->startOfDay(),
|
||||||
'last90' => $date->subDays(90)->startOfDay(),
|
'last90' => $date->subDays(90)->startOfDay(),
|
||||||
@@ -238,7 +237,7 @@ class Navigation
|
|||||||
|
|
||||||
public function endOfPeriod(Carbon $end, string $repeatFreq): Carbon
|
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));
|
// Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq));
|
||||||
|
|
||||||
$functionMap = [
|
$functionMap = [
|
||||||
@@ -272,7 +271,7 @@ class Navigation
|
|||||||
Log::debug('Session data available.');
|
Log::debug('Session data available.');
|
||||||
|
|
||||||
/** @var Carbon $tStart */
|
/** @var Carbon $tStart */
|
||||||
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
||||||
|
|
||||||
/** @var Carbon $tEnd */
|
/** @var Carbon $tEnd */
|
||||||
$tEnd = session('end', today(config('app.timezone'))->endOfMonth());
|
$tEnd = session('end', today(config('app.timezone'))->endOfMonth());
|
||||||
@@ -292,7 +291,7 @@ class Navigation
|
|||||||
return $end->endOfMonth();
|
return $end->endOfMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = match ($repeatFreq) {
|
$result = match ($repeatFreq) {
|
||||||
'last7' => $currentEnd->addDays(7)->startOfDay(),
|
'last7' => $currentEnd->addDays(7)->startOfDay(),
|
||||||
'last30' => $currentEnd->addDays(30)->startOfDay(),
|
'last30' => $currentEnd->addDays(30)->startOfDay(),
|
||||||
'last90' => $currentEnd->addDays(90)->startOfDay(),
|
'last90' => $currentEnd->addDays(90)->startOfDay(),
|
||||||
@@ -312,7 +311,7 @@ class Navigation
|
|||||||
|
|
||||||
return $end;
|
return $end;
|
||||||
}
|
}
|
||||||
$function = $functionMap[$repeatFreq];
|
$function = $functionMap[$repeatFreq];
|
||||||
|
|
||||||
if (array_key_exists($repeatFreq, $modifierMap)) {
|
if (array_key_exists($repeatFreq, $modifierMap)) {
|
||||||
$currentEnd->{$function}($modifierMap[$repeatFreq]); // @phpstan-ignore-line
|
$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
|
public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int
|
||||||
{
|
{
|
||||||
Log::debug(sprintf(
|
Log::debug(sprintf(
|
||||||
'diffInPeriods: %s (skip: %d), between %s and %s.',
|
'diffInPeriods: %s (skip: %d), between %s and %s.',
|
||||||
$period,
|
$period,
|
||||||
$skip,
|
$skip,
|
||||||
$beginning->format('Y-m-d'),
|
$beginning->format('Y-m-d'),
|
||||||
$end->format('Y-m-d')
|
$end->format('Y-m-d')
|
||||||
));
|
));
|
||||||
$map = [
|
$map = [
|
||||||
'daily' => 'diffInDays',
|
'daily' => 'diffInDays',
|
||||||
'weekly' => 'diffInWeeks',
|
'weekly' => 'diffInWeeks',
|
||||||
'monthly' => 'diffInMonths',
|
'monthly' => 'diffInMonths',
|
||||||
@@ -362,7 +361,7 @@ class Navigation
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
$func = $map[$period];
|
$func = $map[$period];
|
||||||
// first do the diff
|
// first do the diff
|
||||||
$floatDiff = $beginning->{$func}($end, true); // @phpstan-ignore-line
|
$floatDiff = $beginning->{$func}($end, true); // @phpstan-ignore-line
|
||||||
|
|
||||||
@@ -377,7 +376,7 @@ class Navigation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then do ceil()
|
// then do ceil()
|
||||||
$diff = ceil($floatDiff);
|
$diff = ceil($floatDiff);
|
||||||
|
|
||||||
Log::debug(sprintf('Diff is %f periods (%d rounded up)', $floatDiff, $diff));
|
Log::debug(sprintf('Diff is %f periods (%d rounded up)', $floatDiff, $diff));
|
||||||
|
|
||||||
@@ -385,11 +384,11 @@ class Navigation
|
|||||||
$parameter = $skip + 1;
|
$parameter = $skip + 1;
|
||||||
$diff = ceil($diff / $parameter) * $parameter;
|
$diff = ceil($diff / $parameter) * $parameter;
|
||||||
Log::debug(sprintf(
|
Log::debug(sprintf(
|
||||||
'diffInPeriods: skip is %d, so param is %d, and diff becomes %d',
|
'diffInPeriods: skip is %d, so param is %d, and diff becomes %d',
|
||||||
$skip,
|
$skip,
|
||||||
$parameter,
|
$parameter,
|
||||||
$diff
|
$diff
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int) $diff;
|
return (int) $diff;
|
||||||
@@ -414,7 +413,7 @@ class Navigation
|
|||||||
'yearly' => 'endOfYear',
|
'yearly' => 'endOfYear',
|
||||||
];
|
];
|
||||||
|
|
||||||
$currentEnd = clone $theCurrentEnd;
|
$currentEnd = clone $theCurrentEnd;
|
||||||
|
|
||||||
if (array_key_exists($repeatFreq, $functionMap)) {
|
if (array_key_exists($repeatFreq, $functionMap)) {
|
||||||
$function = $functionMap[$repeatFreq];
|
$function = $functionMap[$repeatFreq];
|
||||||
@@ -469,7 +468,7 @@ class Navigation
|
|||||||
*/
|
*/
|
||||||
public function listOfPeriods(Carbon $start, Carbon $end): array
|
public function listOfPeriods(Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
// define period to increment
|
// define period to increment
|
||||||
$increment = 'addDay';
|
$increment = 'addDay';
|
||||||
$format = $this->preferredCarbonFormat($start, $end);
|
$format = $this->preferredCarbonFormat($start, $end);
|
||||||
@@ -486,8 +485,8 @@ class Navigation
|
|||||||
$increment = 'addYear';
|
$increment = 'addYear';
|
||||||
$displayFormat = (string) trans('config.year_js');
|
$displayFormat = (string) trans('config.year_js');
|
||||||
}
|
}
|
||||||
$begin = clone $start;
|
$begin = clone $start;
|
||||||
$entries = [];
|
$entries = [];
|
||||||
while ($begin < $end) {
|
while ($begin < $end) {
|
||||||
$formatted = $begin->format($format);
|
$formatted = $begin->format($format);
|
||||||
$displayed = $begin->isoFormat($displayFormat);
|
$displayed = $begin->isoFormat($displayFormat);
|
||||||
@@ -649,7 +648,7 @@ class Navigation
|
|||||||
public function subtractPeriod(Carbon $theDate, string $repeatFreq, ?int $subtract = null): Carbon
|
public function subtractPeriod(Carbon $theDate, string $repeatFreq, ?int $subtract = null): Carbon
|
||||||
{
|
{
|
||||||
$subtract ??= 1;
|
$subtract ??= 1;
|
||||||
$date = clone $theDate;
|
$date = clone $theDate;
|
||||||
// 1D 1W 1M 3M 6M 1Y
|
// 1D 1W 1M 3M 6M 1Y
|
||||||
$functionMap = [
|
$functionMap = [
|
||||||
'1D' => 'subDays',
|
'1D' => 'subDays',
|
||||||
@@ -688,7 +687,7 @@ class Navigation
|
|||||||
// this is then subtracted from $theDate (* $subtract).
|
// this is then subtracted from $theDate (* $subtract).
|
||||||
if ('custom' === $repeatFreq) {
|
if ('custom' === $repeatFreq) {
|
||||||
/** @var Carbon $tStart */
|
/** @var Carbon $tStart */
|
||||||
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
$tStart = session('start', today(config('app.timezone'))->startOfMonth());
|
||||||
|
|
||||||
/** @var Carbon $tEnd */
|
/** @var Carbon $tEnd */
|
||||||
$tEnd = session('end', today(config('app.timezone'))->endOfMonth());
|
$tEnd = session('end', today(config('app.timezone'))->endOfMonth());
|
||||||
@@ -782,7 +781,7 @@ class Navigation
|
|||||||
|
|
||||||
return $fiscalHelper->endOfFiscalYear($end);
|
return $fiscalHelper->endOfFiscalYear($end);
|
||||||
}
|
}
|
||||||
$list = [
|
$list = [
|
||||||
'last7',
|
'last7',
|
||||||
'last30',
|
'last30',
|
||||||
'last90',
|
'last90',
|
||||||
|
@@ -24,12 +24,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support;
|
namespace FireflyIII\Support;
|
||||||
|
|
||||||
use ArrayObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class NullArrayObject
|
* Class NullArrayObject
|
||||||
*/
|
*/
|
||||||
class NullArrayObject extends ArrayObject
|
class NullArrayObject extends \ArrayObject
|
||||||
{
|
{
|
||||||
/** @var null|mixed */
|
/** @var null|mixed */
|
||||||
public $default;
|
public $default;
|
||||||
|
@@ -77,15 +77,15 @@ class ParseDateString
|
|||||||
public function parseDate(string $date): Carbon
|
public function parseDate(string $date): Carbon
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('parseDate("%s")', $date));
|
app('log')->debug(sprintf('parseDate("%s")', $date));
|
||||||
$date = strtolower($date);
|
$date = strtolower($date);
|
||||||
// parse keywords:
|
// parse keywords:
|
||||||
if (in_array($date, $this->keywords, true)) {
|
if (in_array($date, $this->keywords, true)) {
|
||||||
return $this->parseKeyword($date);
|
return $this->parseKeyword($date);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if regex for YYYY-MM-DD:
|
// if regex for YYYY-MM-DD:
|
||||||
$pattern = '/^(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])$/';
|
$pattern = '/^(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])$/';
|
||||||
$result = preg_match($pattern, $date);
|
$result = preg_match($pattern, $date);
|
||||||
if (false !== $result && 0 !== $result) {
|
if (false !== $result && 0 !== $result) {
|
||||||
return $this->parseDefaultDate($date);
|
return $this->parseDefaultDate($date);
|
||||||
}
|
}
|
||||||
@@ -178,11 +178,11 @@ class ParseDateString
|
|||||||
|
|
||||||
foreach ($parts as $part) {
|
foreach ($parts as $part) {
|
||||||
app('log')->debug(sprintf('Now parsing part "%s"', $part));
|
app('log')->debug(sprintf('Now parsing part "%s"', $part));
|
||||||
$part = trim($part);
|
$part = trim($part);
|
||||||
|
|
||||||
// verify if correct
|
// verify if correct
|
||||||
$pattern = '/[+-]\d+[wqmdy]/';
|
$pattern = '/[+-]\d+[wqmdy]/';
|
||||||
$result = preg_match($pattern, $part);
|
$result = preg_match($pattern, $part);
|
||||||
if (0 === $result || false === $result) {
|
if (0 === $result || false === $result) {
|
||||||
app('log')->error(sprintf('Part "%s" does not match regular expression. Will be skipped.', $part));
|
app('log')->error(sprintf('Part "%s" does not match regular expression. Will be skipped.', $part));
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ class ParseDateString
|
|||||||
|
|
||||||
continue;
|
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')));
|
app('log')->debug(sprintf('Will now do %s(%d) on %s', $func, $number, $today->format('Y-m-d')));
|
||||||
$today->{$func}($number); // @phpstan-ignore-line
|
$today->{$func}($number); // @phpstan-ignore-line
|
||||||
app('log')->debug(sprintf('Resulting date is %s', $today->format('Y-m-d')));
|
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)
|
return Preference::where('user_id', $user->id)
|
||||||
->where('name', '!=', 'currencyPreference')
|
->where('name', '!=', 'currencyPreference')
|
||||||
->where(function (Builder $q) use ($user): void {
|
->where(function (Builder $q) use ($user): void {
|
||||||
$q->whereNull('user_group_id');
|
$q->whereNull('user_group_id');
|
||||||
$q->orWhere('user_group_id', $user->user_group_id);
|
$q->orWhere('user_group_id', $user->user_group_id);
|
||||||
})
|
})
|
||||||
->get();
|
->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 */
|
/** @var null|User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
@@ -69,7 +70,7 @@ class Preferences
|
|||||||
return $this->getForUser($user, $name, $default);
|
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.
|
// don't care about user group ID, except for some specific preferences.
|
||||||
$userGroupId = $this->getUserGroupId($user, $name);
|
$userGroupId = $this->getUserGroupId($user, $name);
|
||||||
@@ -121,16 +122,16 @@ class Preferences
|
|||||||
Cache::put($key, '', 5);
|
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);
|
$fullName = sprintf('preference%s%s', $user->id, $name);
|
||||||
$groupId = $this->getUserGroupId($user, $name);
|
$groupId = $this->getUserGroupId($user, $name);
|
||||||
$groupId = 0 === (int) $groupId ? null : (int) $groupId;
|
$groupId = 0 === (int) $groupId ? null : (int) $groupId;
|
||||||
|
|
||||||
Cache::forget($fullName);
|
Cache::forget($fullName);
|
||||||
|
|
||||||
/** @var null|Preference $pref */
|
/** @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) {
|
if (null !== $pref && null === $value) {
|
||||||
$pref->delete();
|
$pref->delete();
|
||||||
@@ -173,12 +174,13 @@ class Preferences
|
|||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
$preferences = Preference::where('user_id', $user->id)
|
$preferences = Preference::where('user_id', $user->id)
|
||||||
->where(function (Builder $q) use ($user): void {
|
->where(function (Builder $q) use ($user): void {
|
||||||
$q->whereNull('user_group_id');
|
$q->whereNull('user_group_id');
|
||||||
$q->orWhere('user_group_id', $user->user_group_id);
|
$q->orWhere('user_group_id', $user->user_group_id);
|
||||||
})
|
})
|
||||||
->whereIn('name', $list)
|
->whereIn('name', $list)
|
||||||
->get(['id', 'name', 'data']);
|
->get(['id', 'name', 'data'])
|
||||||
|
;
|
||||||
|
|
||||||
/** @var Preference $preference */
|
/** @var Preference $preference */
|
||||||
foreach ($preferences as $preference) {
|
foreach ($preferences as $preference) {
|
||||||
@@ -216,7 +218,7 @@ class Preferences
|
|||||||
return $result;
|
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);
|
$result = $this->getForUser($user, $name, $default);
|
||||||
if ('' === $result->data) {
|
if ('' === $result->data) {
|
||||||
@@ -237,7 +239,7 @@ class Preferences
|
|||||||
return $result;
|
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 */
|
/** @var null|User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
@@ -275,7 +277,7 @@ class Preferences
|
|||||||
Session::forget('first');
|
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 */
|
/** @var null|User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
@@ -76,7 +76,7 @@ class BudgetReportGenerator
|
|||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($this->accounts as $account) {
|
foreach ($this->accounts as $account) {
|
||||||
$accountId = $account->id;
|
$accountId = $account->id;
|
||||||
$this->report[$accountId] ??= [
|
$this->report[$accountId] ??= [
|
||||||
'name' => $account->name,
|
'name' => $account->name,
|
||||||
'id' => $account->id,
|
'id' => $account->id,
|
||||||
@@ -113,18 +113,18 @@ class BudgetReportGenerator
|
|||||||
|
|
||||||
$this->report[$sourceAccountId]['currencies'][$currencyId]
|
$this->report[$sourceAccountId]['currencies'][$currencyId]
|
||||||
??= [
|
??= [
|
||||||
'currency_id' => $expenses['currency_id'],
|
'currency_id' => $expenses['currency_id'],
|
||||||
'currency_symbol' => $expenses['currency_symbol'],
|
'currency_symbol' => $expenses['currency_symbol'],
|
||||||
'currency_name' => $expenses['currency_name'],
|
'currency_name' => $expenses['currency_name'],
|
||||||
'currency_decimal_places' => $expenses['currency_decimal_places'],
|
'currency_decimal_places' => $expenses['currency_decimal_places'],
|
||||||
'budgets' => [],
|
'budgets' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId]
|
$this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId]
|
||||||
??= '0';
|
??= '0';
|
||||||
|
|
||||||
$this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId]
|
$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
|
private function processBudget(Budget $budget): void
|
||||||
{
|
{
|
||||||
$budgetId = $budget->id;
|
$budgetId = $budget->id;
|
||||||
$this->report['budgets'][$budgetId] ??= [
|
$this->report['budgets'][$budgetId] ??= [
|
||||||
'budget_id' => $budgetId,
|
'budget_id' => $budgetId,
|
||||||
'budget_name' => $budget->name,
|
'budget_name' => $budget->name,
|
||||||
@@ -171,7 +171,7 @@ class BudgetReportGenerator
|
|||||||
];
|
];
|
||||||
|
|
||||||
// get all budget limits for budget in period:
|
// 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 */
|
/** @var BudgetLimit $limit */
|
||||||
foreach ($limits as $limit) {
|
foreach ($limits as $limit) {
|
||||||
@@ -184,14 +184,14 @@ class BudgetReportGenerator
|
|||||||
*/
|
*/
|
||||||
private function processLimit(Budget $budget, BudgetLimit $limit): void
|
private function processLimit(Budget $budget, BudgetLimit $limit): void
|
||||||
{
|
{
|
||||||
$budgetId = $budget->id;
|
$budgetId = $budget->id;
|
||||||
$limitId = $limit->id;
|
$limitId = $limit->id;
|
||||||
$limitCurrency = $limit->transactionCurrency ?? $this->currency;
|
$limitCurrency = $limit->transactionCurrency ?? $this->currency;
|
||||||
$currencyId = $limitCurrency->id;
|
$currencyId = $limitCurrency->id;
|
||||||
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget]));
|
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget]));
|
||||||
$spent = $expenses[$currencyId]['sum'] ?? '0';
|
$spent = $expenses[$currencyId]['sum'] ?? '0';
|
||||||
$left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent);
|
$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';
|
$overspent = 1 === bccomp(bcmul($spent, '-1'), $limit->amount) ? bcadd($spent, $limit->amount) : '0';
|
||||||
|
|
||||||
$this->report['budgets'][$budgetId]['budget_limits'][$limitId] ??= [
|
$this->report['budgets'][$budgetId]['budget_limits'][$limitId] ??= [
|
||||||
'budget_limit_id' => $limitId,
|
'budget_limit_id' => $limitId,
|
||||||
@@ -212,17 +212,17 @@ class BudgetReportGenerator
|
|||||||
|
|
||||||
// make sum information:
|
// make sum information:
|
||||||
$this->report['sums'][$currencyId]
|
$this->report['sums'][$currencyId]
|
||||||
??= [
|
??= [
|
||||||
'budgeted' => '0',
|
'budgeted' => '0',
|
||||||
'spent' => '0',
|
'spent' => '0',
|
||||||
'left' => '0',
|
'left' => '0',
|
||||||
'overspent' => '0',
|
'overspent' => '0',
|
||||||
'currency_id' => $currencyId,
|
'currency_id' => $currencyId,
|
||||||
'currency_code' => $limitCurrency->code,
|
'currency_code' => $limitCurrency->code,
|
||||||
'currency_name' => $limitCurrency->name,
|
'currency_name' => $limitCurrency->name,
|
||||||
'currency_symbol' => $limitCurrency->symbol,
|
'currency_symbol' => $limitCurrency->symbol,
|
||||||
'currency_decimal_places' => $limitCurrency->decimal_places,
|
'currency_decimal_places' => $limitCurrency->decimal_places,
|
||||||
];
|
];
|
||||||
$this->report['sums'][$currencyId]['budgeted'] = bcadd($this->report['sums'][$currencyId]['budgeted'], $limit->amount);
|
$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]['spent'] = bcadd($this->report['sums'][$currencyId]['spent'], $spent);
|
||||||
$this->report['sums'][$currencyId]['left'] = bcadd($this->report['sums'][$currencyId]['left'], bcadd($limit->amount, $spent));
|
$this->report['sums'][$currencyId]['left'] = bcadd($this->report['sums'][$currencyId]['left'], bcadd($limit->amount, $spent));
|
||||||
@@ -242,16 +242,16 @@ class BudgetReportGenerator
|
|||||||
'budget_limits' => [],
|
'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) {
|
foreach ($noBudget as $noBudgetEntry) {
|
||||||
// currency information:
|
// currency information:
|
||||||
$nbCurrencyId = (int) ($noBudgetEntry['currency_id'] ?? $this->currency->id);
|
$nbCurrencyId = (int) ($noBudgetEntry['currency_id'] ?? $this->currency->id);
|
||||||
$nbCurrencyCode = $noBudgetEntry['currency_code'] ?? $this->currency->code;
|
$nbCurrencyCode = $noBudgetEntry['currency_code'] ?? $this->currency->code;
|
||||||
$nbCurrencyName = $noBudgetEntry['currency_name'] ?? $this->currency->name;
|
$nbCurrencyName = $noBudgetEntry['currency_name'] ?? $this->currency->name;
|
||||||
$nbCurrencySymbol = $noBudgetEntry['currency_symbol'] ?? $this->currency->symbol;
|
$nbCurrencySymbol = $noBudgetEntry['currency_symbol'] ?? $this->currency->symbol;
|
||||||
$nbCurrencyDp = $noBudgetEntry['currency_decimal_places'] ?? $this->currency->decimal_places;
|
$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,
|
'budget_limit_id' => null,
|
||||||
'start_date' => $this->start,
|
'start_date' => $this->start,
|
||||||
'end_date' => $this->end,
|
'end_date' => $this->end,
|
||||||
@@ -267,7 +267,7 @@ class BudgetReportGenerator
|
|||||||
'currency_symbol' => $nbCurrencySymbol,
|
'currency_symbol' => $nbCurrencySymbol,
|
||||||
'currency_decimal_places' => $nbCurrencyDp,
|
'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:
|
// append currency info because it may be missing:
|
||||||
$this->report['sums'][$nbCurrencyId]['currency_id'] = $nbCurrencyId;
|
$this->report['sums'][$nbCurrencyId]['currency_id'] = $nbCurrencyId;
|
||||||
$this->report['sums'][$nbCurrencyId]['currency_code'] = $nbCurrencyCode;
|
$this->report['sums'][$nbCurrencyId]['currency_code'] = $nbCurrencyCode;
|
||||||
@@ -290,15 +290,15 @@ class BudgetReportGenerator
|
|||||||
// make percentages based on total amount.
|
// make percentages based on total amount.
|
||||||
foreach ($this->report['budgets'] as $budgetId => $data) {
|
foreach ($this->report['budgets'] as $budgetId => $data) {
|
||||||
foreach ($data['budget_limits'] as $limitId => $entry) {
|
foreach ($data['budget_limits'] as $limitId => $entry) {
|
||||||
$budgetId = (int) $budgetId;
|
$budgetId = (int) $budgetId;
|
||||||
$limitId = (int) $limitId;
|
$limitId = (int) $limitId;
|
||||||
$currencyId = (int) $entry['currency_id'];
|
$currencyId = (int) $entry['currency_id'];
|
||||||
$spent = $entry['spent'];
|
$spent = $entry['spent'];
|
||||||
$totalSpent = $this->report['sums'][$currencyId]['spent'] ?? '0';
|
$totalSpent = $this->report['sums'][$currencyId]['spent'] ?? '0';
|
||||||
$spentPct = '0';
|
$spentPct = '0';
|
||||||
$budgeted = $entry['budgeted'];
|
$budgeted = $entry['budgeted'];
|
||||||
$totalBudgeted = $this->report['sums'][$currencyId]['budgeted'] ?? '0';
|
$totalBudgeted = $this->report['sums'][$currencyId]['budgeted'] ?? '0';
|
||||||
$budgetedPct = '0';
|
$budgetedPct = '0';
|
||||||
|
|
||||||
if (0 !== bccomp($spent, '0') && 0 !== bccomp($totalSpent, '0')) {
|
if (0 !== bccomp($spent, '0') && 0 !== bccomp($totalSpent, '0')) {
|
||||||
$spentPct = round((float) bcmul(bcdiv($spent, $totalSpent), '100'));
|
$spentPct = round((float) bcmul(bcdiv($spent, $totalSpent), '100'));
|
||||||
@@ -306,7 +306,7 @@ class BudgetReportGenerator
|
|||||||
if (0 !== bccomp($budgeted, '0') && 0 !== bccomp($totalBudgeted, '0')) {
|
if (0 !== bccomp($budgeted, '0') && 0 !== bccomp($totalBudgeted, '0')) {
|
||||||
$budgetedPct = round((float) bcmul(bcdiv($budgeted, $totalBudgeted), '100'));
|
$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]['spent_pct'] = $spentPct;
|
||||||
$this->report['budgets'][$budgetId]['budget_limits'][$limitId]['budgeted_pct'] = $budgetedPct;
|
$this->report['budgets'][$budgetId]['budget_limits'][$limitId]['budgeted_pct'] = $budgetedPct;
|
||||||
}
|
}
|
||||||
|
@@ -62,17 +62,17 @@ class CategoryReportGenerator
|
|||||||
*/
|
*/
|
||||||
public function operations(): void
|
public function operations(): void
|
||||||
{
|
{
|
||||||
$earnedWith = $this->opsRepository->listIncome($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);
|
$spentWith = $this->opsRepository->listExpenses($this->start, $this->end, $this->accounts);
|
||||||
|
|
||||||
// also transferred out and transferred into these accounts in this category:
|
// also transferred out and transferred into these accounts in this category:
|
||||||
$transferredIn = $this->opsRepository->listTransferredIn($this->start, $this->end, $this->accounts);
|
$transferredIn = $this->opsRepository->listTransferredIn($this->start, $this->end, $this->accounts);
|
||||||
$transferredOut = $this->opsRepository->listTransferredOut($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);
|
$earnedWithout = $this->noCatRepository->listIncome($this->start, $this->end, $this->accounts);
|
||||||
$spentWithout = $this->noCatRepository->listExpenses($this->start, $this->end, $this->accounts);
|
$spentWithout = $this->noCatRepository->listExpenses($this->start, $this->end, $this->accounts);
|
||||||
|
|
||||||
$this->report = [
|
$this->report = [
|
||||||
'categories' => [],
|
'categories' => [],
|
||||||
'sums' => [],
|
'sums' => [],
|
||||||
];
|
];
|
||||||
@@ -121,7 +121,7 @@ class CategoryReportGenerator
|
|||||||
|
|
||||||
private function processCategoryRow(int $currencyId, array $currencyRow, int $categoryId, array $categoryRow): void
|
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] ??= [
|
$this->report['categories'][$key] ??= [
|
||||||
'id' => $categoryId,
|
'id' => $categoryId,
|
||||||
'title' => $categoryRow['name'],
|
'title' => $categoryRow['name'],
|
||||||
@@ -137,9 +137,9 @@ class CategoryReportGenerator
|
|||||||
// loop journals:
|
// loop journals:
|
||||||
foreach ($categoryRow['transaction_journals'] as $journal) {
|
foreach ($categoryRow['transaction_journals'] as $journal) {
|
||||||
// sum of sums
|
// 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:
|
// 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'],
|
$this->report['sums'][$currencyId]['spent'],
|
||||||
$journal['amount']
|
$journal['amount']
|
||||||
) : $this->report['sums'][$currencyId]['spent'];
|
) : $this->report['sums'][$currencyId]['spent'];
|
||||||
@@ -150,14 +150,14 @@ class CategoryReportGenerator
|
|||||||
) : $this->report['sums'][$currencyId]['earned'];
|
) : $this->report['sums'][$currencyId]['earned'];
|
||||||
|
|
||||||
// sum of category
|
// 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
|
// 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'],
|
$this->report['categories'][$key]['spent'],
|
||||||
$journal['amount']
|
$journal['amount']
|
||||||
) : $this->report['categories'][$key]['spent'];
|
) : $this->report['categories'][$key]['spent'];
|
||||||
// total earned in category
|
// 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'],
|
$this->report['categories'][$key]['earned'],
|
||||||
$journal['amount']
|
$journal['amount']
|
||||||
) : $this->report['categories'][$key]['earned'];
|
) : $this->report['categories'][$key]['earned'];
|
||||||
|
@@ -82,8 +82,8 @@ trait CalculateRangeOccurrences
|
|||||||
*/
|
*/
|
||||||
protected function getNdomInRange(Carbon $start, Carbon $end, int $skipMod, string $moment): array
|
protected function getNdomInRange(Carbon $start, Carbon $end, int $skipMod, string $moment): array
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
$start->startOfMonth();
|
$start->startOfMonth();
|
||||||
// this feels a bit like a cop out but why reinvent the wheel?
|
// this feels a bit like a cop out but why reinvent the wheel?
|
||||||
$counters = [1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth'];
|
$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
|
protected function getWeeklyInRange(Carbon $start, Carbon $end, int $skipMod, string $moment): array
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
app('log')->debug('Rep is weekly.');
|
app('log')->debug('Rep is weekly.');
|
||||||
// monday = 1
|
// monday = 1
|
||||||
// sunday = 7
|
// sunday = 7
|
||||||
$dayOfWeek = (int) $moment;
|
$dayOfWeek = (int) $moment;
|
||||||
app('log')->debug(sprintf('DoW in repetition is %d, in mutator is %d', $dayOfWeek, $start->dayOfWeekIso));
|
app('log')->debug(sprintf('DoW in repetition is %d, in mutator is %d', $dayOfWeek, $start->dayOfWeekIso));
|
||||||
if ($start->dayOfWeekIso > $dayOfWeek) {
|
if ($start->dayOfWeekIso > $dayOfWeek) {
|
||||||
// day has already passed this week, add one week:
|
// day has already passed this week, add one week:
|
||||||
@@ -154,8 +154,8 @@ trait CalculateRangeOccurrences
|
|||||||
}
|
}
|
||||||
|
|
||||||
// is $date between $start and $end?
|
// is $date between $start and $end?
|
||||||
$obj = clone $date;
|
$obj = clone $date;
|
||||||
$count = 0;
|
$count = 0;
|
||||||
while ($obj <= $end && $obj >= $start && $count < 10) {
|
while ($obj <= $end && $obj >= $start && $count < 10) {
|
||||||
if (0 === $attempts % $skipMod) {
|
if (0 === $attempts % $skipMod) {
|
||||||
$return[] = clone $obj;
|
$return[] = clone $obj;
|
||||||
|
@@ -89,10 +89,10 @@ trait CalculateXOccurrences
|
|||||||
*/
|
*/
|
||||||
protected function getXNDomOccurrences(Carbon $date, int $count, int $skipMod, string $moment): array
|
protected function getXNDomOccurrences(Carbon $date, int $count, int $skipMod, string $moment): array
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$total = 0;
|
$total = 0;
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
$mutator = clone $date;
|
$mutator = clone $date;
|
||||||
$mutator->addDay(); // always assume today has passed.
|
$mutator->addDay(); // always assume today has passed.
|
||||||
$mutator->startOfMonth();
|
$mutator->startOfMonth();
|
||||||
// this feels a bit like a cop out but why reinvent the wheel?
|
// 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
|
protected function getXWeeklyOccurrences(Carbon $date, int $count, int $skipMod, string $moment): array
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$total = 0;
|
$total = 0;
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
$mutator = clone $date;
|
$mutator = clone $date;
|
||||||
// monday = 1
|
// monday = 1
|
||||||
// sunday = 7
|
// sunday = 7
|
||||||
$mutator->addDay(); // always assume today has passed.
|
$mutator->addDay(); // always assume today has passed.
|
||||||
$dayOfWeek = (int) $moment;
|
$dayOfWeek = (int) $moment;
|
||||||
if ($mutator->dayOfWeekIso > $dayOfWeek) {
|
if ($mutator->dayOfWeekIso > $dayOfWeek) {
|
||||||
// day has already passed this week, add one week:
|
// day has already passed this week, add one week:
|
||||||
$mutator->addWeek();
|
$mutator->addWeek();
|
||||||
@@ -164,7 +164,7 @@ trait CalculateXOccurrences
|
|||||||
if ($mutator > $date) {
|
if ($mutator > $date) {
|
||||||
$date->addYear();
|
$date->addYear();
|
||||||
}
|
}
|
||||||
$obj = clone $date;
|
$obj = clone $date;
|
||||||
while ($total < $count) {
|
while ($total < $count) {
|
||||||
if (0 === $attempts % $skipMod) {
|
if (0 === $attempts % $skipMod) {
|
||||||
$return[] = clone $obj;
|
$return[] = clone $obj;
|
||||||
|
@@ -86,7 +86,7 @@ trait CalculateXOccurrencesSince
|
|||||||
++$total;
|
++$total;
|
||||||
}
|
}
|
||||||
++$attempts;
|
++$attempts;
|
||||||
$mutator = $mutator->endOfMonth()->addDay();
|
$mutator = $mutator->endOfMonth()->addDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
@@ -101,10 +101,10 @@ trait CalculateXOccurrencesSince
|
|||||||
protected function getXNDomOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
protected function getXNDomOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||||
$return = [];
|
$return = [];
|
||||||
$total = 0;
|
$total = 0;
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
$mutator = clone $date;
|
$mutator = clone $date;
|
||||||
$mutator->addDay(); // always assume today has passed.
|
$mutator->addDay(); // always assume today has passed.
|
||||||
$mutator->startOfMonth();
|
$mutator->startOfMonth();
|
||||||
// this feels a bit like a cop out but why reinvent the wheel?
|
// 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
|
protected function getXWeeklyOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||||
$return = [];
|
$return = [];
|
||||||
$total = 0;
|
$total = 0;
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
$mutator = clone $date;
|
$mutator = clone $date;
|
||||||
// monday = 1
|
// monday = 1
|
||||||
// sunday = 7
|
// sunday = 7
|
||||||
// Removed assumption today has passed, see issue https://github.com/firefly-iii/firefly-iii/issues/4798
|
// Removed assumption today has passed, see issue https://github.com/firefly-iii/firefly-iii/issues/4798
|
||||||
// $mutator->addDay(); // always assume today has passed.
|
// $mutator->addDay(); // always assume today has passed.
|
||||||
$dayOfWeek = (int) $moment;
|
$dayOfWeek = (int) $moment;
|
||||||
if ($mutator->dayOfWeekIso > $dayOfWeek) {
|
if ($mutator->dayOfWeekIso > $dayOfWeek) {
|
||||||
// day has already passed this week, add one week:
|
// day has already passed this week, add one week:
|
||||||
$mutator->addWeek();
|
$mutator->addWeek();
|
||||||
@@ -187,7 +187,7 @@ trait CalculateXOccurrencesSince
|
|||||||
$date->addYear();
|
$date->addYear();
|
||||||
app('log')->debug(sprintf('Date is now %s', $date->format('Y-m-d')));
|
app('log')->debug(sprintf('Date is now %s', $date->format('Y-m-d')));
|
||||||
}
|
}
|
||||||
$obj = clone $date;
|
$obj = clone $date;
|
||||||
while ($total < $count) {
|
while ($total < $count) {
|
||||||
app('log')->debug(sprintf('total (%d) < count (%d) so go.', $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));
|
app('log')->debug(sprintf('attempts (%d) %% skipmod (%d) === %d', $attempts, $skipMod, $attempts % $skipMod));
|
||||||
|
@@ -44,7 +44,7 @@ trait FiltersWeekends
|
|||||||
|
|
||||||
return $dates;
|
return $dates;
|
||||||
}
|
}
|
||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
foreach ($dates as $date) {
|
foreach ($dates as $date) {
|
||||||
@@ -58,7 +58,7 @@ trait FiltersWeekends
|
|||||||
|
|
||||||
// is weekend and must set back to Friday?
|
// is weekend and must set back to Friday?
|
||||||
if (RecurrenceRepetition::WEEKEND_TO_FRIDAY === $repetition->weekend) {
|
if (RecurrenceRepetition::WEEKEND_TO_FRIDAY === $repetition->weekend) {
|
||||||
$clone = clone $date;
|
$clone = clone $date;
|
||||||
$clone->addDays(5 - $date->dayOfWeekIso);
|
$clone->addDays(5 - $date->dayOfWeekIso);
|
||||||
app('log')->debug(
|
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'))
|
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?
|
// postpone to Monday?
|
||||||
if (RecurrenceRepetition::WEEKEND_TO_MONDAY === $repetition->weekend) {
|
if (RecurrenceRepetition::WEEKEND_TO_MONDAY === $repetition->weekend) {
|
||||||
$clone = clone $date;
|
$clone = clone $date;
|
||||||
$clone->addDays(8 - $date->dayOfWeekIso);
|
$clone->addDays(8 - $date->dayOfWeekIso);
|
||||||
app('log')->debug(
|
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'))
|
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
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function setUser(null | Authenticatable | User $user): void
|
public function setUser(null|Authenticatable|User $user): void
|
||||||
{
|
{
|
||||||
if ($user instanceof User) {
|
if ($user instanceof User) {
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
if (null === $user->userGroup) {
|
if (null === $user->userGroup) {
|
||||||
throw new FireflyException(sprintf('User #%d has no user group.', $user->id));
|
throw new FireflyException(sprintf('User #%d has no user group.', $user->id));
|
||||||
}
|
}
|
||||||
@@ -70,15 +70,16 @@ trait UserGroupTrait
|
|||||||
*/
|
*/
|
||||||
public function setUserGroupById(int $userGroupId): void
|
public function setUserGroupById(int $userGroupId): void
|
||||||
{
|
{
|
||||||
$memberships = GroupMembership::where('user_id', $this->user->id)
|
$memberships = GroupMembership::where('user_id', $this->user->id)
|
||||||
->where('user_group_id', $userGroupId)
|
->where('user_group_id', $userGroupId)
|
||||||
->count();
|
->count()
|
||||||
|
;
|
||||||
if (0 === $memberships) {
|
if (0 === $memberships) {
|
||||||
throw new FireflyException(sprintf('User #%d has no access to administration #%d', $this->user->id, $userGroupId));
|
throw new FireflyException(sprintf('User #%d has no access to administration #%d', $this->user->id, $userGroupId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var null|UserGroup $userGroup */
|
/** @var null|UserGroup $userGroup */
|
||||||
$userGroup = UserGroup::find($userGroupId);
|
$userGroup = UserGroup::find($userGroupId);
|
||||||
if (null === $userGroup) {
|
if (null === $userGroup) {
|
||||||
throw new FireflyException(sprintf('Cannot find administration for user #%d', $this->user->id));
|
throw new FireflyException(sprintf('Cannot find administration for user #%d', $this->user->id));
|
||||||
}
|
}
|
||||||
|
@@ -82,12 +82,12 @@ trait AppendsLocationData
|
|||||||
$data['latitude'] = null;
|
$data['latitude'] = null;
|
||||||
$data['zoom_level'] = null;
|
$data['zoom_level'] = null;
|
||||||
|
|
||||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||||
$isValidPOST = $this->isValidPost($prefix);
|
$isValidPOST = $this->isValidPost($prefix);
|
||||||
$isValidPUT = $this->isValidPUT($prefix);
|
$isValidPUT = $this->isValidPUT($prefix);
|
||||||
$isValidEmptyPUT = $this->isValidEmptyPUT($prefix);
|
$isValidEmptyPUT = $this->isValidEmptyPUT($prefix);
|
||||||
|
|
||||||
// for a POST (store), all fields must be present and not NULL.
|
// for a POST (store), all fields must be present and not NULL.
|
||||||
if ($isValidPOST) {
|
if ($isValidPOST) {
|
||||||
@@ -245,9 +245,9 @@ trait AppendsLocationData
|
|||||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
null === $this->get($longitudeKey)
|
null === $this->get($longitudeKey)
|
||||||
&& null === $this->get($latitudeKey)
|
&& null === $this->get($latitudeKey)
|
||||||
&& null === $this->get($zoomLevelKey))
|
&& null === $this->get($zoomLevelKey))
|
||||||
&& (
|
&& (
|
||||||
'PUT' === $this->method()
|
'PUT' === $this->method()
|
||||||
|| ('POST' === $this->method() && $this->routeIs('*.update'))
|
|| ('POST' === $this->method() && $this->routeIs('*.update'))
|
||||||
|
@@ -40,7 +40,7 @@ trait ChecksLogin
|
|||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||||
// Only allow logged-in users
|
// Only allow logged-in users
|
||||||
$check = auth()->check();
|
$check = auth()->check();
|
||||||
if (!$check) {
|
if (!$check) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ trait ChecksLogin
|
|||||||
public function getUserGroup(): ?UserGroup
|
public function getUserGroup(): ?UserGroup
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
app('log')->debug('Now in getUserGroup()');
|
app('log')->debug('Now in getUserGroup()');
|
||||||
|
|
||||||
/** @var null|UserGroup $userGroup */
|
/** @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));
|
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;
|
$userGroupId = (int) $user->user_group_id;
|
||||||
}
|
}
|
||||||
$userGroup = UserGroup::find($userGroupId);
|
$userGroup = UserGroup::find($userGroupId);
|
||||||
if (null === $userGroup) {
|
if (null === $userGroup) {
|
||||||
app('log')->error(sprintf('Request class has user_group_id (#%d), but group does not exist.', $userGroupId));
|
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
|
trait ConvertAPIDataTypes {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
@@ -38,13 +38,13 @@ trait GetFilterInstructions
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
foreach ($set as $info) {
|
foreach ($set as $info) {
|
||||||
$column = $info['column'] ?? 'NOPE';
|
$column = $info['column'] ?? 'NOPE';
|
||||||
$filterValue = (string) ($info['filter'] ?? self::INVALID_FILTER);
|
$filterValue = (string) ($info['filter'] ?? self::INVALID_FILTER);
|
||||||
if (false === in_array($column, $allowed, true)) {
|
if (false === in_array($column, $allowed, true)) {
|
||||||
// skip invalid column
|
// skip invalid column
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$filterType = $config[$column] ?? false;
|
$filterType = $config[$column] ?? false;
|
||||||
|
|
||||||
switch ($filterType) {
|
switch ($filterType) {
|
||||||
default:
|
default:
|
||||||
|
@@ -35,8 +35,8 @@ trait GetSortInstructions
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
foreach ($set as $info) {
|
foreach ($set as $info) {
|
||||||
$column = $info['column'] ?? 'NOPE';
|
$column = $info['column'] ?? 'NOPE';
|
||||||
$direction = $info['direction'] ?? 'NOPE';
|
$direction = $info['direction'] ?? 'NOPE';
|
||||||
if ('asc' !== $direction && 'desc' !== $direction) {
|
if ('asc' !== $direction && 'desc' !== $direction) {
|
||||||
// skip invalid direction
|
// skip invalid direction
|
||||||
continue;
|
continue;
|
||||||
|
@@ -35,16 +35,16 @@ use Illuminate\Support\Collection;
|
|||||||
class AccountSearch implements GenericSearchInterface
|
class AccountSearch implements GenericSearchInterface
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const string SEARCH_ALL = 'all';
|
public const string SEARCH_ALL = 'all';
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const string SEARCH_IBAN = 'iban';
|
public const string SEARCH_IBAN = 'iban';
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const string SEARCH_ID = 'id';
|
public const string SEARCH_ID = 'id';
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const string SEARCH_NAME = 'name';
|
public const string SEARCH_NAME = 'name';
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const string SEARCH_NUMBER = 'number';
|
public const string SEARCH_NUMBER = 'number';
|
||||||
@@ -61,9 +61,10 @@ class AccountSearch implements GenericSearchInterface
|
|||||||
public function search(): Collection
|
public function search(): Collection
|
||||||
{
|
{
|
||||||
$searchQuery = $this->user->accounts()
|
$searchQuery = $this->user->accounts()
|
||||||
->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id')
|
->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id')
|
||||||
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
|
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
|
||||||
->whereIn('account_types.type', $this->types);
|
->whereIn('account_types.type', $this->types)
|
||||||
|
;
|
||||||
$like = sprintf('%%%s%%', $this->query);
|
$like = sprintf('%%%s%%', $this->query);
|
||||||
$originalQuery = $this->query;
|
$originalQuery = $this->query;
|
||||||
|
|
||||||
@@ -134,7 +135,7 @@ class AccountSearch implements GenericSearchInterface
|
|||||||
$this->types = $types;
|
$this->types = $types;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUser(null | Authenticatable | User $user): void
|
public function setUser(null|Authenticatable|User $user): void
|
||||||
{
|
{
|
||||||
if ($user instanceof User) {
|
if ($user instanceof User) {
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
|
@@ -57,8 +57,6 @@ use Gdbots\QueryParser\Node\Word;
|
|||||||
use Gdbots\QueryParser\QueryParser;
|
use Gdbots\QueryParser\QueryParser;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use LogicException;
|
|
||||||
use TypeError;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OperatorQuerySearch
|
* Class OperatorQuerySearch
|
||||||
@@ -151,7 +149,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$query1 = $parser->parse($query);
|
$query1 = $parser->parse($query);
|
||||||
} catch (LogicException | TypeError $e) {
|
} catch (\LogicException|\TypeError $e) {
|
||||||
app('log')->error($e->getMessage());
|
app('log')->error($e->getMessage());
|
||||||
app('log')->error(sprintf('Could not parse search: "%s".', $query));
|
app('log')->error(sprintf('Could not parse search: "%s".', $query));
|
||||||
|
|
||||||
@@ -203,7 +201,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case Emoticon::class:
|
case Emoticon::class:
|
||||||
case Emoji::class:
|
case Emoji::class:
|
||||||
case Mention::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));
|
app('log')->debug(sprintf('Add words "%s" to search string, because Node class is "%s"', $allWords, $class));
|
||||||
$this->words[] = $allWords;
|
$this->words[] = $allWords;
|
||||||
|
|
||||||
@@ -214,10 +212,10 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
/** @var Field $searchNode */
|
/** @var Field $searchNode */
|
||||||
// used to search for x:y
|
// used to search for x:y
|
||||||
$operator = strtolower($searchNode->getValue());
|
$operator = strtolower($searchNode->getValue());
|
||||||
$value = $searchNode->getNode()->getValue();
|
$value = $searchNode->getNode()->getValue();
|
||||||
$prohibited = BoolOperator::PROHIBITED === $searchNode->getBoolOperator();
|
$prohibited = BoolOperator::PROHIBITED === $searchNode->getBoolOperator();
|
||||||
$context = config(sprintf('search.operators.%s.needs_context', $operator));
|
$context = config(sprintf('search.operators.%s.needs_context', $operator));
|
||||||
|
|
||||||
// is an operator that needs no context, and value is false, then prohibited = true.
|
// 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) {
|
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));
|
throw new FireflyException(sprintf('Unsupported search operator: "%s"', $operator));
|
||||||
|
|
||||||
// some search operators are ignored, basically:
|
// some search operators are ignored, basically:
|
||||||
case 'user_action':
|
case 'user_action':
|
||||||
app('log')->info(sprintf('Ignore search operator "%s"', $operator));
|
app('log')->info(sprintf('Ignore search operator "%s"', $operator));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//
|
//
|
||||||
// all account related searches:
|
// all account related searches:
|
||||||
//
|
//
|
||||||
case 'account_is':
|
case 'account_is':
|
||||||
$this->searchAccount($value, SearchDirection::BOTH, StringPosition::IS);
|
$this->searchAccount($value, SearchDirection::BOTH, StringPosition::IS);
|
||||||
|
|
||||||
@@ -447,7 +445,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'source_account_id':
|
case 'source_account_id':
|
||||||
$account = $this->accountRepository->find((int) $value);
|
$account = $this->accountRepository->find((int) $value);
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
$this->collector->setSourceAccounts(new Collection([$account]));
|
$this->collector->setSourceAccounts(new Collection([$account]));
|
||||||
}
|
}
|
||||||
@@ -459,7 +457,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-source_account_id':
|
case '-source_account_id':
|
||||||
$account = $this->accountRepository->find((int) $value);
|
$account = $this->accountRepository->find((int) $value);
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
$this->collector->excludeSourceAccounts(new Collection([$account]));
|
$this->collector->excludeSourceAccounts(new Collection([$account]));
|
||||||
}
|
}
|
||||||
@@ -471,25 +469,25 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'journal_id':
|
case 'journal_id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
$this->collector->setJournalIds($parts);
|
$this->collector->setJournalIds($parts);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-journal_id':
|
case '-journal_id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
$this->collector->excludeJournalIds($parts);
|
$this->collector->excludeJournalIds($parts);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'id':
|
case 'id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
$this->collector->setIds($parts);
|
$this->collector->setIds($parts);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-id':
|
case '-id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
$this->collector->excludeIds($parts);
|
$this->collector->excludeIds($parts);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -575,7 +573,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'destination_account_id':
|
case 'destination_account_id':
|
||||||
$account = $this->accountRepository->find((int) $value);
|
$account = $this->accountRepository->find((int) $value);
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
$this->collector->setDestinationAccounts(new Collection([$account]));
|
$this->collector->setDestinationAccounts(new Collection([$account]));
|
||||||
}
|
}
|
||||||
@@ -586,7 +584,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-destination_account_id':
|
case '-destination_account_id':
|
||||||
$account = $this->accountRepository->find((int) $value);
|
$account = $this->accountRepository->find((int) $value);
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
$this->collector->excludeDestinationAccounts(new Collection([$account]));
|
$this->collector->excludeDestinationAccounts(new Collection([$account]));
|
||||||
}
|
}
|
||||||
@@ -597,8 +595,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'account_id':
|
case 'account_id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
$collection = new Collection();
|
$collection = new Collection();
|
||||||
foreach ($parts as $accountId) {
|
foreach ($parts as $accountId) {
|
||||||
$account = $this->accountRepository->find((int) $accountId);
|
$account = $this->accountRepository->find((int) $accountId);
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
@@ -615,8 +613,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-account_id':
|
case '-account_id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
$collection = new Collection();
|
$collection = new Collection();
|
||||||
foreach ($parts as $accountId) {
|
foreach ($parts as $accountId) {
|
||||||
$account = $this->accountRepository->find((int) $accountId);
|
$account = $this->accountRepository->find((int) $accountId);
|
||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
@@ -632,48 +630,48 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// cash account
|
// cash account
|
||||||
//
|
//
|
||||||
case 'source_is_cash':
|
case 'source_is_cash':
|
||||||
$account = $this->getCashAccount();
|
$account = $this->getCashAccount();
|
||||||
$this->collector->setSourceAccounts(new Collection([$account]));
|
$this->collector->setSourceAccounts(new Collection([$account]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-source_is_cash':
|
case '-source_is_cash':
|
||||||
$account = $this->getCashAccount();
|
$account = $this->getCashAccount();
|
||||||
$this->collector->excludeSourceAccounts(new Collection([$account]));
|
$this->collector->excludeSourceAccounts(new Collection([$account]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'destination_is_cash':
|
case 'destination_is_cash':
|
||||||
$account = $this->getCashAccount();
|
$account = $this->getCashAccount();
|
||||||
$this->collector->setDestinationAccounts(new Collection([$account]));
|
$this->collector->setDestinationAccounts(new Collection([$account]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-destination_is_cash':
|
case '-destination_is_cash':
|
||||||
$account = $this->getCashAccount();
|
$account = $this->getCashAccount();
|
||||||
$this->collector->excludeDestinationAccounts(new Collection([$account]));
|
$this->collector->excludeDestinationAccounts(new Collection([$account]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'account_is_cash':
|
case 'account_is_cash':
|
||||||
$account = $this->getCashAccount();
|
$account = $this->getCashAccount();
|
||||||
$this->collector->setAccounts(new Collection([$account]));
|
$this->collector->setAccounts(new Collection([$account]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-account_is_cash':
|
case '-account_is_cash':
|
||||||
$account = $this->getCashAccount();
|
$account = $this->getCashAccount();
|
||||||
$this->collector->excludeAccounts(new Collection([$account]));
|
$this->collector->excludeAccounts(new Collection([$account]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// description
|
// description
|
||||||
//
|
//
|
||||||
case 'description_starts':
|
case 'description_starts':
|
||||||
$this->collector->descriptionStarts([$value]);
|
$this->collector->descriptionStarts([$value]);
|
||||||
|
|
||||||
@@ -695,7 +693,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'description_contains':
|
case 'description_contains':
|
||||||
$this->words[] = $value;
|
$this->words[] = $value;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -714,11 +712,11 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// currency
|
// currency
|
||||||
//
|
//
|
||||||
case 'currency_is':
|
case 'currency_is':
|
||||||
$currency = $this->findCurrency($value);
|
$currency = $this->findCurrency($value);
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$this->collector->setCurrency($currency);
|
$this->collector->setCurrency($currency);
|
||||||
}
|
}
|
||||||
@@ -729,7 +727,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-currency_is':
|
case '-currency_is':
|
||||||
$currency = $this->findCurrency($value);
|
$currency = $this->findCurrency($value);
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$this->collector->excludeCurrency($currency);
|
$this->collector->excludeCurrency($currency);
|
||||||
}
|
}
|
||||||
@@ -740,7 +738,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'foreign_currency_is':
|
case 'foreign_currency_is':
|
||||||
$currency = $this->findCurrency($value);
|
$currency = $this->findCurrency($value);
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$this->collector->setForeignCurrency($currency);
|
$this->collector->setForeignCurrency($currency);
|
||||||
}
|
}
|
||||||
@@ -751,7 +749,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-foreign_currency_is':
|
case '-foreign_currency_is':
|
||||||
$currency = $this->findCurrency($value);
|
$currency = $this->findCurrency($value);
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$this->collector->excludeForeignCurrency($currency);
|
$this->collector->excludeForeignCurrency($currency);
|
||||||
}
|
}
|
||||||
@@ -761,9 +759,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// attachments
|
// attachments
|
||||||
//
|
//
|
||||||
case 'has_attachments':
|
case 'has_attachments':
|
||||||
case '-has_no_attachments':
|
case '-has_no_attachments':
|
||||||
app('log')->debug('Set collector to filter on attachments.');
|
app('log')->debug('Set collector to filter on attachments.');
|
||||||
@@ -778,8 +776,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// categories
|
// categories
|
||||||
case '-has_any_category':
|
case '-has_any_category':
|
||||||
case 'has_no_category':
|
case 'has_no_category':
|
||||||
$this->collector->withoutCategory();
|
$this->collector->withoutCategory();
|
||||||
@@ -793,7 +791,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'category_is':
|
case 'category_is':
|
||||||
$category = $this->categoryRepository->findByName($value);
|
$category = $this->categoryRepository->findByName($value);
|
||||||
if (null !== $category) {
|
if (null !== $category) {
|
||||||
$this->collector->setCategory($category);
|
$this->collector->setCategory($category);
|
||||||
|
|
||||||
@@ -804,7 +802,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-category_is':
|
case '-category_is':
|
||||||
$category = $this->categoryRepository->findByName($value);
|
$category = $this->categoryRepository->findByName($value);
|
||||||
if (null !== $category) {
|
if (null !== $category) {
|
||||||
$this->collector->excludeCategory($category);
|
$this->collector->excludeCategory($category);
|
||||||
|
|
||||||
@@ -814,7 +812,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'category_ends':
|
case 'category_ends':
|
||||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setCategories($result);
|
$this->collector->setCategories($result);
|
||||||
}
|
}
|
||||||
@@ -825,7 +823,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-category_ends':
|
case '-category_ends':
|
||||||
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
$result = $this->categoryRepository->categoryEndsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeCategories($result);
|
$this->collector->excludeCategories($result);
|
||||||
}
|
}
|
||||||
@@ -836,7 +834,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'category_starts':
|
case 'category_starts':
|
||||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setCategories($result);
|
$this->collector->setCategories($result);
|
||||||
}
|
}
|
||||||
@@ -847,7 +845,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-category_starts':
|
case '-category_starts':
|
||||||
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
$result = $this->categoryRepository->categoryStartsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeCategories($result);
|
$this->collector->excludeCategories($result);
|
||||||
}
|
}
|
||||||
@@ -858,7 +856,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'category_contains':
|
case 'category_contains':
|
||||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setCategories($result);
|
$this->collector->setCategories($result);
|
||||||
}
|
}
|
||||||
@@ -869,7 +867,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-category_contains':
|
case '-category_contains':
|
||||||
$result = $this->categoryRepository->searchCategory($value, 1337);
|
$result = $this->categoryRepository->searchCategory($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeCategories($result);
|
$this->collector->excludeCategories($result);
|
||||||
}
|
}
|
||||||
@@ -879,9 +877,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// budgets
|
// budgets
|
||||||
//
|
//
|
||||||
case '-has_any_budget':
|
case '-has_any_budget':
|
||||||
case 'has_no_budget':
|
case 'has_no_budget':
|
||||||
$this->collector->withoutBudget();
|
$this->collector->withoutBudget();
|
||||||
@@ -895,7 +893,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'budget_contains':
|
case 'budget_contains':
|
||||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBudgets($result);
|
$this->collector->setBudgets($result);
|
||||||
}
|
}
|
||||||
@@ -906,7 +904,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-budget_contains':
|
case '-budget_contains':
|
||||||
$result = $this->budgetRepository->searchBudget($value, 1337);
|
$result = $this->budgetRepository->searchBudget($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeBudgets($result);
|
$this->collector->excludeBudgets($result);
|
||||||
}
|
}
|
||||||
@@ -917,7 +915,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'budget_is':
|
case 'budget_is':
|
||||||
$budget = $this->budgetRepository->findByName($value);
|
$budget = $this->budgetRepository->findByName($value);
|
||||||
if (null !== $budget) {
|
if (null !== $budget) {
|
||||||
$this->collector->setBudget($budget);
|
$this->collector->setBudget($budget);
|
||||||
|
|
||||||
@@ -928,7 +926,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-budget_is':
|
case '-budget_is':
|
||||||
$budget = $this->budgetRepository->findByName($value);
|
$budget = $this->budgetRepository->findByName($value);
|
||||||
if (null !== $budget) {
|
if (null !== $budget) {
|
||||||
$this->collector->excludeBudget($budget);
|
$this->collector->excludeBudget($budget);
|
||||||
|
|
||||||
@@ -939,7 +937,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'budget_ends':
|
case 'budget_ends':
|
||||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBudgets($result);
|
$this->collector->setBudgets($result);
|
||||||
}
|
}
|
||||||
@@ -950,7 +948,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-budget_ends':
|
case '-budget_ends':
|
||||||
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
$result = $this->budgetRepository->budgetEndsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeBudgets($result);
|
$this->collector->excludeBudgets($result);
|
||||||
}
|
}
|
||||||
@@ -961,7 +959,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'budget_starts':
|
case 'budget_starts':
|
||||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBudgets($result);
|
$this->collector->setBudgets($result);
|
||||||
}
|
}
|
||||||
@@ -972,7 +970,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-budget_starts':
|
case '-budget_starts':
|
||||||
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
$result = $this->budgetRepository->budgetStartsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeBudgets($result);
|
$this->collector->excludeBudgets($result);
|
||||||
}
|
}
|
||||||
@@ -982,9 +980,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// bill
|
// bill
|
||||||
//
|
//
|
||||||
case '-has_any_bill':
|
case '-has_any_bill':
|
||||||
case 'has_no_bill':
|
case 'has_no_bill':
|
||||||
$this->collector->withoutBill();
|
$this->collector->withoutBill();
|
||||||
@@ -998,7 +996,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bill_contains':
|
case 'bill_contains':
|
||||||
$result = $this->billRepository->searchBill($value, 1337);
|
$result = $this->billRepository->searchBill($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBills($result);
|
$this->collector->setBills($result);
|
||||||
|
|
||||||
@@ -1009,7 +1007,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-bill_contains':
|
case '-bill_contains':
|
||||||
$result = $this->billRepository->searchBill($value, 1337);
|
$result = $this->billRepository->searchBill($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeBills($result);
|
$this->collector->excludeBills($result);
|
||||||
|
|
||||||
@@ -1020,7 +1018,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bill_is':
|
case 'bill_is':
|
||||||
$bill = $this->billRepository->findByName($value);
|
$bill = $this->billRepository->findByName($value);
|
||||||
if (null !== $bill) {
|
if (null !== $bill) {
|
||||||
$this->collector->setBill($bill);
|
$this->collector->setBill($bill);
|
||||||
|
|
||||||
@@ -1031,7 +1029,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-bill_is':
|
case '-bill_is':
|
||||||
$bill = $this->billRepository->findByName($value);
|
$bill = $this->billRepository->findByName($value);
|
||||||
if (null !== $bill) {
|
if (null !== $bill) {
|
||||||
$this->collector->excludeBills(new Collection([$bill]));
|
$this->collector->excludeBills(new Collection([$bill]));
|
||||||
|
|
||||||
@@ -1042,7 +1040,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bill_ends':
|
case 'bill_ends':
|
||||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBills($result);
|
$this->collector->setBills($result);
|
||||||
}
|
}
|
||||||
@@ -1053,7 +1051,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-bill_ends':
|
case '-bill_ends':
|
||||||
$result = $this->billRepository->billEndsWith($value, 1337);
|
$result = $this->billRepository->billEndsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeBills($result);
|
$this->collector->excludeBills($result);
|
||||||
}
|
}
|
||||||
@@ -1064,7 +1062,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bill_starts':
|
case 'bill_starts':
|
||||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBills($result);
|
$this->collector->setBills($result);
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1073,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-bill_starts':
|
case '-bill_starts':
|
||||||
$result = $this->billRepository->billStartsWith($value, 1337);
|
$result = $this->billRepository->billStartsWith($value, 1337);
|
||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->excludeBills($result);
|
$this->collector->excludeBills($result);
|
||||||
}
|
}
|
||||||
@@ -1085,9 +1083,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// tags
|
// tags
|
||||||
//
|
//
|
||||||
case '-has_any_tag':
|
case '-has_any_tag':
|
||||||
case 'has_no_tag':
|
case 'has_no_tag':
|
||||||
$this->collector->withoutTags();
|
$this->collector->withoutTags();
|
||||||
@@ -1102,7 +1100,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
case '-tag_is_not':
|
case '-tag_is_not':
|
||||||
case 'tag_is':
|
case 'tag_is':
|
||||||
$result = $this->tagRepository->findByTag($value);
|
$result = $this->tagRepository->findByTag($value);
|
||||||
if (null !== $result) {
|
if (null !== $result) {
|
||||||
$this->includeTags[] = $result->id;
|
$this->includeTags[] = $result->id;
|
||||||
$this->includeTags = array_unique($this->includeTags);
|
$this->includeTags = array_unique($this->includeTags);
|
||||||
@@ -1116,7 +1114,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tag_contains':
|
case 'tag_contains':
|
||||||
$tags = $this->tagRepository->searchTag($value);
|
$tags = $this->tagRepository->searchTag($value);
|
||||||
if (0 === $tags->count()) {
|
if (0 === $tags->count()) {
|
||||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -1130,7 +1128,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tag_starts':
|
case 'tag_starts':
|
||||||
$tags = $this->tagRepository->tagStartsWith($value);
|
$tags = $this->tagRepository->tagStartsWith($value);
|
||||||
if (0 === $tags->count()) {
|
if (0 === $tags->count()) {
|
||||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -1144,7 +1142,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-tag_starts':
|
case '-tag_starts':
|
||||||
$tags = $this->tagRepository->tagStartsWith($value);
|
$tags = $this->tagRepository->tagStartsWith($value);
|
||||||
if (0 === $tags->count()) {
|
if (0 === $tags->count()) {
|
||||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -1157,7 +1155,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tag_ends':
|
case 'tag_ends':
|
||||||
$tags = $this->tagRepository->tagEndsWith($value);
|
$tags = $this->tagRepository->tagEndsWith($value);
|
||||||
if (0 === $tags->count()) {
|
if (0 === $tags->count()) {
|
||||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -1170,7 +1168,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-tag_ends':
|
case '-tag_ends':
|
||||||
$tags = $this->tagRepository->tagEndsWith($value);
|
$tags = $this->tagRepository->tagEndsWith($value);
|
||||||
if (0 === $tags->count()) {
|
if (0 === $tags->count()) {
|
||||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -1183,7 +1181,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-tag_contains':
|
case '-tag_contains':
|
||||||
$tags = $this->tagRepository->searchTag($value)->keyBy('id');
|
$tags = $this->tagRepository->searchTag($value)->keyBy('id');
|
||||||
|
|
||||||
if (0 === $tags->count()) {
|
if (0 === $tags->count()) {
|
||||||
app('log')->info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
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':
|
||||||
case 'tag_is_not':
|
case 'tag_is_not':
|
||||||
$result = $this->tagRepository->findByTag($value);
|
$result = $this->tagRepository->findByTag($value);
|
||||||
if (null !== $result) {
|
if (null !== $result) {
|
||||||
$this->excludeTags[] = $result->id;
|
$this->excludeTags[] = $result->id;
|
||||||
$this->excludeTags = array_unique($this->excludeTags);
|
$this->excludeTags = array_unique($this->excludeTags);
|
||||||
@@ -1206,9 +1204,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// notes
|
// notes
|
||||||
//
|
//
|
||||||
case 'notes_contains':
|
case 'notes_contains':
|
||||||
$this->collector->notesContain($value);
|
$this->collector->notesContain($value);
|
||||||
|
|
||||||
@@ -1271,14 +1269,14 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// amount
|
// amount
|
||||||
//
|
//
|
||||||
case 'amount_is':
|
case 'amount_is':
|
||||||
// strip comma's, make dots.
|
// strip comma's, make dots.
|
||||||
app('log')->debug(sprintf('Original value "%s"', $value));
|
app('log')->debug(sprintf('Original value "%s"', $value));
|
||||||
$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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->amountIs($amount);
|
$this->collector->amountIs($amount);
|
||||||
|
|
||||||
@@ -1287,8 +1285,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case '-amount_is':
|
case '-amount_is':
|
||||||
// strip comma's, make dots.
|
// strip comma's, make dots.
|
||||||
app('log')->debug(sprintf('Original value "%s"', $value));
|
app('log')->debug(sprintf('Original value "%s"', $value));
|
||||||
$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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->amountIsNot($amount);
|
$this->collector->amountIsNot($amount);
|
||||||
|
|
||||||
@@ -1296,9 +1294,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
case 'foreign_amount_is':
|
case 'foreign_amount_is':
|
||||||
// strip comma's, make dots.
|
// 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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->foreignAmountIs($amount);
|
$this->collector->foreignAmountIs($amount);
|
||||||
|
|
||||||
@@ -1306,9 +1304,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
case '-foreign_amount_is':
|
case '-foreign_amount_is':
|
||||||
// strip comma's, make dots.
|
// 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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->foreignAmountIsNot($amount);
|
$this->collector->foreignAmountIsNot($amount);
|
||||||
|
|
||||||
@@ -1317,9 +1315,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case '-amount_more':
|
case '-amount_more':
|
||||||
case 'amount_less':
|
case 'amount_less':
|
||||||
// strip comma's, make dots.
|
// 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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->amountLess($amount);
|
$this->collector->amountLess($amount);
|
||||||
|
|
||||||
@@ -1328,9 +1326,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case '-foreign_amount_more':
|
case '-foreign_amount_more':
|
||||||
case 'foreign_amount_less':
|
case 'foreign_amount_less':
|
||||||
// strip comma's, make dots.
|
// 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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->foreignAmountLess($amount);
|
$this->collector->foreignAmountLess($amount);
|
||||||
|
|
||||||
@@ -1340,8 +1338,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'amount_more':
|
case 'amount_more':
|
||||||
app('log')->debug(sprintf('Now handling operator "%s"', $operator));
|
app('log')->debug(sprintf('Now handling operator "%s"', $operator));
|
||||||
// strip comma's, make dots.
|
// 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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->amountMore($amount);
|
$this->collector->amountMore($amount);
|
||||||
|
|
||||||
@@ -1351,16 +1349,16 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'foreign_amount_more':
|
case 'foreign_amount_more':
|
||||||
app('log')->debug(sprintf('Now handling operator "%s"', $operator));
|
app('log')->debug(sprintf('Now handling operator "%s"', $operator));
|
||||||
// strip comma's, make dots.
|
// 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));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
|
||||||
$this->collector->foreignAmountMore($amount);
|
$this->collector->foreignAmountMore($amount);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// transaction type
|
// transaction type
|
||||||
//
|
//
|
||||||
case 'transaction_type':
|
case 'transaction_type':
|
||||||
$this->collector->setTypes([ucfirst($value)]);
|
$this->collector->setTypes([ucfirst($value)]);
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||||
@@ -1373,152 +1371,152 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// dates
|
// dates
|
||||||
//
|
//
|
||||||
case '-date_on':
|
case '-date_on':
|
||||||
case 'date_on':
|
case 'date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactDateParams($range, $prohibited);
|
$this->setExactDateParams($range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'date_before':
|
case 'date_before':
|
||||||
case '-date_after':
|
case '-date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setDateBeforeParams($range);
|
$this->setDateBeforeParams($range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'date_after':
|
case 'date_after':
|
||||||
case '-date_before':
|
case '-date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setDateAfterParams($range);
|
$this->setDateAfterParams($range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'interest_date_on':
|
case 'interest_date_on':
|
||||||
case '-interest_date_on':
|
case '-interest_date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactMetaDateParams('interest_date', $range, $prohibited);
|
$this->setExactMetaDateParams('interest_date', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'interest_date_before':
|
case 'interest_date_before':
|
||||||
case '-interest_date_after':
|
case '-interest_date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateBeforeParams('interest_date', $range);
|
$this->setMetaDateBeforeParams('interest_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'interest_date_after':
|
case 'interest_date_after':
|
||||||
case '-interest_date_before':
|
case '-interest_date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateAfterParams('interest_date', $range);
|
$this->setMetaDateAfterParams('interest_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'book_date_on':
|
case 'book_date_on':
|
||||||
case '-book_date_on':
|
case '-book_date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactMetaDateParams('book_date', $range, $prohibited);
|
$this->setExactMetaDateParams('book_date', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'book_date_before':
|
case 'book_date_before':
|
||||||
case '-book_date_after':
|
case '-book_date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateBeforeParams('book_date', $range);
|
$this->setMetaDateBeforeParams('book_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'book_date_after':
|
case 'book_date_after':
|
||||||
case '-book_date_before':
|
case '-book_date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateAfterParams('book_date', $range);
|
$this->setMetaDateAfterParams('book_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'process_date_on':
|
case 'process_date_on':
|
||||||
case '-process_date_on':
|
case '-process_date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactMetaDateParams('process_date', $range, $prohibited);
|
$this->setExactMetaDateParams('process_date', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'process_date_before':
|
case 'process_date_before':
|
||||||
case '-process_date_after':
|
case '-process_date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateBeforeParams('process_date', $range);
|
$this->setMetaDateBeforeParams('process_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'process_date_after':
|
case 'process_date_after':
|
||||||
case '-process_date_before':
|
case '-process_date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateAfterParams('process_date', $range);
|
$this->setMetaDateAfterParams('process_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'due_date_on':
|
case 'due_date_on':
|
||||||
case '-due_date_on':
|
case '-due_date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactMetaDateParams('due_date', $range, $prohibited);
|
$this->setExactMetaDateParams('due_date', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'due_date_before':
|
case 'due_date_before':
|
||||||
case '-due_date_after':
|
case '-due_date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateBeforeParams('due_date', $range);
|
$this->setMetaDateBeforeParams('due_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'due_date_after':
|
case 'due_date_after':
|
||||||
case '-due_date_before':
|
case '-due_date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateAfterParams('due_date', $range);
|
$this->setMetaDateAfterParams('due_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'payment_date_on':
|
case 'payment_date_on':
|
||||||
case '-payment_date_on':
|
case '-payment_date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactMetaDateParams('payment_date', $range, $prohibited);
|
$this->setExactMetaDateParams('payment_date', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'payment_date_before':
|
case 'payment_date_before':
|
||||||
case '-payment_date_after':
|
case '-payment_date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateBeforeParams('payment_date', $range);
|
$this->setMetaDateBeforeParams('payment_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'payment_date_after':
|
case 'payment_date_after':
|
||||||
case '-payment_date_before':
|
case '-payment_date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateAfterParams('payment_date', $range);
|
$this->setMetaDateAfterParams('payment_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'invoice_date_on':
|
case 'invoice_date_on':
|
||||||
case '-invoice_date_on':
|
case '-invoice_date_on':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setExactMetaDateParams('invoice_date', $range, $prohibited);
|
$this->setExactMetaDateParams('invoice_date', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'invoice_date_before':
|
case 'invoice_date_before':
|
||||||
case '-invoice_date_after':
|
case '-invoice_date_after':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateBeforeParams('invoice_date', $range);
|
$this->setMetaDateBeforeParams('invoice_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case 'invoice_date_after':
|
case 'invoice_date_after':
|
||||||
case '-invoice_date_before':
|
case '-invoice_date_before':
|
||||||
$range = $this->parseDateRange($operator, $value);
|
$range = $this->parseDateRange($operator, $value);
|
||||||
$this->setMetaDateAfterParams('invoice_date', $range);
|
$this->setMetaDateAfterParams('invoice_date', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1526,7 +1524,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'created_at_on':
|
case 'created_at_on':
|
||||||
case '-created_at_on':
|
case '-created_at_on':
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
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);
|
$this->setExactObjectDateParams('created_at', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1534,7 +1532,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'created_at_before':
|
case 'created_at_before':
|
||||||
case '-created_at_after':
|
case '-created_at_after':
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
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);
|
$this->setObjectDateBeforeParams('created_at', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1542,7 +1540,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'created_at_after':
|
case 'created_at_after':
|
||||||
case '-created_at_before':
|
case '-created_at_before':
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
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);
|
$this->setObjectDateAfterParams('created_at', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1550,7 +1548,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'updated_at_on':
|
case 'updated_at_on':
|
||||||
case '-updated_at_on':
|
case '-updated_at_on':
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
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);
|
$this->setExactObjectDateParams('updated_at', $range, $prohibited);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1558,7 +1556,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'updated_at_before':
|
case 'updated_at_before':
|
||||||
case '-updated_at_after':
|
case '-updated_at_after':
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
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);
|
$this->setObjectDateBeforeParams('updated_at', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1566,14 +1564,14 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
case 'updated_at_after':
|
case 'updated_at_after':
|
||||||
case '-updated_at_before':
|
case '-updated_at_before':
|
||||||
app('log')->debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
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);
|
$this->setObjectDateAfterParams('updated_at', $range);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//
|
//
|
||||||
// external URL
|
// external URL
|
||||||
//
|
//
|
||||||
case '-any_external_url':
|
case '-any_external_url':
|
||||||
case 'no_external_url':
|
case 'no_external_url':
|
||||||
$this->collector->withoutExternalUrl();
|
$this->collector->withoutExternalUrl();
|
||||||
@@ -1638,9 +1636,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// other fields
|
// other fields
|
||||||
//
|
//
|
||||||
case 'external_id_is':
|
case 'external_id_is':
|
||||||
$this->collector->setExternalId($value);
|
$this->collector->setExternalId($value);
|
||||||
|
|
||||||
@@ -1842,7 +1840,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
$operator = substr($operator, 1);
|
$operator = substr($operator, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$config = config(sprintf('search.operators.%s', $operator));
|
$config = config(sprintf('search.operators.%s', $operator));
|
||||||
if (null === $config) {
|
if (null === $config) {
|
||||||
throw new FireflyException(sprintf('No configuration for search operator "%s"', $operator));
|
throw new FireflyException(sprintf('No configuration for search operator "%s"', $operator));
|
||||||
}
|
}
|
||||||
@@ -1896,7 +1894,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// string position (default): starts with:
|
// string position (default): starts with:
|
||||||
$stringMethod = 'str_starts_with';
|
$stringMethod = 'str_starts_with';
|
||||||
|
|
||||||
// string position: ends with:
|
// string position: ends with:
|
||||||
if (StringPosition::ENDS === $stringPosition) {
|
if (StringPosition::ENDS === $stringPosition) {
|
||||||
@@ -1910,7 +1908,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get accounts:
|
// get accounts:
|
||||||
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 1337);
|
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 1337);
|
||||||
if (0 === $accounts->count() && false === $prohibited) {
|
if (0 === $accounts->count() && false === $prohibited) {
|
||||||
app('log')->debug('Found zero accounts, search for non existing account, NO results will be returned.');
|
app('log')->debug('Found zero accounts, search for non existing account, NO results will be returned.');
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -1923,7 +1921,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Found %d accounts, will filter.', $accounts->count()));
|
app('log')->debug(sprintf('Found %d accounts, will filter.', $accounts->count()));
|
||||||
$filtered = $accounts->filter(
|
$filtered = $accounts->filter(
|
||||||
static function (Account $account) use ($value, $stringMethod) {
|
static function (Account $account) use ($value, $stringMethod) {
|
||||||
return $stringMethod(strtolower($account->name), strtolower($value));
|
return $stringMethod(strtolower($account->name), strtolower($value));
|
||||||
}
|
}
|
||||||
@@ -1978,7 +1976,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// string position (default): starts with:
|
// string position (default): starts with:
|
||||||
$stringMethod = 'str_starts_with';
|
$stringMethod = 'str_starts_with';
|
||||||
|
|
||||||
// string position: ends with:
|
// string position: ends with:
|
||||||
if (StringPosition::ENDS === $stringPosition) {
|
if (StringPosition::ENDS === $stringPosition) {
|
||||||
@@ -1992,7 +1990,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search for accounts:
|
// search for accounts:
|
||||||
$accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 1337);
|
$accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 1337);
|
||||||
if (0 === $accounts->count()) {
|
if (0 === $accounts->count()) {
|
||||||
app('log')->debug('Found zero accounts, search for invalid account.');
|
app('log')->debug('Found zero accounts, search for invalid account.');
|
||||||
$this->collector->findNothing();
|
$this->collector->findNothing();
|
||||||
@@ -2002,7 +2000,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
// if found, do filter
|
// if found, do filter
|
||||||
app('log')->debug(sprintf('Found %d accounts, will filter.', $accounts->count()));
|
app('log')->debug(sprintf('Found %d accounts, will filter.', $accounts->count()));
|
||||||
$filtered = $accounts->filter(
|
$filtered = $accounts->filter(
|
||||||
static function (Account $account) use ($value, $stringMethod) {
|
static function (Account $account) use ($value, $stringMethod) {
|
||||||
// either IBAN or account number
|
// either IBAN or account number
|
||||||
$ibanMatch = $stringMethod(strtolower((string) $account->iban), strtolower($value));
|
$ibanMatch = $stringMethod(strtolower((string) $account->iban), strtolower($value));
|
||||||
|
@@ -24,18 +24,12 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support;
|
namespace FireflyIII\Support;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
|
||||||
use Exception;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use stdClass;
|
|
||||||
use Str;
|
|
||||||
use ValueError;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Steam.
|
* Class Steam.
|
||||||
@@ -44,8 +38,8 @@ class Steam
|
|||||||
{
|
{
|
||||||
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
||||||
{
|
{
|
||||||
$type = $account->accountType->type;
|
$type = $account->accountType->type;
|
||||||
$list = config('firefly.valid_currency_account_types');
|
$list = config('firefly.valid_currency_account_types');
|
||||||
|
|
||||||
// return null if not in this list.
|
// return null if not in this list.
|
||||||
if (!in_array($type, $list, true)) {
|
if (!in_array($type, $list, true)) {
|
||||||
@@ -55,6 +49,7 @@ class Steam
|
|||||||
if (null === $result) {
|
if (null === $result) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TransactionCurrency::find((int) $result->data);
|
return TransactionCurrency::find((int) $result->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +67,6 @@ class Steam
|
|||||||
return $sum;
|
return $sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function finalAccountBalanceInRange(Account $account, Carbon $start, Carbon $end): array
|
public function finalAccountBalanceInRange(Account $account, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
// expand period.
|
// expand period.
|
||||||
@@ -80,7 +74,7 @@ class Steam
|
|||||||
$end->addDay()->endOfDay();
|
$end->addDay()->endOfDay();
|
||||||
|
|
||||||
// set up cache
|
// set up cache
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
$cache->addProperty('final-balance-in-range');
|
$cache->addProperty('final-balance-in-range');
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
@@ -89,51 +83,52 @@ class Steam
|
|||||||
// return $cache->get();
|
// return $cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
$balances = [];
|
$balances = [];
|
||||||
$formatted = $start->format('Y-m-d');
|
$formatted = $start->format('Y-m-d');
|
||||||
$startBalance = $this->finalAccountBalance($account, $start);
|
$startBalance = $this->finalAccountBalance($account, $start);
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||||
$currency = $this->getAccountCurrency($account) ?? $defaultCurrency;
|
$currency = $this->getAccountCurrency($account) ?? $defaultCurrency;
|
||||||
$currencies = [
|
$currencies = [
|
||||||
$currency->id => $currency,
|
$currency->id => $currency,
|
||||||
$defaultCurrency->id => $defaultCurrency,
|
$defaultCurrency->id => $defaultCurrency,
|
||||||
];
|
];
|
||||||
$startBalance[$defaultCurrency->code] ??= '0';
|
$startBalance[$defaultCurrency->code] ??= '0';
|
||||||
$startBalance[$currency->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.
|
// sums up the balance changes per day, for foreign, native and normal amounts.
|
||||||
$set = $account->transactions()
|
$set = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
->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', '>=', $start->format('Y-m-d H:i:s'))
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s'))
|
||||||
->groupBy('transaction_journals.date')
|
->groupBy('transaction_journals.date')
|
||||||
->groupBy('transactions.transaction_currency_id')
|
->groupBy('transactions.transaction_currency_id')
|
||||||
->groupBy('transactions.foreign_currency_id')
|
->groupBy('transactions.foreign_currency_id')
|
||||||
->orderBy('transaction_journals.date', 'ASC')
|
->orderBy('transaction_journals.date', 'ASC')
|
||||||
->whereNull('transaction_journals.deleted_at')
|
->whereNull('transaction_journals.deleted_at')
|
||||||
->get(
|
->get(
|
||||||
[ // @phpstan-ignore-line
|
[ // @phpstan-ignore-line
|
||||||
'transaction_journals.date',
|
'transaction_journals.date',
|
||||||
'transactions.transaction_currency_id',
|
'transactions.transaction_currency_id',
|
||||||
DB::raw('SUM(transactions.amount) AS modified'),
|
\DB::raw('SUM(transactions.amount) AS modified'),
|
||||||
'transactions.foreign_currency_id',
|
'transactions.foreign_currency_id',
|
||||||
DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
|
\DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
|
||||||
DB::raw('SUM(transactions.native_amount) AS modified_native'),
|
\DB::raw('SUM(transactions.native_amount) AS modified_native'),
|
||||||
]
|
]
|
||||||
);
|
)
|
||||||
|
;
|
||||||
|
|
||||||
$currentBalance = $startBalance;
|
$currentBalance = $startBalance;
|
||||||
|
|
||||||
/** @var Transaction $entry */
|
/** @var Transaction $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
|
|
||||||
// normal, native and foreign amount
|
// normal, native and foreign amount
|
||||||
$carbon = new Carbon($entry->date, $entry->date_tz);
|
$carbon = new Carbon($entry->date, $entry->date_tz);
|
||||||
$modified = (string) (null === $entry->modified ? '0' : $entry->modified);
|
$modified = (string) (null === $entry->modified ? '0' : $entry->modified);
|
||||||
$foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign);
|
$foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign);
|
||||||
$nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native);
|
$nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native);
|
||||||
|
|
||||||
// add "modified" to amount if the currency id matches the account currency id.
|
// add "modified" to amount if the currency id matches the account currency id.
|
||||||
if ($entry->transaction_currency_id === $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.
|
// 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
|
// add modified foreign to the array
|
||||||
if (null !== $entry->foreign_currency_id) {
|
if (null !== $entry->foreign_currency_id) {
|
||||||
@@ -159,11 +154,13 @@ class Steam
|
|||||||
return $balances;
|
return $balances;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function finalAccountsBalance(Collection $accounts, Carbon $date): array {
|
public function finalAccountsBalance(Collection $accounts, Carbon $date): array
|
||||||
|
{
|
||||||
$balances = [];
|
$balances = [];
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$balances[$account->id] = $this->finalAccountBalance($account, $date);
|
$balances[$account->id] = $this->finalAccountBalance($account, $date);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $balances;
|
return $balances;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,10 +183,10 @@ class Steam
|
|||||||
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
|
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
|
||||||
if (str_contains($number, '.')) {
|
if (str_contains($number, '.')) {
|
||||||
if ('-' !== $number[0]) {
|
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;
|
return $number;
|
||||||
@@ -261,26 +258,22 @@ class Steam
|
|||||||
* THAT currency.
|
* THAT currency.
|
||||||
* "native_balance" the balance according to the "native_amount" + "native_foreign_amount" fields.
|
* "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).
|
* "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
|
public function finalAccountBalance(Account $account, Carbon $date): array
|
||||||
{
|
{
|
||||||
$native = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
$native = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||||
$currency = $this->getAccountCurrency($account) ?? $native;
|
$currency = $this->getAccountCurrency($account) ?? $native;
|
||||||
$return = [
|
$return = [
|
||||||
'native_balance' => '0',
|
'native_balance' => '0',
|
||||||
];
|
];
|
||||||
Log::debug(sprintf('Now in finalAccountBalance("%s", "%s")', $account->name, $date->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('Now in finalAccountBalance("%s", "%s")', $account->name, $date->format('Y-m-d H:i:s')));
|
||||||
// first, the "balance", as described earlier.
|
// first, the "balance", as described earlier.
|
||||||
$array = $account->transactions()
|
$array = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->where('transactions.transaction_currency_id', $currency->id)
|
->where('transactions.transaction_currency_id', $currency->id)
|
||||||
->get(['transactions.amount'])->toArray();
|
->get(['transactions.amount'])->toArray()
|
||||||
|
;
|
||||||
$return['balance'] = $this->sumTransactions($array, 'amount');
|
$return['balance'] = $this->sumTransactions($array, 'amount');
|
||||||
Log::debug(sprintf('balance is %s', $return['balance']));
|
Log::debug(sprintf('balance is %s', $return['balance']));
|
||||||
// add virtual balance:
|
// add virtual balance:
|
||||||
@@ -290,9 +283,10 @@ class Steam
|
|||||||
// then, native balance (if necessary(
|
// then, native balance (if necessary(
|
||||||
if ($native->id !== $currency->id) {
|
if ($native->id !== $currency->id) {
|
||||||
$array = $account->transactions()
|
$array = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->get(['transactions.native_amount'])->toArray();
|
->get(['transactions.native_amount'])->toArray()
|
||||||
|
;
|
||||||
$return['native_balance'] = $this->sumTransactions($array, 'native_amount');
|
$return['native_balance'] = $this->sumTransactions($array, 'native_amount');
|
||||||
Log::debug(sprintf('native_balance is %s', $return['native_balance']));
|
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']);
|
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['balance']);
|
||||||
@@ -300,13 +294,15 @@ class Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// balance(s) in other currencies.
|
// balance(s) in other currencies.
|
||||||
$array = $account->transactions()
|
$array = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->get(['transaction_currencies.code', 'transactions.amount'])->toArray();
|
->get(['transaction_currencies.code', 'transactions.amount'])->toArray()
|
||||||
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
;
|
||||||
|
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
||||||
Log::debug('All others are (joined)', $others);
|
Log::debug('All others are (joined)', $others);
|
||||||
|
|
||||||
return array_merge($return, $others);
|
return array_merge($return, $others);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +314,7 @@ class Steam
|
|||||||
$groupKey = $item[$group] ?? 'unknown';
|
$groupKey = $item[$group] ?? 'unknown';
|
||||||
$return[$groupKey] = bcadd($return[$groupKey] ?? '0', $item[$field]);
|
$return[$groupKey] = bcadd($return[$groupKey] ?? '0', $item[$field]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +327,7 @@ class Steam
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$hostName = gethostbyaddr($ipAddress);
|
$hostName = gethostbyaddr($ipAddress);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $e) {
|
||||||
app('log')->error($e->getMessage());
|
app('log')->error($e->getMessage());
|
||||||
$hostName = $ipAddress;
|
$hostName = $ipAddress;
|
||||||
}
|
}
|
||||||
@@ -346,15 +343,15 @@ class Steam
|
|||||||
{
|
{
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
$set = auth()->user()->transactions()
|
$set = auth()->user()->transactions()
|
||||||
->whereIn('transactions.account_id', $accounts)
|
->whereIn('transactions.account_id', $accounts)
|
||||||
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
|
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
|
||||||
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
|
->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
|
||||||
;
|
;
|
||||||
|
|
||||||
/** @var Transaction $entry */
|
/** @var Transaction $entry */
|
||||||
foreach ($set as $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'));
|
$date->setTimezone(config('app.timezone'));
|
||||||
$list[$entry->account_id] = $date;
|
$list[$entry->account_id] = $date;
|
||||||
}
|
}
|
||||||
@@ -429,9 +426,9 @@ class Steam
|
|||||||
public function getSafeUrl(string $unknownUrl, string $safeUrl): string
|
public function getSafeUrl(string $unknownUrl, string $safeUrl): string
|
||||||
{
|
{
|
||||||
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
|
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
|
||||||
$returnUrl = $safeUrl;
|
$returnUrl = $safeUrl;
|
||||||
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
|
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
|
||||||
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
|
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
|
||||||
|
|
||||||
if (null !== $unknownHost && $unknownHost === $safeHost) {
|
if (null !== $unknownHost && $unknownHost === $safeHost) {
|
||||||
$returnUrl = $unknownUrl;
|
$returnUrl = $unknownUrl;
|
||||||
@@ -439,7 +436,7 @@ class Steam
|
|||||||
|
|
||||||
// URL must not lead to weird pages
|
// URL must not lead to weird pages
|
||||||
$forbiddenWords = ['jscript', 'json', 'debug', 'serviceworker', 'offline', 'delete', '/login', '/attachments/view'];
|
$forbiddenWords = ['jscript', 'json', 'debug', 'serviceworker', 'offline', 'delete', '/login', '/attachments/view'];
|
||||||
if (Str::contains($returnUrl, $forbiddenWords)) {
|
if (\Str::contains($returnUrl, $forbiddenWords)) {
|
||||||
$returnUrl = $safeUrl;
|
$returnUrl = $safeUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +465,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function floatalize(string $value): string
|
public function floatalize(string $value): string
|
||||||
{
|
{
|
||||||
$value = strtoupper($value);
|
$value = strtoupper($value);
|
||||||
if (!str_contains($value, 'E')) {
|
if (!str_contains($value, 'E')) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
@@ -537,7 +534,7 @@ class Steam
|
|||||||
if (-1 === bccomp($amount, '0')) {
|
if (-1 === bccomp($amount, '0')) {
|
||||||
$amount = bcmul($amount, '-1');
|
$amount = bcmul($amount, '-1');
|
||||||
}
|
}
|
||||||
} catch (ValueError $e) {
|
} catch (\ValueError $e) {
|
||||||
Log::error(sprintf('ValueError in Steam::positive("%s"): %s', $amount, $e->getMessage()));
|
Log::error(sprintf('ValueError in Steam::positive("%s"): %s', $amount, $e->getMessage()));
|
||||||
Log::error($e->getTraceAsString());
|
Log::error($e->getTraceAsString());
|
||||||
|
|
||||||
|
@@ -24,8 +24,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support\System;
|
namespace FireflyIII\Support\System;
|
||||||
|
|
||||||
use Artisan;
|
|
||||||
use Crypt;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Laravel\Passport\Console\KeysCommand;
|
use Laravel\Passport\Console\KeysCommand;
|
||||||
@@ -67,7 +65,7 @@ class OAuthKeys
|
|||||||
try {
|
try {
|
||||||
$privateKey = (string) app('fireflyconfig')->get(self::PRIVATE_KEY)?->data;
|
$privateKey = (string) app('fireflyconfig')->get(self::PRIVATE_KEY)?->data;
|
||||||
$publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_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(sprintf('Could not validate keysInDatabase(): %s', $e->getMessage()));
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
}
|
}
|
||||||
@@ -89,16 +87,16 @@ class OAuthKeys
|
|||||||
|
|
||||||
public static function generateKeys(): void
|
public static function generateKeys(): void
|
||||||
{
|
{
|
||||||
Artisan::registerCommand(new KeysCommand());
|
\Artisan::registerCommand(new KeysCommand());
|
||||||
Artisan::call('firefly-iii:laravel-passport-keys');
|
\Artisan::call('firefly-iii:laravel-passport-keys');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function storeKeysInDB(): void
|
public static function storeKeysInDB(): void
|
||||||
{
|
{
|
||||||
$private = storage_path('oauth-private.key');
|
$private = storage_path('oauth-private.key');
|
||||||
$public = storage_path('oauth-public.key');
|
$public = storage_path('oauth-public.key');
|
||||||
app('fireflyconfig')->set(self::PRIVATE_KEY, Crypt::encrypt(file_get_contents($private)));
|
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::PUBLIC_KEY, \Crypt::encrypt(file_get_contents($public)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,8 +108,8 @@ class OAuthKeys
|
|||||||
$publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_KEY)?->data;
|
$publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_KEY)?->data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$privateContent = Crypt::decrypt($privateKey);
|
$privateContent = \Crypt::decrypt($privateKey);
|
||||||
$publicContent = Crypt::decrypt($publicKey);
|
$publicContent = \Crypt::decrypt($publicKey);
|
||||||
} catch (DecryptException $e) {
|
} catch (DecryptException $e) {
|
||||||
app('log')->error('Could not decrypt pub/private keypair.');
|
app('log')->error('Could not decrypt pub/private keypair.');
|
||||||
app('log')->error($e->getMessage());
|
app('log')->error($e->getMessage());
|
||||||
@@ -122,8 +120,8 @@ class OAuthKeys
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$private = storage_path('oauth-private.key');
|
$private = storage_path('oauth-private.key');
|
||||||
$public = storage_path('oauth-public.key');
|
$public = storage_path('oauth-public.key');
|
||||||
file_put_contents($private, $privateContent);
|
file_put_contents($private, $privateContent);
|
||||||
file_put_contents($public, $publicContent);
|
file_put_contents($public, $publicContent);
|
||||||
|
|
||||||
|
@@ -108,8 +108,8 @@ class AmountFormat extends AbstractExtension
|
|||||||
return new TwigFunction(
|
return new TwigFunction(
|
||||||
'formatAmountBySymbol',
|
'formatAmountBySymbol',
|
||||||
static function (string $amount, string $symbol, ?int $decimalPlaces = null, ?bool $coloured = null): string {
|
static function (string $amount, string $symbol, ?int $decimalPlaces = null, ?bool $coloured = null): string {
|
||||||
$decimalPlaces ??= 2;
|
$decimalPlaces ??= 2;
|
||||||
$coloured ??= true;
|
$coloured ??= true;
|
||||||
$currency = new TransactionCurrency();
|
$currency = new TransactionCurrency();
|
||||||
$currency->symbol = $symbol;
|
$currency->symbol = $symbol;
|
||||||
$currency->decimal_places = $decimalPlaces;
|
$currency->decimal_places = $decimalPlaces;
|
||||||
|
@@ -78,6 +78,7 @@ class General extends AbstractExtension
|
|||||||
if (!$convertToNative || $currency->code === $native->code) {
|
if (!$convertToNative || $currency->code === $native->code) {
|
||||||
$strings[] = app('amount')->formatAnything($currency, $balance, false);
|
$strings[] = app('amount')->formatAnything($currency, $balance, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ('native_balance' === $key) {
|
if ('native_balance' === $key) {
|
||||||
@@ -85,6 +86,7 @@ class General extends AbstractExtension
|
|||||||
if ($convertToNative) {
|
if ($convertToNative) {
|
||||||
$strings[] = app('amount')->formatAnything($native, $balance, false);
|
$strings[] = app('amount')->formatAnything($native, $balance, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($key !== $currency->code) {
|
if ($key !== $currency->code) {
|
||||||
@@ -108,15 +110,15 @@ class General extends AbstractExtension
|
|||||||
static function (int $size): string {
|
static function (int $size): string {
|
||||||
// less than one GB, more than one MB
|
// less than one GB, more than one MB
|
||||||
if ($size < (1024 * 1024 * 2014) && $size >= (1024 * 1024)) {
|
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
|
// less than one MB
|
||||||
if ($size < (1024 * 1024)) {
|
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':
|
case 'application/pdf':
|
||||||
return 'fa-file-pdf-o';
|
return 'fa-file-pdf-o';
|
||||||
|
|
||||||
// image
|
// image
|
||||||
case 'image/png':
|
case 'image/png':
|
||||||
case 'image/jpeg':
|
case 'image/jpeg':
|
||||||
case 'image/svg+xml':
|
case 'image/svg+xml':
|
||||||
@@ -147,7 +149,7 @@ class General extends AbstractExtension
|
|||||||
case 'application/vnd.oasis.opendocument.image':
|
case 'application/vnd.oasis.opendocument.image':
|
||||||
return 'fa-file-image-o';
|
return 'fa-file-image-o';
|
||||||
|
|
||||||
// MS word
|
// MS word
|
||||||
case 'application/msword':
|
case 'application/msword':
|
||||||
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
||||||
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template':
|
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template':
|
||||||
@@ -163,7 +165,7 @@ class General extends AbstractExtension
|
|||||||
case 'application/vnd.oasis.opendocument.text-master':
|
case 'application/vnd.oasis.opendocument.text-master':
|
||||||
return 'fa-file-word-o';
|
return 'fa-file-word-o';
|
||||||
|
|
||||||
// MS excel
|
// MS excel
|
||||||
case 'application/vnd.ms-excel':
|
case 'application/vnd.ms-excel':
|
||||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
||||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template':
|
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template':
|
||||||
@@ -174,7 +176,7 @@ class General extends AbstractExtension
|
|||||||
case 'application/vnd.oasis.opendocument.spreadsheet-template':
|
case 'application/vnd.oasis.opendocument.spreadsheet-template':
|
||||||
return 'fa-file-excel-o';
|
return 'fa-file-excel-o';
|
||||||
|
|
||||||
// MS powerpoint
|
// MS powerpoint
|
||||||
case 'application/vnd.ms-powerpoint':
|
case 'application/vnd.ms-powerpoint':
|
||||||
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
|
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
|
||||||
case 'application/vnd.openxmlformats-officedocument.presentationml.template':
|
case 'application/vnd.openxmlformats-officedocument.presentationml.template':
|
||||||
@@ -186,7 +188,7 @@ class General extends AbstractExtension
|
|||||||
case 'application/vnd.oasis.opendocument.presentation-template':
|
case 'application/vnd.oasis.opendocument.presentation-template':
|
||||||
return 'fa-file-powerpoint-o';
|
return 'fa-file-powerpoint-o';
|
||||||
|
|
||||||
// calc
|
// calc
|
||||||
case 'application/vnd.sun.xml.draw':
|
case 'application/vnd.sun.xml.draw':
|
||||||
case 'application/vnd.sun.xml.draw.template':
|
case 'application/vnd.sun.xml.draw.template':
|
||||||
case 'application/vnd.stardivision.draw':
|
case 'application/vnd.stardivision.draw':
|
||||||
@@ -282,7 +284,7 @@ class General extends AbstractExtension
|
|||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$route = $args[0]; // name of the route.
|
$route = $args[0]; // name of the route.
|
||||||
|
|
||||||
if (Route::getCurrentRoute()->getName() === $route) {
|
if (\Route::getCurrentRoute()->getName() === $route) {
|
||||||
return 'active';
|
return 'active';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +304,7 @@ class General extends AbstractExtension
|
|||||||
static function (): string {
|
static function (): string {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$route = $args[0]; // name of the route.
|
$route = $args[0]; // name of the route.
|
||||||
$name = Route::getCurrentRoute()->getName() ?? '';
|
$name = \Route::getCurrentRoute()->getName() ?? '';
|
||||||
if (str_contains($name, $route)) {
|
if (str_contains($name, $route)) {
|
||||||
return 'active';
|
return 'active';
|
||||||
}
|
}
|
||||||
@@ -322,11 +324,11 @@ class General extends AbstractExtension
|
|||||||
'activeRoutePartialObjectType',
|
'activeRoutePartialObjectType',
|
||||||
static function ($context): string {
|
static function ($context): string {
|
||||||
[, $route, $objectType] = func_get_args();
|
[, $route, $objectType] = func_get_args();
|
||||||
$activeObjectType = $context['objectType'] ?? false;
|
$activeObjectType = $context['objectType'] ?? false;
|
||||||
|
|
||||||
if ($objectType === $activeObjectType
|
if ($objectType === $activeObjectType
|
||||||
&& false !== stripos(
|
&& false !== stripos(
|
||||||
Route::getCurrentRoute()->getName(),
|
\Route::getCurrentRoute()->getName(),
|
||||||
$route
|
$route
|
||||||
)) {
|
)) {
|
||||||
return 'active';
|
return 'active';
|
||||||
@@ -349,7 +351,7 @@ class General extends AbstractExtension
|
|||||||
static function (): string {
|
static function (): string {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$route = $args[0]; // name of the route.
|
$route = $args[0]; // name of the route.
|
||||||
$name = Route::getCurrentRoute()->getName() ?? '';
|
$name = \Route::getCurrentRoute()->getName() ?? '';
|
||||||
if (str_contains($name, $route)) {
|
if (str_contains($name, $route)) {
|
||||||
return 'menu-open';
|
return 'menu-open';
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support\Twig;
|
namespace FireflyIII\Support\Twig;
|
||||||
|
|
||||||
use Config;
|
|
||||||
use Twig\Extension\AbstractExtension;
|
use Twig\Extension\AbstractExtension;
|
||||||
use Twig\TwigFunction;
|
use Twig\TwigFunction;
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ class Rule extends AbstractExtension
|
|||||||
$possibleTriggers = [];
|
$possibleTriggers = [];
|
||||||
foreach ($ruleTriggers as $key) {
|
foreach ($ruleTriggers as $key) {
|
||||||
if ('user_action' !== $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);
|
unset($ruleTriggers);
|
||||||
@@ -81,10 +80,10 @@ class Rule extends AbstractExtension
|
|||||||
'allRuleActions',
|
'allRuleActions',
|
||||||
static function () {
|
static function () {
|
||||||
// array of valid values for actions
|
// array of valid values for actions
|
||||||
$ruleActions = array_keys(Config::get('firefly.rule-actions'));
|
$ruleActions = array_keys(\Config::get('firefly.rule-actions'));
|
||||||
$possibleActions = [];
|
$possibleActions = [];
|
||||||
foreach ($ruleActions as $key) {
|
foreach ($ruleActions as $key) {
|
||||||
$possibleActions[$key] = (string) trans('firefly.rule_action_' . $key . '_choice');
|
$possibleActions[$key] = (string) trans('firefly.rule_action_'.$key.'_choice');
|
||||||
}
|
}
|
||||||
unset($ruleActions);
|
unset($ruleActions);
|
||||||
asort($possibleActions);
|
asort($possibleActions);
|
||||||
|
@@ -25,7 +25,6 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support\Twig;
|
namespace FireflyIII\Support\Twig;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
@@ -87,7 +86,7 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
$colored = false;
|
$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) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
$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
|
private function foreignJournalArrayAmount(array $array): string
|
||||||
{
|
{
|
||||||
$type = $array['transaction_type_type'] ?? TransactionType::WITHDRAWAL;
|
$type = $array['transaction_type_type'] ?? TransactionType::WITHDRAWAL;
|
||||||
$amount = $array['foreign_amount'] ?? '0';
|
$amount = $array['foreign_amount'] ?? '0';
|
||||||
$colored = true;
|
$colored = true;
|
||||||
|
|
||||||
$sourceType = $array['source_account_type'] ?? 'invalid';
|
$sourceType = $array['source_account_type'] ?? 'invalid';
|
||||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||||
@@ -130,7 +129,7 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
if (TransactionType::TRANSFER === $type) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$colored = false;
|
$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) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
||||||
}
|
}
|
||||||
@@ -171,12 +170,12 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
$colored = true;
|
$colored = true;
|
||||||
$sourceType = $first->account()->first()->accountType()->first()->type;
|
$sourceType = $first->account()->first()->accountType()->first()->type;
|
||||||
|
|
||||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||||
|
|
||||||
if (TransactionType::TRANSFER === $type) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$colored = false;
|
$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) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
$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
|
private function foreignJournalObjectAmount(TransactionJournal $journal): string
|
||||||
{
|
{
|
||||||
$type = $journal->transactionType->type;
|
$type = $journal->transactionType->type;
|
||||||
|
|
||||||
/** @var Transaction $first */
|
/** @var Transaction $first */
|
||||||
$first = $journal->transactions()->where('amount', '<', 0)->first();
|
$first = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
@@ -206,12 +205,12 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
$colored = true;
|
$colored = true;
|
||||||
$sourceType = $first->account()->first()->accountType()->first()->type;
|
$sourceType = $first->account()->first()->accountType()->first()->type;
|
||||||
|
|
||||||
$amount = $this->signAmount($amount, $type, $sourceType);
|
$amount = $this->signAmount($amount, $type, $sourceType);
|
||||||
|
|
||||||
if (TransactionType::TRANSFER === $type) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$colored = false;
|
$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) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
$result = sprintf('<span class="text-info money-transfer">%s</span>', $result);
|
||||||
}
|
}
|
||||||
@@ -224,11 +223,12 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
return new TwigFunction(
|
return new TwigFunction(
|
||||||
'journalHasMeta',
|
'journalHasMeta',
|
||||||
static function (int $journalId, string $metaField) {
|
static function (int $journalId, string $metaField) {
|
||||||
$count = DB::table('journal_meta')
|
$count = \DB::table('journal_meta')
|
||||||
->where('name', $metaField)
|
->where('name', $metaField)
|
||||||
->where('transaction_journal_id', $journalId)
|
->where('transaction_journal_id', $journalId)
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->count();
|
->count()
|
||||||
|
;
|
||||||
|
|
||||||
return 1 === $count;
|
return 1 === $count;
|
||||||
}
|
}
|
||||||
@@ -241,11 +241,12 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
'journalGetMetaDate',
|
'journalGetMetaDate',
|
||||||
static function (int $journalId, string $metaField) {
|
static function (int $journalId, string $metaField) {
|
||||||
/** @var null|TransactionJournalMeta $entry */
|
/** @var null|TransactionJournalMeta $entry */
|
||||||
$entry = DB::table('journal_meta')
|
$entry = \DB::table('journal_meta')
|
||||||
->where('name', $metaField)
|
->where('name', $metaField)
|
||||||
->where('transaction_journal_id', $journalId)
|
->where('transaction_journal_id', $journalId)
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
if (null === $entry) {
|
if (null === $entry) {
|
||||||
return today(config('app.timezone'));
|
return today(config('app.timezone'));
|
||||||
}
|
}
|
||||||
@@ -261,11 +262,12 @@ class TransactionGroupTwig extends AbstractExtension
|
|||||||
'journalGetMetaField',
|
'journalGetMetaField',
|
||||||
static function (int $journalId, string $metaField) {
|
static function (int $journalId, string $metaField) {
|
||||||
/** @var null|TransactionJournalMeta $entry */
|
/** @var null|TransactionJournalMeta $entry */
|
||||||
$entry = DB::table('journal_meta')
|
$entry = \DB::table('journal_meta')
|
||||||
->where('name', $metaField)
|
->where('name', $metaField)
|
||||||
->where('transaction_journal_id', $journalId)
|
->where('transaction_journal_id', $journalId)
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->first();
|
->first()
|
||||||
|
;
|
||||||
if (null === $entry) {
|
if (null === $entry) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@@ -14,17 +14,14 @@
|
|||||||
"/public/v1/js/app.js.LICENSE.txt": "/public/v1/js/app.js.LICENSE.txt",
|
"/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": "/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/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": "/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/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": "/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/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": "/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/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": "/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/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-reconciliation.js": "/public/v1/js/ff/accounts/edit-reconciliation.js",
|
||||||
"/public/v1/js/ff/accounts/edit.js": "/public/v1/js/ff/accounts/edit.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-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/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/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/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/accounting.min.js": "/public/v1/js/lib/accounting.min.js",
|
||||||
"/public/v1/js/lib/bootstrap-multiselect.js": "/public/v1/js/lib/bootstrap-multiselect.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/lib/vue.js": "/public/v1/js/lib/vue.js",
|
||||||
"/public/v1/js/profile.js": "/public/v1/js/profile.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/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": "/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/create.js.LICENSE.txt": "/public/v1/js/webhooks/create.js.LICENSE.txt",
|
||||||
"/public/v1/js/webhooks/edit.js": "/public/v1/js/webhooks/edit.js",
|
"/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.",
|
"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_rates": "Wechselkurse",
|
||||||
"header_exchange_rates_table": "Tabelle mit Wechselkursen",
|
"header_exchange_rates_table": "Tabelle mit Wechselkursen",
|
||||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
"help_rate_form": "An diesem Tag, wie viele {to} werden Sie f\u00fcr einen {from} bekommen?",
|
||||||
"add_new_rate": "Add a new exchange rate",
|
"add_new_rate": "Neuen Wechselkurs hinzuf\u00fcgen",
|
||||||
"save_new_rate": "Save new rate"
|
"save_new_rate": "Neuen Kurs speichern"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
"webhook_delivery": "Zustellung",
|
"webhook_delivery": "Zustellung",
|
||||||
"from_currency_to_currency": "{from} → {to}",
|
"from_currency_to_currency": "{from} → {to}",
|
||||||
"to_currency_from_currency": "{to} → {from}",
|
"to_currency_from_currency": "{to} → {from}",
|
||||||
"rate": "Rate"
|
"rate": "Kurs"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"active": "Aktiv?",
|
"active": "Aktiv?",
|
||||||
|
@@ -130,15 +130,15 @@
|
|||||||
"response": "Odpowied\u017a",
|
"response": "Odpowied\u017a",
|
||||||
"visit_webhook_url": "Odwied\u017a adres URL webhooka",
|
"visit_webhook_url": "Odwied\u017a adres URL webhooka",
|
||||||
"reset_webhook_secret": "Resetuj sekret webhooka",
|
"reset_webhook_secret": "Resetuj sekret webhooka",
|
||||||
"header_exchange_rates": "Exchange rates",
|
"header_exchange_rates": "Kursy wymiany",
|
||||||
"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_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": "Between {from} and {to} (and the other way around)",
|
"exchange_rates_from_to": "Pomi\u0119dzy {from} i {to} (i odwrotnie)",
|
||||||
"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.",
|
"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": "Exchange rates",
|
"header_exchange_rates_rates": "Kursy wymiany",
|
||||||
"header_exchange_rates_table": "Table with exchange rates",
|
"header_exchange_rates_table": "Tabela z kursami wymiany walut",
|
||||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
"help_rate_form": "W tym dniu, ile {to} otrzymasz za jeden {from}?",
|
||||||
"add_new_rate": "Add a new exchange rate",
|
"add_new_rate": "Dodaj nowy kurs wymiany",
|
||||||
"save_new_rate": "Save new rate"
|
"save_new_rate": "Zapisz nowy kurs"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
"webhook_delivery": "Dor\u0119czenie",
|
"webhook_delivery": "Dor\u0119czenie",
|
||||||
"from_currency_to_currency": "{from} → {to}",
|
"from_currency_to_currency": "{from} → {to}",
|
||||||
"to_currency_from_currency": "{to} → {from}",
|
"to_currency_from_currency": "{to} → {from}",
|
||||||
"rate": "Rate"
|
"rate": "Kurs"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"active": "Jest aktywny?",
|
"active": "Jest aktywny?",
|
||||||
|
@@ -1320,9 +1320,9 @@ return [
|
|||||||
'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?',
|
'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_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_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' => '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_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_native_help' => 'Display native amounts',
|
||||||
'pref_custom_fiscal_year' => 'Fiscal year settings',
|
'pref_custom_fiscal_year' => 'Fiscal year settings',
|
||||||
'pref_custom_fiscal_year_label' => 'Enabled',
|
'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',
|
'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',
|
||||||
|
Reference in New Issue
Block a user