mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-14 00:04:24 +00:00
Allow account endpoint to be filtered on various fields.
This commit is contained in:
@@ -30,63 +30,62 @@ use FireflyIII\Models\AccountType;
|
||||
*/
|
||||
trait AccountFilter
|
||||
{
|
||||
protected array $types = [
|
||||
'all' => [
|
||||
AccountType::DEFAULT,
|
||||
AccountType::CASH,
|
||||
AccountType::ASSET,
|
||||
AccountType::EXPENSE,
|
||||
AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::BENEFICIARY,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
AccountType::DEBT,
|
||||
AccountType::MORTGAGE,
|
||||
],
|
||||
'asset' => [AccountType::DEFAULT, AccountType::ASSET],
|
||||
'cash' => [AccountType::CASH],
|
||||
'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY],
|
||||
'revenue' => [AccountType::REVENUE],
|
||||
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION],
|
||||
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION],
|
||||
'liability' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
'liabilities' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
AccountType::DEFAULT => [AccountType::DEFAULT],
|
||||
AccountType::CASH => [AccountType::CASH],
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
AccountType::EXPENSE => [AccountType::EXPENSE],
|
||||
AccountType::REVENUE => [AccountType::REVENUE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::BENEFICIARY => [AccountType::BENEFICIARY],
|
||||
AccountType::IMPORT => [AccountType::IMPORT],
|
||||
AccountType::RECONCILIATION => [AccountType::RECONCILIATION],
|
||||
AccountType::LOAN => [AccountType::LOAN],
|
||||
AccountType::MORTGAGE => [AccountType::MORTGAGE],
|
||||
AccountType::DEBT => [AccountType::DEBT],
|
||||
AccountType::CREDITCARD => [AccountType::CREDITCARD],
|
||||
'default account' => [AccountType::DEFAULT],
|
||||
'cash account' => [AccountType::CASH],
|
||||
'asset account' => [AccountType::ASSET],
|
||||
'expense account' => [AccountType::EXPENSE],
|
||||
'revenue account' => [AccountType::REVENUE],
|
||||
'initial balance account' => [AccountType::INITIAL_BALANCE],
|
||||
'reconciliation' => [AccountType::RECONCILIATION],
|
||||
'loan' => [AccountType::LOAN],
|
||||
'mortgage' => [AccountType::MORTGAGE],
|
||||
'debt' => [AccountType::DEBT],
|
||||
'credit card' => [AccountType::CREDITCARD],
|
||||
'credit-card' => [AccountType::CREDITCARD],
|
||||
'creditcard' => [AccountType::CREDITCARD],
|
||||
'cc' => [AccountType::CREDITCARD],
|
||||
];
|
||||
/**
|
||||
* All the available types.
|
||||
*/
|
||||
protected function mapAccountTypes(string $type): array
|
||||
{
|
||||
$types = [
|
||||
'all' => [
|
||||
AccountType::DEFAULT,
|
||||
AccountType::CASH,
|
||||
AccountType::ASSET,
|
||||
AccountType::EXPENSE,
|
||||
AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::BENEFICIARY,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
AccountType::DEBT,
|
||||
AccountType::MORTGAGE,
|
||||
],
|
||||
'asset' => [AccountType::DEFAULT, AccountType::ASSET],
|
||||
'cash' => [AccountType::CASH],
|
||||
'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY],
|
||||
'revenue' => [AccountType::REVENUE],
|
||||
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION],
|
||||
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION],
|
||||
'liability' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
'liabilities' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
AccountType::DEFAULT => [AccountType::DEFAULT],
|
||||
AccountType::CASH => [AccountType::CASH],
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
AccountType::EXPENSE => [AccountType::EXPENSE],
|
||||
AccountType::REVENUE => [AccountType::REVENUE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::BENEFICIARY => [AccountType::BENEFICIARY],
|
||||
AccountType::IMPORT => [AccountType::IMPORT],
|
||||
AccountType::RECONCILIATION => [AccountType::RECONCILIATION],
|
||||
AccountType::LOAN => [AccountType::LOAN],
|
||||
AccountType::MORTGAGE => [AccountType::MORTGAGE],
|
||||
AccountType::DEBT => [AccountType::DEBT],
|
||||
AccountType::CREDITCARD => [AccountType::CREDITCARD],
|
||||
'default account' => [AccountType::DEFAULT],
|
||||
'cash account' => [AccountType::CASH],
|
||||
'asset account' => [AccountType::ASSET],
|
||||
'expense account' => [AccountType::EXPENSE],
|
||||
'revenue account' => [AccountType::REVENUE],
|
||||
'initial balance account' => [AccountType::INITIAL_BALANCE],
|
||||
'reconciliation' => [AccountType::RECONCILIATION],
|
||||
'loan' => [AccountType::LOAN],
|
||||
'mortgage' => [AccountType::MORTGAGE],
|
||||
'debt' => [AccountType::DEBT],
|
||||
'credit card' => [AccountType::CREDITCARD],
|
||||
'credit-card' => [AccountType::CREDITCARD],
|
||||
'creditcard' => [AccountType::CREDITCARD],
|
||||
'cc' => [AccountType::CREDITCARD],
|
||||
];
|
||||
|
||||
return $types[$type] ?? $types['all'];
|
||||
return $this->types[$type] ?? $this->types['all'];
|
||||
}
|
||||
}
|
||||
|
@@ -23,8 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use LaravelJsonApi\Core\Query\FilterParameters;
|
||||
use LaravelJsonApi\Core\Query\SortFields;
|
||||
|
||||
@@ -51,35 +53,80 @@ trait ExpandsQuery
|
||||
return $query;
|
||||
}
|
||||
|
||||
private function parseAccountTypeFilter(array $value): array
|
||||
{
|
||||
$return = [];
|
||||
foreach ($value as $entry) {
|
||||
$return = array_merge($return, $this->mapAccountTypes($entry));
|
||||
}
|
||||
return array_unique($return);
|
||||
}
|
||||
|
||||
private function parseAllFilters(string $class, FilterParameters $filters): array
|
||||
{
|
||||
$config = config('api.valid_api_filters')[$class];
|
||||
$parsed = [];
|
||||
foreach ($filters->all() as $filter) {
|
||||
$key = $filter->key();
|
||||
if (!in_array($key, $config, true)) {
|
||||
continue;
|
||||
}
|
||||
// make array if not array:
|
||||
$value = $filter->value();
|
||||
if (null === $value) {
|
||||
continue;
|
||||
}
|
||||
if (!is_array($value)) {
|
||||
$value = [$value];
|
||||
}
|
||||
|
||||
switch ($filter->key()) {
|
||||
case 'name':
|
||||
$parsed['name'] = $value;
|
||||
break;
|
||||
case 'type':
|
||||
$parsed['type'] = $this->parseAccountTypeFilter($value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
final protected function addFilterParams(string $class, Builder $query, ?FilterParameters $filters): Builder
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
if (null === $filters) {
|
||||
return $query;
|
||||
}
|
||||
$config = config(sprintf('firefly.valid_query_filters.%s', $class)) ?? [];
|
||||
if (0 === count($filters->all())) {
|
||||
return $query;
|
||||
}
|
||||
$query->where(function (Builder $q) use ($config, $filters): void {
|
||||
foreach ($filters->all() as $filter) {
|
||||
if (in_array($filter->key(), $config, true)) {
|
||||
foreach ($filter->value() as $value) {
|
||||
$q->where($filter->key(), 'LIKE', sprintf('%%%s%%', $value));
|
||||
// parse filters valid for this class.
|
||||
$parsed = $this->parseAllFilters($class, $filters);
|
||||
|
||||
// expand query for each query filter
|
||||
$config = config('api.valid_query_filters')[$class];
|
||||
$query->where(function (Builder $q) use ($config, $parsed): void {
|
||||
foreach ($parsed as $key => $filter) {
|
||||
if (in_array($key, $config, true)) {
|
||||
Log::debug(sprintf('Add query filter "%s"', $key));
|
||||
// add type to query:
|
||||
foreach ($filter as $value) {
|
||||
$q->where($key, 'LIKE', sprintf('%%%s%%', $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// some filters are special, i.e. the account type filter.
|
||||
$typeFilters = $filters->value('type', false);
|
||||
if (false !== $typeFilters && count($typeFilters) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
foreach ($typeFilters as $typeFilter) {
|
||||
$types = $this->mapAccountTypes($typeFilter);
|
||||
$query->whereIn('account_types.type', $types);
|
||||
// TODO this is special treatment, but alas, unavoidable right now.
|
||||
if ($class === Account::class && array_key_exists('type', $parsed)) {
|
||||
if (count($parsed['type']) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$query->whereIn('account_types.type', $parsed['type']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ trait ValidateSortParameters
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = config(sprintf('firefly.full_data_set.%s', $class)) ?? [];
|
||||
$config = config(sprintf('api.full_data_set.%s', $class)) ?? [];
|
||||
|
||||
foreach ($params->all() as $field) {
|
||||
if (in_array($field->name(), $config, true)) {
|
||||
|
Reference in New Issue
Block a user