diff --git a/app/JsonApi/V3/Accounts/AccountRepository.php b/app/JsonApi/V3/Accounts/AccountRepository.php index 02c7d4b1f8..248dd6fbff 100644 --- a/app/JsonApi/V3/Accounts/AccountRepository.php +++ b/app/JsonApi/V3/Accounts/AccountRepository.php @@ -27,6 +27,7 @@ use FireflyIII\Models\Account; use FireflyIII\Support\JsonApi\Concerns\UsergroupAware; use LaravelJsonApi\Contracts\Store\QueriesAll; use LaravelJsonApi\NonEloquent\AbstractRepository; +use LaravelJsonApi\NonEloquent\Concerns\HasCrudCapability; class AccountRepository extends AbstractRepository implements QueriesAll @@ -39,6 +40,17 @@ class AccountRepository extends AbstractRepository implements QueriesAll */ public function __construct() {} + /** + * Get the tags relationship + * + * @param Account $account + * @return iterable + */ + public function getBalances(Account $account): iterable + { + die('here we are'); + } + /** * @inheritDoc */ diff --git a/app/JsonApi/V3/Accounts/AccountResource.php b/app/JsonApi/V3/Accounts/AccountResource.php index fa824c7b93..36e97d061d 100644 --- a/app/JsonApi/V3/Accounts/AccountResource.php +++ b/app/JsonApi/V3/Accounts/AccountResource.php @@ -54,18 +54,24 @@ class AccountResource extends JsonApiResource 'name' => $this->resource->name, 'iban' => '' === $this->resource->iban ? null : $this->resource->iban, 'active' => $this->resource->active, - 'virtual_balance' => $this->resource->virtual_balance, +// 'virtual_balance' => $this->resource->virtual_balance, 'last_activity' => $this->resource->last_activity, - 'balance' => $this->resource->balance, - 'native_balance' => $this->resource->native_balance, - 'type' => $this->resource->name, +// 'native_balance' => $this->resource->native_balance, + 'type' => $this->resource->type, + 'account_role' => $this->resource->account_role, + //'user' => $this->resource->user_array, +// 'balances' => [] +// + // currency +// 'currency_id' => $this->resource->currency_id, +// 'currency_code' => $this->resource->currency_code, +// 'currency_symbol' => $this->resource->currency_symbol, +// 'currency_decimal_places' => $this->resource->currency_decimal_places, + + // balance (in currency, on date) +// 'current_balance' => $this->resource->current_balance, + - // 'type' => strtolower($accountType), - // 'account_role' => $accountRole, - // 'currency_id' => $currencyId, - // 'currency_code' => $currencyCode, - // 'currency_symbol' => $currencySymbol, - // 'currency_decimal_places' => $decimalPlaces, // 'current_balance' => app('steam')->bcround(app('steam')->balance($account, $date), $decimalPlaces), // 'current_balance_date' => $date->toAtomString(), // 'notes' => $this->repository->getNoteText($account), @@ -84,16 +90,9 @@ class AccountResource extends JsonApiResource // 'longitude' => $longitude, // 'latitude' => $latitude, // 'zoom_level' => $zoomLevel, - // 'id' => (string) $account->id, - // 'created_at' => $account->created_at->toAtomString(), - // 'updated_at' => $account->updated_at->toAtomString(), - // 'active' => $account->active, + // 'order' => $order, - // 'name' => $account->name, - // 'iban' => '' === (string) $account->iban ? null : $account->iban, - // 'account_number' => $this->accountMeta[$id]['account_number'] ?? null, - // 'type' => strtolower($accountType), - // 'account_role' => $accountRole, + // 'currency_id' => (string) $currency->id, // 'currency_code' => $currency->code, // 'currency_symbol' => $currency->symbol, @@ -153,7 +152,8 @@ class AccountResource extends JsonApiResource public function relationships($request): iterable { return [ - $this->relation('user')->withData($this->resource->user), + $this->relation('user')->withData($this->resource->user_array), + $this->relation('balances')->withData([]), //$this->relation('tags')->withData($this->resource->getTags()), ]; } diff --git a/app/JsonApi/V3/Accounts/AccountSchema.php b/app/JsonApi/V3/Accounts/AccountSchema.php index 61ac9c8e35..5710731f5c 100644 --- a/app/JsonApi/V3/Accounts/AccountSchema.php +++ b/app/JsonApi/V3/Accounts/AccountSchema.php @@ -59,14 +59,43 @@ class AccountSchema extends Schema Attribute::make('name')->sortable(), Attribute::make('iban'), Attribute::make('active'), - Attribute::make('virtual_balance'), Attribute::make('last_activity')->sortable(), - Attribute::make('balance')->sortable(), - Attribute::make('native_balance')->sortable(), Attribute::make('type'), + Attribute::make('account_role'), + + ToOne::make('user'), + ToMany::make('balances'), + + // currency +// Attribute::make('currency_id'), +// Attribute::make('currency_code'), +// Attribute::make('currency_symbol'), +// Attribute::make('currency_decimal_places'), +// +// // native currency +// Attribute::make('native_currency_id'), +// Attribute::make('native_currency_code'), +// Attribute::make('native_currency_symbol'), +// Attribute::make('native_currency_decimal_places'), +// +// // current balance (in currency, on date) +// Attribute::make('current_balance')->sortable(), +// Attribute::make('current_balance_date'), +// +// // native current balance (in native currency) +// Attribute::make('native_current_balance'), +// +// // virtual balance +// Attribute::make('virtual_balance'), +// +// // native virtual balance +// Attribute::make('native_virtual_balance'), + + // balance difference (if start + end filter present) + + // native balance difference (if start + end filter present) - // fancy fields: @@ -153,7 +182,7 @@ class AccountSchema extends Schema // 'latitude' => $latitude, // 'zoom_level' => $zoomLevel, - ToOne::make('user'), +// ToOne::make('user'), // ToMany::make('tags'), ]; } @@ -174,6 +203,7 @@ class AccountSchema extends Schema { return [ Filter::make('name'), + Filter::make('type'), ]; } public function repository(): AccountRepository diff --git a/app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php b/app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php index 7ef2de6b8a..4ebf4f247d 100644 --- a/app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php +++ b/app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php @@ -77,8 +77,5 @@ class AccountQuery extends QueryAll implements HasPagination // var_dump($filters->value('name')); // exit; - - - return Account::get(); } } diff --git a/app/JsonApi/V3/Users/UserSchema.php b/app/JsonApi/V3/Users/UserSchema.php index 81e18adc41..00dc8e0363 100644 --- a/app/JsonApi/V3/Users/UserSchema.php +++ b/app/JsonApi/V3/Users/UserSchema.php @@ -30,8 +30,8 @@ class UserSchema extends Schema { return [ ID::make(), - DateTime::make('createdAt')->sortable()->readOnly(), - DateTime::make('updatedAt')->sortable()->readOnly(), + DateTime::make('created_at')->sortable()->readOnly(), + DateTime::make('created_at')->sortable()->readOnly(), HasMany::make('accounts'), ]; } @@ -57,9 +57,4 @@ class UserSchema extends Schema { return PagePagination::make(); } - public function authorizable(): bool - { - return false; - } - } diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index 4f1343c6d9..f827d9f528 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -25,7 +25,10 @@ namespace FireflyIII\Support\JsonApi\Enrichments; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; @@ -33,20 +36,30 @@ class AccountEnrichment implements EnrichmentInterface { private Collection $collection; + private array $currencies; + #[\Override] public function enrich(Collection $collection): Collection { - $this->collection = $collection; - + $this->collection = $collection; + $this->currencies = []; // do everything here: $this->getLastActivity(); - $this->getMetaBalances(); + //$this->getMetaBalances(); + $this->collectAccountTypes(); + $this->collectMetaData(); + + $this->collection->transform(function (Account $account) { + $account->user_array = ['id' => 1,'bla bla' => 'bla']; + return $account; + }); return $this->collection; } /** * TODO this method refers to a single-use method inside Steam that could be moved here. + * * @return void */ private function getLastActivity(): void @@ -56,11 +69,13 @@ class AccountEnrichment implements EnrichmentInterface $lastActivity = $accountRepository->getLastActivity($this->collection); foreach ($lastActivity as $row) { $this->collection->where('id', $row['account_id'])->first()->last_activity = Carbon::parse($row['date_max'], config('app.timezone')); + } } /** * TODO this method refers to a single-use method inside Steam that could be moved here. + * * @return void */ private function getMetaBalances(): void @@ -72,8 +87,62 @@ class AccountEnrichment implements EnrichmentInterface return; } foreach ($array as $accountId => $row) { - $this->collection->where('id', $accountId)->first()->balance = $row['balance']; + $this->collection->where('id', $accountId)->first()->balance = $row['balance']; $this->collection->where('id', $accountId)->first()->native_balance = $row['native_balance']; } } + + /** + * TODO this method refers to a single-use method inside Steam that could be moved here. + * + * @return void + */ + private function collectAccountTypes(): void + { + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + $accountTypes = $accountRepository->getAccountTypes($this->collection); + $types = []; + + /** @var AccountType $row */ + foreach ($accountTypes as $row) { + $types[$row->id] = $row->type; + } + $this->collection->transform(function (Account $account) use ($types) { + $account->type = $types[$account->id]; + return $account; + }); + } + + private function collectMetaData(): void + { + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + + $metaFields = $accountRepository->getMetaValues($this->collection, ['currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']); + $currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray(); + + $currencies = []; + foreach ($repository->getByIds($currencyIds) as $currency) { + $id = $currency->id; + $currencies[$id] = $currency; + } + + + $this->collection->transform(function (Account $account) use ($metaFields, $currencies) { + $set = $metaFields->where('account_id', $account->id); + foreach ($set as $entry) { + $account->{$entry->name} = $entry->data; + if ('currency_id' === $entry->name) { + $id = (int) $entry->data; + $account->currency_code = $currencies[$id]?->code; + $account->currency_symbol = $currencies[$id]?->symbol; + $account->currency_decimal_places = $currencies[$id]?->decimal_places; + } + } + return $account; + }); + } } diff --git a/app/Support/JsonApi/ExpandsQuery.php b/app/Support/JsonApi/ExpandsQuery.php index 20902eb254..d364bb901b 100644 --- a/app/Support/JsonApi/ExpandsQuery.php +++ b/app/Support/JsonApi/ExpandsQuery.php @@ -23,20 +23,26 @@ declare(strict_types=1); namespace FireflyIII\Support\JsonApi; +use FireflyIII\Support\Http\Api\AccountFilter; use Illuminate\Contracts\Database\Eloquent\Builder; use LaravelJsonApi\Core\Query\FilterParameters; use LaravelJsonApi\Core\Query\SortFields; trait ExpandsQuery { + use AccountFilter; + final protected function addPagination(Builder $query, array $pagination): Builder { $skip = ($pagination['number'] - 1) * $pagination['size']; return $query->skip($skip)->take($pagination['size']); } - final protected function addSortParams(Builder $query, SortFields $sort): Builder + final protected function addSortParams(Builder $query, ?SortFields $sort): Builder { + if (null === $sort) { + return $query; + } foreach ($sort->all() as $sortField) { $query->orderBy($sortField->name(), $sortField->isAscending() ? 'ASC' : 'DESC'); } @@ -55,13 +61,23 @@ trait ExpandsQuery $query->where(function (Builder $q) use ($config, $filters) { foreach ($filters->all() as $filter) { if (in_array($filter->key(), $config, true)) { - foreach($filter->value() as $value) { + foreach ($filter->value() as $value) { $q->where($filter->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); + } + } + return $query; } diff --git a/app/Support/JsonApi/SortsCollection.php b/app/Support/JsonApi/SortsCollection.php index 30953e32a9..28ec985448 100644 --- a/app/Support/JsonApi/SortsCollection.php +++ b/app/Support/JsonApi/SortsCollection.php @@ -28,8 +28,11 @@ use LaravelJsonApi\Core\Query\SortFields; trait SortsCollection { - protected function sortCollection(Collection $collection, SortFields $sortFields): Collection { + protected function sortCollection(Collection $collection, ?SortFields $sortFields): Collection { + if(null === $sortFields) { + return $collection; + } foreach($sortFields->all() as $sortField) { $collection = $sortField->isAscending() ? $collection->sortBy($sortField->name()) : $collection->sortByDesc($sortField->name()); } diff --git a/app/Support/JsonApi/ValidateSortParameters.php b/app/Support/JsonApi/ValidateSortParameters.php index 73d144d05f..0fd2b55e1e 100644 --- a/app/Support/JsonApi/ValidateSortParameters.php +++ b/app/Support/JsonApi/ValidateSortParameters.php @@ -27,11 +27,15 @@ use LaravelJsonApi\Core\Query\SortFields; trait ValidateSortParameters { - function validateParams(string $class, SortFields $params): bool + function validateParams(string $class, ?SortFields $params): bool { + if(null === $params) { + return false; + } $config = config(sprintf('firefly.full_data_set.%s', $class)) ?? []; + foreach ($params->all() as $field) { if (in_array($field->name(), $config, true)) { return true; diff --git a/config/jsonapi.php b/config/jsonapi.php index eb990cac14..e06569dc2e 100644 --- a/config/jsonapi.php +++ b/config/jsonapi.php @@ -29,7 +29,6 @@ return [ | class name of the server class. */ 'servers' => [ -// 'v1' => \App\JsonApi\V1\Server::class, -'v3' => Server::class, + 'v3' => Server::class, ], ];