Optimize queries for statistics.

This commit is contained in:
James Cole
2025-09-26 06:05:37 +02:00
parent 08879d31ba
commit 4ec2fcdb8a
92 changed files with 6499 additions and 6514 deletions

View File

@@ -51,55 +51,24 @@ class AccountForm
$repository = $this->getAccountRepository();
$grouped = $this->getAccountsGrouped($types, $repository);
$cash = $repository->getCashAccount();
$key = (string) trans('firefly.cash_account_type');
$grouped[$key][$cash->id] = sprintf('(%s)', (string) trans('firefly.cash'));
$key = (string)trans('firefly.cash_account_type');
$grouped[$key][$cash->id] = sprintf('(%s)', (string)trans('firefly.cash'));
return $this->select($name, $grouped, $value, $options);
}
private function getAccountsGrouped(array $types, ?AccountRepositoryInterface $repository = null): array
{
if (!$repository instanceof AccountRepositoryInterface) {
$repository = $this->getAccountRepository();
}
$accountList = $repository->getActiveAccountsByType($types);
$liabilityTypes = [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::LOAN->value];
$grouped = [];
/** @var Account $account */
foreach ($accountList as $account) {
$role = (string) $repository->getMetaValue($account, 'account_role');
if (in_array($account->accountType->type, $liabilityTypes, true)) {
$role = sprintf('l_%s', $account->accountType->type);
}
if ('' === $role) {
$role = 'no_account_type';
if (AccountTypeEnum::EXPENSE->value === $account->accountType->type) {
$role = 'expense_account';
}
if (AccountTypeEnum::REVENUE->value === $account->accountType->type) {
$role = 'revenue_account';
}
}
$key = (string) trans(sprintf('firefly.opt_group_%s', $role));
$grouped[$key][$account->id] = $account->name;
}
return $grouped;
}
/**
* Grouped dropdown list of all accounts that are valid as the destination of a withdrawal.
*/
public function activeWithdrawalDestinations(string $name, mixed $value = null, ?array $options = null): string
{
$types = [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::EXPENSE->value];
$repository = $this->getAccountRepository();
$grouped = $this->getAccountsGrouped($types, $repository);
$types = [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::EXPENSE->value];
$repository = $this->getAccountRepository();
$grouped = $this->getAccountsGrouped($types, $repository);
$cash = $repository->getCashAccount();
$key = (string) trans('firefly.cash_account_type');
$grouped[$key][$cash->id] = sprintf('(%s)', (string) trans('firefly.cash'));
$key = (string)trans('firefly.cash_account_type');
$grouped[$key][$cash->id] = sprintf('(%s)', (string)trans('firefly.cash'));
return $this->select($name, $grouped, $value, $options);
}
@@ -111,15 +80,15 @@ class AccountForm
*/
public function assetAccountCheckList(string $name, ?array $options = null): string
{
$options ??= [];
$options ??= [];
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = request()->old($name) ?? [];
// get all asset accounts:
$types = [AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value];
$grouped = $this->getAccountsGrouped($types);
$types = [AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value];
$grouped = $this->getAccountsGrouped($types);
unset($options['class']);
@@ -173,4 +142,35 @@ class AccountForm
return $this->select($name, $grouped, $value, $options);
}
private function getAccountsGrouped(array $types, ?AccountRepositoryInterface $repository = null): array
{
if (!$repository instanceof AccountRepositoryInterface) {
$repository = $this->getAccountRepository();
}
$accountList = $repository->getActiveAccountsByType($types);
$liabilityTypes = [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::LOAN->value];
$grouped = [];
/** @var Account $account */
foreach ($accountList as $account) {
$role = (string)$repository->getMetaValue($account, 'account_role');
if (in_array($account->accountType->type, $liabilityTypes, true)) {
$role = sprintf('l_%s', $account->accountType->type);
}
if ('' === $role) {
$role = 'no_account_type';
if (AccountTypeEnum::EXPENSE->value === $account->accountType->type) {
$role = 'expense_account';
}
if (AccountTypeEnum::REVENUE->value === $account->accountType->type) {
$role = 'revenue_account';
}
}
$key = (string)trans(sprintf('firefly.opt_group_%s', $role));
$grouped[$key][$account->id] = $account->name;
}
return $grouped;
}
}

View File

@@ -49,60 +49,6 @@ class CurrencyForm
return $this->currencyField($name, 'amount', $value, $options);
}
/**
* @phpstan-param view-string $view
*
* @throws FireflyException
*/
protected function currencyField(string $name, string $view, mixed $value = null, ?array $options = null): string
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$options['step'] = 'any';
$primaryCurrency = $options['currency'] ?? app('amount')->getPrimaryCurrency();
/** @var Collection $currencies */
$currencies = app('amount')->getCurrencies();
unset($options['currency'], $options['placeholder']);
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
$preFilled = session('preFilled');
if (!is_array($preFilled)) {
$preFilled = [];
}
$key = 'amount_currency_id_'.$name;
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $primaryCurrency->id;
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
// find this currency in set of currencies:
foreach ($currencies as $currency) {
if ($currency->id === $sentCurrencyId) {
$primaryCurrency = $currency;
app('log')->debug(sprintf('default currency is now %s', $primaryCurrency->code));
break;
}
}
// make sure value is formatted nicely:
if (null !== $value && '' !== $value) {
$value = app('steam')->bcround($value, $primaryCurrency->decimal_places);
}
try {
$html = view('form.'.$view, compact('primaryCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
} catch (Throwable $e) {
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
$html = 'Could not render currencyField.';
throw new FireflyException($html, 0, $e);
}
return $html;
}
/**
* TODO describe and cleanup.
*
@@ -115,6 +61,52 @@ class CurrencyForm
return $this->allCurrencyField($name, 'balance', $value, $options);
}
/**
* TODO cleanup and describe
*
* @param mixed $value
*/
public function currencyList(string $name, $value = null, ?array $options = null): string
{
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
// get all currencies:
$list = $currencyRepos->get();
$array = [];
/** @var TransactionCurrency $currency */
foreach ($list as $currency) {
$array[$currency->id] = $currency->name . ' (' . $currency->symbol . ')';
}
return $this->select($name, $array, $value, $options);
}
/**
* TODO cleanup and describe
*
* @param mixed $value
*/
public function currencyListEmpty(string $name, $value = null, ?array $options = null): string
{
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
// get all currencies:
$list = $currencyRepos->get();
$array = [
0 => (string)trans('firefly.no_currency'),
];
/** @var TransactionCurrency $currency */
foreach ($list as $currency) {
$array[$currency->id] = $currency->name . ' (' . $currency->symbol . ')';
}
return $this->select($name, $array, $value, $options);
}
/**
* TODO describe and cleanup
*
@@ -132,16 +124,16 @@ class CurrencyForm
$primaryCurrency = $options['currency'] ?? app('amount')->getPrimaryCurrency();
/** @var Collection $currencies */
$currencies = app('amount')->getAllCurrencies();
$currencies = app('amount')->getAllCurrencies();
unset($options['currency'], $options['placeholder']);
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
$preFilled = session('preFilled');
$preFilled = session('preFilled');
if (!is_array($preFilled)) {
$preFilled = [];
}
$key = 'amount_currency_id_'.$name;
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $primaryCurrency->id;
$key = 'amount_currency_id_' . $name;
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int)$preFilled[$key] : $primaryCurrency->id;
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
@@ -161,7 +153,7 @@ class CurrencyForm
}
try {
$html = view('form.'.$view, compact('primaryCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
$html = view('form.' . $view, compact('primaryCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
} catch (Throwable $e) {
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
$html = 'Could not render currencyField.';
@@ -173,48 +165,56 @@ class CurrencyForm
}
/**
* TODO cleanup and describe
* @phpstan-param view-string $view
*
* @param mixed $value
* @throws FireflyException
*/
public function currencyList(string $name, $value = null, ?array $options = null): string
protected function currencyField(string $name, string $view, mixed $value = null, ?array $options = null): string
{
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$options['step'] = 'any';
$primaryCurrency = $options['currency'] ?? app('amount')->getPrimaryCurrency();
// get all currencies:
$list = $currencyRepos->get();
$array = [];
/** @var Collection $currencies */
$currencies = app('amount')->getCurrencies();
unset($options['currency'], $options['placeholder']);
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
$preFilled = session('preFilled');
if (!is_array($preFilled)) {
$preFilled = [];
}
$key = 'amount_currency_id_' . $name;
$sentCurrencyId = array_key_exists($key, $preFilled) ? (int)$preFilled[$key] : $primaryCurrency->id;
/** @var TransactionCurrency $currency */
foreach ($list as $currency) {
$array[$currency->id] = $currency->name.' ('.$currency->symbol.')';
app('log')->debug(sprintf('Sent currency ID is %d', $sentCurrencyId));
// find this currency in set of currencies:
foreach ($currencies as $currency) {
if ($currency->id === $sentCurrencyId) {
$primaryCurrency = $currency;
app('log')->debug(sprintf('default currency is now %s', $primaryCurrency->code));
break;
}
}
return $this->select($name, $array, $value, $options);
}
/**
* TODO cleanup and describe
*
* @param mixed $value
*/
public function currencyListEmpty(string $name, $value = null, ?array $options = null): string
{
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
// get all currencies:
$list = $currencyRepos->get();
$array = [
0 => (string) trans('firefly.no_currency'),
];
/** @var TransactionCurrency $currency */
foreach ($list as $currency) {
$array[$currency->id] = $currency->name.' ('.$currency->symbol.')';
// make sure value is formatted nicely:
if (null !== $value && '' !== $value) {
$value = app('steam')->bcround($value, $primaryCurrency->decimal_places);
}
return $this->select($name, $array, $value, $options);
try {
$html = view('form.' . $view, compact('primaryCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
} catch (Throwable $e) {
app('log')->debug(sprintf('Could not render currencyField(): %s', $e->getMessage()));
$html = 'Could not render currencyField.';
throw new FireflyException($html, 0, $e);
}
return $html;
}
}

View File

@@ -36,7 +36,7 @@ trait FormSupport
{
public function multiSelect(string $name, ?array $list = null, mixed $selected = null, ?array $options = null): string
{
$list ??= [];
$list ??= [];
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
@@ -54,15 +54,26 @@ trait FormSupport
return $html;
}
protected function label(string $name, ?array $options = null): string
/**
* @param mixed $selected
*/
public function select(string $name, ?array $list = null, $selected = null, ?array $options = null): string
{
$options ??= [];
if (array_key_exists('label', $options)) {
return $options['label'];
}
$name = str_replace('[]', '', $name);
$list ??= [];
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = $this->fillFieldValue($name, $selected);
unset($options['autocomplete'], $options['placeholder']);
return (string)trans('form.'.$name);
try {
$html = view('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
} catch (Throwable $e) {
app('log')->debug(sprintf('Could not render select(): %s', $e->getMessage()));
$html = 'Could not render select.';
}
return $html;
}
/**
@@ -70,29 +81,16 @@ trait FormSupport
*/
protected function expandOptionArray(string $name, $label, ?array $options = null): array
{
$options ??= [];
$options ??= [];
$name = str_replace('[]', '', $name);
$options['class'] = 'form-control';
$options['id'] = 'ffInput_'.$name;
$options['id'] = 'ffInput_' . $name;
$options['autocomplete'] = 'off';
$options['placeholder'] = ucfirst((string)$label);
return $options;
}
protected function getHolderClasses(string $name): string
{
// Get errors from session:
/** @var null|MessageBag $errors */
$errors = session('errors');
if (null !== $errors && $errors->has($name)) {
return 'form-group has-error has-feedback';
}
return 'form-group';
}
/**
* @param null|mixed $value
*
@@ -116,28 +114,6 @@ trait FormSupport
return $value;
}
/**
* @param mixed $selected
*/
public function select(string $name, ?array $list = null, $selected = null, ?array $options = null): string
{
$list ??= [];
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = $this->fillFieldValue($name, $selected);
unset($options['autocomplete'], $options['placeholder']);
try {
$html = view('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
} catch (Throwable $e) {
app('log')->debug(sprintf('Could not render select(): %s', $e->getMessage()));
$html = 'Could not render select.';
}
return $html;
}
protected function getAccountRepository(): AccountRepositoryInterface
{
return app(AccountRepositoryInterface::class);
@@ -147,4 +123,28 @@ trait FormSupport
{
return today(config('app.timezone'));
}
protected function getHolderClasses(string $name): string
{
// Get errors from session:
/** @var null|MessageBag $errors */
$errors = session('errors');
if (null !== $errors && $errors->has($name)) {
return 'form-group has-error has-feedback';
}
return 'form-group';
}
protected function label(string $name, ?array $options = null): string
{
$options ??= [];
if (array_key_exists('label', $options)) {
return $options['label'];
}
$name = str_replace('[]', '', $name);
return (string)trans('form.' . $name);
}
}

View File

@@ -47,7 +47,7 @@ class PiggyBankForm
/** @var PiggyBankRepositoryInterface $repository */
$repository = app(PiggyBankRepositoryInterface::class);
$piggyBanks = $repository->getPiggyBanksWithAmount();
$title = (string) trans('firefly.default_group_title_name');
$title = (string)trans('firefly.default_group_title_name');
$array = [];
$subList = [
0 => [
@@ -55,21 +55,21 @@ class PiggyBankForm
'title' => $title,
],
'piggies' => [
(string) trans('firefly.none_in_select_list'),
(string)trans('firefly.none_in_select_list'),
],
],
];
/** @var PiggyBank $piggy */
foreach ($piggyBanks as $piggy) {
$group = $piggy->objectGroups->first();
$groupTitle = null;
$groupOrder = 0;
$group = $piggy->objectGroups->first();
$groupTitle = null;
$groupOrder = 0;
if (null !== $group) {
$groupTitle = $group->title;
$groupOrder = $group->order;
}
$subList[$groupOrder] ??= [
$subList[$groupOrder] ??= [
'group' => [
'title' => $groupTitle,
],

View File

@@ -41,8 +41,8 @@ class RuleForm
$groupRepos = app(RuleGroupRepositoryInterface::class);
// get all currencies:
$list = $groupRepos->get();
$array = [];
$list = $groupRepos->get();
$array = [];
/** @var RuleGroup $group */
foreach ($list as $group) {
@@ -57,21 +57,21 @@ class RuleForm
*/
public function ruleGroupListWithEmpty(string $name, $value = null, ?array $options = null): string
{
$options ??= [];
$options ??= [];
$options['class'] = 'form-control';
/** @var RuleGroupRepositoryInterface $groupRepos */
$groupRepos = app(RuleGroupRepositoryInterface::class);
$groupRepos = app(RuleGroupRepositoryInterface::class);
// get all currencies:
$list = $groupRepos->get();
$array = [
0 => (string) trans('firefly.none_in_select_list'),
$list = $groupRepos->get();
$array = [
0 => (string)trans('firefly.none_in_select_list'),
];
/** @var RuleGroup $group */
foreach ($list as $group) {
if (array_key_exists('hidden', $options) && (int) $options['hidden'] !== $group->id) {
if (array_key_exists('hidden', $options) && (int)$options['hidden'] !== $group->id) {
$array[$group->id] = $group->title;
}
}