From 05b0425929a4b85e3e8fc05628faf4b80d8effa1 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 8 Dec 2018 21:26:20 +0100 Subject: [PATCH] Expand API and routes. --- app/Api/V1/Controllers/AccountController.php | 51 +- app/Api/V1/Controllers/CurrencyController.php | 474 +++++++++++++++++- app/Api/V1/Controllers/ImportController.php | 10 +- app/Api/V1/Controllers/LinkTypeController.php | 6 +- .../V1/Controllers/RecurrenceController.php | 6 +- app/Api/V1/Controllers/TagController.php | 6 +- .../V1/Controllers/TransactionController.php | 6 +- .../Controllers/TransactionLinkController.php | 4 +- app/Api/V1/Requests/CurrencyRequest.php | 19 +- .../Collector/TransactionCollector.php | 20 + .../TransactionCollectorInterface.php | 10 + app/Models/TransactionCurrency.php | 21 +- .../Currency/CurrencyRepository.php | 20 + .../Currency/CurrencyRepositoryInterface.php | 17 +- app/Support/Http/Api/AccountFilter.php | 79 +++ ...Transactions.php => TransactionFilter.php} | 8 +- app/Transformers/AccountTransformer.php | 76 --- .../AvailableBudgetTransformer.php | 41 -- app/Transformers/BillTransformer.php | 86 ---- app/Transformers/BudgetLimitTransformer.php | 27 - app/Transformers/BudgetTransformer.php | 53 -- app/Transformers/CategoryTransformer.php | 53 -- .../CurrencyExchangeRateTransformer.php | 35 +- app/Transformers/CurrencyTransformer.php | 13 - app/Transformers/JournalMetaTransformer.php | 41 -- config/firefly.php | 1 + routes/api.php | 19 +- 27 files changed, 686 insertions(+), 516 deletions(-) create mode 100644 app/Support/Http/Api/AccountFilter.php rename app/Support/Http/Api/{Transactions.php => TransactionFilter.php} (94%) diff --git a/app/Api/V1/Controllers/AccountController.php b/app/Api/V1/Controllers/AccountController.php index 937858d797..2dd530ed8c 100644 --- a/app/Api/V1/Controllers/AccountController.php +++ b/app/Api/V1/Controllers/AccountController.php @@ -28,6 +28,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Transformers\AccountTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; @@ -46,6 +47,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class AccountController extends Controller { + use AccountFilter; /** @var CurrencyRepositoryInterface The currency repository */ private $currencyRepository; /** @var AccountRepositoryInterface The account repository */ @@ -105,7 +107,7 @@ class AccountController extends Controller $this->parameters->set('type', $type); // types to get, page size: - $types = $this->mapTypes($this->parameters->get('type')); + $types = $this->mapAccountTypes($this->parameters->get('type')); $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of accounts. Count it and split it. @@ -195,51 +197,4 @@ class AccountController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } - - /** - * All the available types. - * - * @param string $type - * - * @return array - */ - private function mapTypes(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], - 'cc' => [AccountType::CREDITCARD], - 'creditcard' => [AccountType::CREDITCARD], - 'credit_card' => [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], - - ]; - $return = $types['all']; - if (isset($types[$type])) { - $return = $types[$type]; - } - - return $return; // @codeCoverageIgnore - } } diff --git a/app/Api/V1/Controllers/CurrencyController.php b/app/Api/V1/Controllers/CurrencyController.php index 803ed146dd..e721820a2c 100644 --- a/app/Api/V1/Controllers/CurrencyController.php +++ b/app/Api/V1/Controllers/CurrencyController.php @@ -26,14 +26,42 @@ namespace FireflyIII\Api\V1\Controllers; use FireflyIII\Api\V1\Requests\CurrencyRequest; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Collector\TransactionCollectorInterface; +use FireflyIII\Helpers\Filter\InternalTransferFilter; +use FireflyIII\Models\Account; +use FireflyIII\Models\AvailableBudget; +use FireflyIII\Models\Bill; +use FireflyIII\Models\BudgetLimit; +use FireflyIII\Models\Recurrence; +use FireflyIII\Models\RecurrenceTransaction; +use FireflyIII\Models\Rule; +use FireflyIII\Models\RuleTrigger; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Support\Http\Api\AccountFilter; +use FireflyIII\Support\Http\Api\TransactionFilter; +use FireflyIII\Transformers\AccountTransformer; +use FireflyIII\Transformers\AvailableBudgetTransformer; +use FireflyIII\Transformers\BillTransformer; +use FireflyIII\Transformers\BudgetLimitTransformer; +use FireflyIII\Transformers\CurrencyExchangeRateTransformer; use FireflyIII\Transformers\CurrencyTransformer; +use FireflyIII\Transformers\RecurrenceTransformer; +use FireflyIII\Transformers\RuleTransformer; +use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Collection; use League\Fractal\Manager; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; @@ -47,6 +75,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class CurrencyController extends Controller { + use AccountFilter, TransactionFilter; /** @var CurrencyRepositoryInterface The currency repository */ private $repository; /** @var UserRepositoryInterface The user repository */ @@ -73,6 +102,269 @@ class CurrencyController extends Controller ); } + /** + * Display a list of accounts. + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function accounts(Request $request, TransactionCurrency $currency): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + + // read type from URI + $type = $request->get('type') ?? 'all'; + $this->parameters->set('type', $type); + + // types to get, page size: + $types = $this->mapAccountTypes($this->parameters->get('type')); + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of accounts. Count it and split it. + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + $unfiltered = $accountRepository->getAccountsByType($types); + + // filter list on currency preference: + $collection = $unfiltered->filter( + function (Account $account) use ($currency, $accountRepository) { + $currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id'); + + return $currencyId === $currency->id; + } + ); + + $count = $collection->count(); + $accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]) . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($accounts, new AccountTransformer($this->parameters), 'accounts'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * Show all transactions. + * + * @param Request $request + * + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function transactions(Request $request, TransactionCurrency $currency): JsonResponse + { + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $type = $request->get('type') ?? 'default'; + $this->parameters->set('type', $type); + + $types = $this->mapTransactionTypes($this->parameters->get('type')); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + /** @var User $admin */ + $admin = auth()->user(); + /** @var TransactionCollectorInterface $collector */ + $collector = app(TransactionCollectorInterface::class); + $collector->setUser($admin); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + $collector->setAllAssetAccounts(); + $collector->setCurrency($currency); + + if (\in_array(TransactionType::TRANSFER, $types, true)) { + $collector->removeFilter(InternalTransferFilter::class); + } + + if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $collector->setTypes($types); + $paginator = $collector->getPaginatedTransactions(); + $paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]) . $this->buildParams()); + $transactions = $paginator->getCollection(); + + $journalRepository = app(JournalRepositoryInterface::class); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $journalRepository), 'transactions'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * Display a listing of the resource. + * + * @param Request $request + * + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function availableBudgets(Request $request, TransactionCurrency $currency): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + + // types to get, page size: + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of available budgets. Count it and split it. + /** @var BudgetRepositoryInterface $repository */ + $repository = app(BudgetRepositoryInterface::class); + $unfiltered = $repository->getAvailableBudgets(); + + // filter list. + $collection = $unfiltered->filter( + function (AvailableBudget $availableBudget) use ($currency) { + return $availableBudget->transaction_currency_id === $currency->id; + } + ); + + $count = $collection->count(); + $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + + // make paginator: + $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.currencies.available_budgets', [$currency->code]) . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($availableBudgets, new AvailableBudgetTransformer($this->parameters), 'available_budgets'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * List all bills + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function bills(Request $request, TransactionCurrency $currency): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + + /** @var BillRepositoryInterface $repository */ + $repository = app(BillRepositoryInterface::class); + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $paginator = $repository->getPaginator($pageSize); + /** @var Collection $bills */ + $unfiltered = $paginator->getCollection(); + + // filter and paginate list: + $collection = $unfiltered->filter( + function (Bill $bill) use ($currency) { + return $bill->transaction_currency_id === $currency->id; + } + ); + $count = $collection->count(); + $bills = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.currencies.bills', [$currency->code]) . $this->buildParams()); + + + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * List all budget limits + * + * @param Request $request + * + * @return JsonResponse + */ + public function budgetLimits(Request $request, TransactionCurrency $currency): JsonResponse + { + /** @var BudgetRepositoryInterface $repository */ + $repository = app(BudgetRepositoryInterface::class); + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $budgetId = (int)($request->get('budget_id') ?? 0); + $budget = $repository->findNull($budgetId); + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $this->parameters->set('budget_id', $budgetId); + + $unfiltered = new Collection; + if (null === $budget) { + $unfiltered = $repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end')); + } + if (null !== $budget) { + $unfiltered = $repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); + } + + // filter budget limits on currency ID + $collection = $unfiltered->filter( + function (BudgetLimit $budgetLimit) use ($currency) { + return $budgetLimit->transaction_currency_id === $currency->id; + } + ); + + $count = $collection->count(); + $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]) . $this->buildParams()); + + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($budgetLimits, new BudgetLimitTransformer($this->parameters), 'budget_limits'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * Show a list of known exchange rates + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function cer(Request $request, TransactionCurrency $currency): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $collection = $this->repository->getExchangeRates($currency); + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + + $count = $collection->count(); + $exchangeRates = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + $paginator = new LengthAwarePaginator($exchangeRates, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.currencies.cer', [$currency->code]) . $this->buildParams()); + + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($exchangeRates, new CurrencyExchangeRateTransformer($this->parameters), 'currency_exchange_rates'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + /** * Remove the specified resource from storage. * @@ -98,6 +390,60 @@ class CurrencyController extends Controller return response()->json([], 204); } + /** + * Disable a currency. + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function disable(Request $request, TransactionCurrency $currency): JsonResponse + { + // must be unused. + if ($this->repository->currencyInUse($currency)) { + return response()->json([], 409); + } + $this->repository->disable($currency); + $currency = $this->repository->find($currency->id); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); + $this->parameters->set('defaultCurrency', $defaultCurrency); + + $resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * Enable a currency. + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function enable(Request $request, TransactionCurrency $currency): JsonResponse + { + $this->repository->enable($currency); + $currency = $this->repository->find($currency->id); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); + $this->parameters->set('defaultCurrency', $defaultCurrency); + + $resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + /** * Display a listing of the resource. * @@ -128,6 +474,133 @@ class CurrencyController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } + /** + * Make the currency a default currency. + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse + */ + public function makeDefault(Request $request, TransactionCurrency $currency): JsonResponse + { + $this->repository->enable($currency); + + app('preferences')->set('currencyPreference', $currency->code); + app('preferences')->mark(); + + $currency = $this->repository->find($currency->id); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $this->parameters->set('defaultCurrency', $currency); + + $resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * List all recurring transactions. + * + * @param Request $request + * + * @return JsonResponse] + */ + public function recurrences(Request $request, TransactionCurrency $currency): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + + // types to get, page size: + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of budgets. Count it and split it. + /** @var RecurringRepositoryInterface $repository */ + $repository = app(RecurringRepositoryInterface::class); + $unfiltered = $repository->getAll(); + + // filter selection + $collection = $unfiltered->filter( + function (Recurrence $recurrence) use ($currency) { + /** @var RecurrenceTransaction $transaction */ + foreach ($recurrence->recurrenceTransactions as $transaction) { + if ($transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id) { + return $recurrence; + } + } + + return null; + } + ); + + + $count = $collection->count(); + $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]) . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($piggyBanks, new RecurrenceTransformer($this->parameters), 'recurrences'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * List all of them. + * + * @param Request $request + * @param TransactionCurrency $currency + * + * @return JsonResponse] + */ + public function rules(Request $request, TransactionCurrency $currency): JsonResponse + { + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of budgets. Count it and split it. + /** @var RuleRepositoryInterface $repository */ + $repository = app(RuleRepositoryInterface::class); + $unfiltered = $repository->getAll(); + + $collection = $unfiltered->filter( + function (Rule $rule) use ($currency) { + /** @var RuleTrigger $trigger */ + foreach ($rule->ruleTriggers as $trigger) { + if ('currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value) { + return $rule; + } + } + + return null; + } + ); + + $count = $collection->count(); + $rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($rules, new RuleTransformer($this->parameters), 'rules'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } /** * Show a currency. @@ -181,7 +654,6 @@ class CurrencyController extends Controller } - /** * Update a currency. * diff --git a/app/Api/V1/Controllers/ImportController.php b/app/Api/V1/Controllers/ImportController.php index fa82b6c41e..4f48bdcc59 100644 --- a/app/Api/V1/Controllers/ImportController.php +++ b/app/Api/V1/Controllers/ImportController.php @@ -29,7 +29,7 @@ use FireflyIII\Models\ImportJob; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use FireflyIII\Support\Http\Api\Transactions; +use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\ImportJobTransformer; use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; @@ -48,7 +48,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class ImportController extends Controller { - use Transactions; + use TransactionFilter; /** @var ImportJobRepositoryInterface Import job repository. */ private $repository; @@ -128,7 +128,7 @@ class ImportController extends Controller $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); - $types = $this->mapTypes($this->parameters->get('type')); + $types = $this->mapTransactionTypes($this->parameters->get('type')); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); @@ -163,8 +163,8 @@ class ImportController extends Controller } - $repository = app(JournalRepositoryInterface::class); - $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $repository), 'transactions'); + $repository = app(JournalRepositoryInterface::class); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $repository), 'transactions'); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); diff --git a/app/Api/V1/Controllers/LinkTypeController.php b/app/Api/V1/Controllers/LinkTypeController.php index 6ad7a937df..0255221416 100644 --- a/app/Api/V1/Controllers/LinkTypeController.php +++ b/app/Api/V1/Controllers/LinkTypeController.php @@ -32,7 +32,7 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; -use FireflyIII\Support\Http\Api\Transactions; +use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\LinkTypeTransformer; use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; @@ -52,7 +52,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class LinkTypeController extends Controller { - use Transactions; + use TransactionFilter; /** @var LinkTypeRepositoryInterface The link type repository */ private $repository; @@ -189,7 +189,7 @@ class LinkTypeController extends Controller $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); - $types = $this->mapTypes($this->parameters->get('type')); + $types = $this->mapTransactionTypes($this->parameters->get('type')); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); diff --git a/app/Api/V1/Controllers/RecurrenceController.php b/app/Api/V1/Controllers/RecurrenceController.php index 31a267e79c..b4e4b15dbf 100644 --- a/app/Api/V1/Controllers/RecurrenceController.php +++ b/app/Api/V1/Controllers/RecurrenceController.php @@ -32,7 +32,7 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Support\Cronjobs\RecurringCronjob; -use FireflyIII\Support\Http\Api\Transactions; +use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; @@ -51,7 +51,7 @@ use Log; */ class RecurrenceController extends Controller { - use Transactions; + use TransactionFilter; /** @var RecurringRepositoryInterface The recurring transaction repository */ private $repository; @@ -176,7 +176,7 @@ class RecurrenceController extends Controller $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); - $types = $this->mapTypes($this->parameters->get('type')); + $types = $this->mapTransactionTypes($this->parameters->get('type')); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); diff --git a/app/Api/V1/Controllers/TagController.php b/app/Api/V1/Controllers/TagController.php index 2b5fd7d3e6..9d7f7828f2 100644 --- a/app/Api/V1/Controllers/TagController.php +++ b/app/Api/V1/Controllers/TagController.php @@ -30,7 +30,7 @@ use FireflyIII\Models\Tag; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; -use FireflyIII\Support\Http\Api\Transactions; +use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\TagTransformer; use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; @@ -48,7 +48,7 @@ use League\Fractal\Resource\Collection as FractalCollection; */ class TagController extends Controller { - use Transactions; + use TransactionFilter; /** @var TagRepositoryInterface The tag repository */ private $repository; @@ -155,7 +155,7 @@ class TagController extends Controller $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); - $types = $this->mapTypes($this->parameters->get('type')); + $types = $this->mapTransactionTypes($this->parameters->get('type')); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); diff --git a/app/Api/V1/Controllers/TransactionController.php b/app/Api/V1/Controllers/TransactionController.php index 308d945e9c..0fdd10a8e9 100644 --- a/app/Api/V1/Controllers/TransactionController.php +++ b/app/Api/V1/Controllers/TransactionController.php @@ -35,7 +35,7 @@ use FireflyIII\Helpers\Filter\PositiveAmountFilter; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use FireflyIII\Support\Http\Api\Transactions; +use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\PiggyBankEventTransformer; use FireflyIII\Transformers\TransactionTransformer; @@ -54,7 +54,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class TransactionController extends Controller { - use Transactions; + use TransactionFilter; /** @var JournalRepositoryInterface The journal repository */ private $repository; @@ -145,7 +145,7 @@ class TransactionController extends Controller $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); - $types = $this->mapTypes($this->parameters->get('type')); + $types = $this->mapTransactionTypes($this->parameters->get('type')); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); diff --git a/app/Api/V1/Controllers/TransactionLinkController.php b/app/Api/V1/Controllers/TransactionLinkController.php index 2352414f53..c504b2d396 100644 --- a/app/Api/V1/Controllers/TransactionLinkController.php +++ b/app/Api/V1/Controllers/TransactionLinkController.php @@ -28,7 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; -use FireflyIII\Support\Http\Api\Transactions; +use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\JournalLinkTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; @@ -45,7 +45,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class TransactionLinkController extends Controller { - use Transactions; + use TransactionFilter; /** @var JournalRepositoryInterface The journal repository */ private $journalRepository; diff --git a/app/Api/V1/Requests/CurrencyRequest.php b/app/Api/V1/Requests/CurrencyRequest.php index 95f48d949e..09e51f8935 100644 --- a/app/Api/V1/Requests/CurrencyRequest.php +++ b/app/Api/V1/Requests/CurrencyRequest.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; +use FireflyIII\Rules\IsBoolean; + /** * Class CurrencyRequest @@ -47,13 +49,22 @@ class CurrencyRequest extends Request */ public function getAll(): array { + $enabled = true; + $default = false; + if (null !== $this->get('enabled')) { + $enabled = $this->boolean('enabled'); + } + if (null !== $this->get('default')) { + $default = $this->boolean('default'); + } + return [ 'name' => $this->string('name'), 'code' => $this->string('code'), 'symbol' => $this->string('symbol'), 'decimal_places' => $this->integer('decimal_places'), - 'default' => $this->boolean('default'), - 'enabled' => $this->boolean('enabled'), + 'default' => $default, + 'enabled' => $enabled, ]; } @@ -69,8 +80,8 @@ class CurrencyRequest extends Request 'code' => 'required|between:3,3|unique:transaction_currencies,code', 'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol', 'decimal_places' => 'required|between:0,20|numeric|min:0|max:20', - 'enabled' => 'required|boolean', - 'default' => 'boolean', + 'enabled' => [new IsBoolean()], + 'default' => [new IsBoolean()], ]; diff --git a/app/Helpers/Collector/TransactionCollector.php b/app/Helpers/Collector/TransactionCollector.php index 3862fd2d56..1476ee8365 100644 --- a/app/Helpers/Collector/TransactionCollector.php +++ b/app/Helpers/Collector/TransactionCollector.php @@ -42,6 +42,7 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Support\CacheProperties; use FireflyIII\User; @@ -527,6 +528,25 @@ class TransactionCollector implements TransactionCollectorInterface return $this; } + /** + * Set the required currency (local or foreign) + * + * @param TransactionCurrency $currency + * + * @return TransactionCollectorInterface + */ + public function setCurrency(TransactionCurrency $currency): TransactionCollectorInterface + { + $this->query->where( + function (EloquentBuilder $builder) use ($currency) { + $builder->where('transactions.transaction_currency_id', $currency->id); + $builder->orWhere('transactions.foreign_currency_id', $currency->id); + } + ); + + return $this; + } + /** * @param array $journalIds * diff --git a/app/Helpers/Collector/TransactionCollectorInterface.php b/app/Helpers/Collector/TransactionCollectorInterface.php index 47e37a7a48..1691b63021 100644 --- a/app/Helpers/Collector/TransactionCollectorInterface.php +++ b/app/Helpers/Collector/TransactionCollectorInterface.php @@ -27,6 +27,7 @@ use Carbon\Carbon; use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Tag; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\User; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Pagination\LengthAwarePaginator; @@ -144,6 +145,15 @@ interface TransactionCollectorInterface */ public function setAllAssetAccounts(): TransactionCollectorInterface; + /** + * Set the required currency (local or foreign) + * + * @param TransactionCurrency $currency + * + * @return TransactionCollectorInterface + */ + public function setCurrency(TransactionCurrency $currency): TransactionCollectorInterface; + /** * Collect transactions before a specific date. * diff --git a/app/Models/TransactionCurrency.php b/app/Models/TransactionCurrency.php index 9309e4c8f7..e8360fa28d 100644 --- a/app/Models/TransactionCurrency.php +++ b/app/Models/TransactionCurrency.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; @@ -36,6 +37,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property int $id * @property string name * @property bool $enabled + * @property Carbon $created_at + * @property Carbon $updated_at * */ class TransactionCurrency extends Model @@ -78,6 +81,15 @@ class TransactionCurrency extends Model throw new NotFoundHttpException; } + /** + * @codeCoverageIgnore + * @return HasMany + */ + public function budgetLimits(): HasMany + { + return $this->hasMany(BudgetLimit::class); + } + /** * @codeCoverageIgnore * @return HasMany @@ -95,13 +107,4 @@ class TransactionCurrency extends Model { return $this->hasMany(Transaction::class); } - - /** - * @codeCoverageIgnore - * @return HasMany - */ - public function budgetLimits(): HasMany - { - return $this->hasMany(BudgetLimit::class); - } } diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index fc8f3a2611..b921f7ba18 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -33,6 +33,7 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Services\Internal\Destroy\CurrencyDestroyService; use FireflyIII\Services\Internal\Update\CurrencyUpdateService; use FireflyIII\User; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; use Log; @@ -341,6 +342,25 @@ class CurrencyRepository implements CurrencyRepositoryInterface return null; } + /** + * Return a list of exchange rates with this currency. + * + * @param TransactionCurrency $currency + * + * @return Collection + */ + public function getExchangeRates(TransactionCurrency $currency): Collection + { + /** @var CurrencyExchangeRate $rate */ + return $this->user->currencyExchangeRates() + ->where( + function (Builder $query) use ($currency) { + $query->where('from_currency_id', $currency->id); + $query->orWhere('to_currency_id', $currency->id); + } + )->get(); + } + /** * @param User $user */ diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index 76d3aaacaa..0adb767196 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -37,16 +37,16 @@ interface CurrencyRepositoryInterface /** * @param TransactionCurrency $currency * - * @return bool + * @return int */ - public function currencyInUse(TransactionCurrency $currency): bool; + public function countJournals(TransactionCurrency $currency): int; /** * @param TransactionCurrency $currency * - * @return int + * @return bool */ - public function countJournals(TransactionCurrency $currency): int; + public function currencyInUse(TransactionCurrency $currency): bool; /** * @param TransactionCurrency $currency @@ -176,6 +176,15 @@ interface CurrencyRepositoryInterface */ public function getExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): ?CurrencyExchangeRate; + /** + * Return a list of exchange rates with this currency. + * + * @param TransactionCurrency $currency + * + * @return Collection + */ + public function getExchangeRates(TransactionCurrency $currency): Collection; + /** * @param User $user */ diff --git a/app/Support/Http/Api/AccountFilter.php b/app/Support/Http/Api/AccountFilter.php new file mode 100644 index 0000000000..831c28f946 --- /dev/null +++ b/app/Support/Http/Api/AccountFilter.php @@ -0,0 +1,79 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Http\Api; + +use FireflyIII\Models\AccountType; + +/** + * Trait AccountFilter + */ +trait AccountFilter +{ + /** + * All the available types. + * + * @param string $type + * + * @return array + */ + 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], +// 'cc' => [AccountType::CREDITCARD], +// 'creditcard' => [AccountType::CREDITCARD], +// 'credit_card' => [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], + + ]; + $return = $types['all']; + if (isset($types[$type])) { + $return = $types[$type]; + } + + return $return; // @codeCoverageIgnore + } +} \ No newline at end of file diff --git a/app/Support/Http/Api/Transactions.php b/app/Support/Http/Api/TransactionFilter.php similarity index 94% rename from app/Support/Http/Api/Transactions.php rename to app/Support/Http/Api/TransactionFilter.php index 30ad3da8fe..e2f0f82ea5 100644 --- a/app/Support/Http/Api/Transactions.php +++ b/app/Support/Http/Api/TransactionFilter.php @@ -1,6 +1,6 @@ [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE, diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index 951e9454b5..48fc2eccd1 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -42,19 +42,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class AccountTransformer extends TransformerAbstract { - /** @noinspection ClassOverridesFieldOfSuperClassInspection */ - /** - * List of resources possible to include. - * - * @var array - */ - protected $availableIncludes = ['transactions', 'piggy_banks', 'user']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = []; /** @var ParameterBag */ protected $parameters; @@ -75,69 +62,6 @@ class AccountTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * Include piggy banks into end result. - * - * @codeCoverageIgnore - * - * @param Account $account - * - * @return FractalCollection - */ - public function includePiggyBanks(Account $account): FractalCollection - { - $piggies = $account->piggyBanks()->get(); - - return $this->collection($piggies, new PiggyBankTransformer($this->parameters), 'piggy_banks'); - } - - /** - * Include transactions into end result. - * - * @codeCoverageIgnore - * - * @param Account $account - * - * @return FractalCollection - */ - public function includeTransactions(Account $account): FractalCollection - { - $pageSize = (int)app('preferences')->getForUser($account->user, 'listPageSize', 50)->data; - - // journals always use collector and limited using URL parameters. - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($account->user); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - if ($account->accountType->type === AccountType::ASSET) { - $collector->setAccounts(new Collection([$account])); - } else { - $collector->setOpposingAccounts(new Collection([$account])); - } - if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { - $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); - } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $transactions = $collector->getTransactions(); - - $journalRepos = app(JournalRepositoryInterface::class); - - return $this->collection($transactions, new TransactionTransformer($this->parameters, $journalRepos), 'transactions'); - } - - /** - * Include user data in end result. - * - * @codeCoverageIgnore - * - * @param Account $account - * - * @return Item - */ - public function includeUser(Account $account): Item - { - return $this->item($account->user, new UserTransformer($this->parameters), 'users'); - } - /** * Transform the account. * diff --git a/app/Transformers/AvailableBudgetTransformer.php b/app/Transformers/AvailableBudgetTransformer.php index 2dc8e65acb..a3d225c7d6 100644 --- a/app/Transformers/AvailableBudgetTransformer.php +++ b/app/Transformers/AvailableBudgetTransformer.php @@ -34,19 +34,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class AvailableBudgetTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['transaction_currency', 'user']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = ['transaction_currency']; - /** @var ParameterBag */ protected $parameters; @@ -62,34 +49,6 @@ class AvailableBudgetTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * Attach the currency. - * - * @codeCoverageIgnore - * - * @param AvailableBudget $availableBudget - * - * @return Item - */ - public function includeTransactionCurrency(AvailableBudget $availableBudget): Item - { - return $this->item($availableBudget->transactionCurrency, new CurrencyTransformer($this->parameters), 'transaction_currencies'); - } - - /** - * Attach the user. - * - * @codeCoverageIgnore - * - * @param AvailableBudget $availableBudget - * - * @return Item - */ - public function includeUser(AvailableBudget $availableBudget): Item - { - return $this->item($availableBudget->user, new UserTransformer($this->parameters), 'users'); - } - /** * Transform the note. * diff --git a/app/Transformers/BillTransformer.php b/app/Transformers/BillTransformer.php index 449781ca35..2c3fa8786c 100644 --- a/app/Transformers/BillTransformer.php +++ b/app/Transformers/BillTransformer.php @@ -39,19 +39,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class BillTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['attachments', 'transactions', 'user', 'rules']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = ['rules']; - /** @var ParameterBag */ protected $parameters; @@ -71,79 +58,6 @@ class BillTransformer extends TransformerAbstract $this->repository = app(BillRepositoryInterface::class); } - /** - * Include any attachments. - * - * @param Bill $bill - * - * @codeCoverageIgnore - * @return FractalCollection - */ - public function includeAttachments(Bill $bill): FractalCollection - { - $attachments = $bill->attachments()->get(); - - return $this->collection($attachments, new AttachmentTransformer($this->parameters), 'attachments'); - } - - /** - * Attach the rules. - * - * @codeCoverageIgnore - * - * @param Bill $bill - * - * @return FractalCollection - */ - public function includeRules(Bill $bill): FractalCollection - { - $this->repository->setUser($bill->user); - // add info about rules: - $rules = $this->repository->getRulesForBill($bill); - - return $this->collection($rules, new RuleTransformer($this->parameters), 'rules'); - } - - /** - * Include any transactions. - * - * @param Bill $bill - * - * @codeCoverageIgnore - * @return FractalCollection - */ - public function includeTransactions(Bill $bill): FractalCollection - { - $pageSize = (int)app('preferences')->getForUser($bill->user, 'listPageSize', 50)->data; - - // journals always use collector and limited using URL parameters. - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($bill->user); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - $collector->setAllAssetAccounts(); - $collector->setBills(new Collection([$bill])); - if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { - $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); - } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $transactions = $collector->getTransactions(); - - return $this->collection($transactions, new TransactionTransformer($this->parameters), 'transactions'); - } - - /** - * Include the user. - * - * @param Bill $bill - * - * @codeCoverageIgnore - * @return \League\Fractal\Resource\Item - */ - public function includeUser(Bill $bill): Item - { - return $this->item($bill->user, new UserTransformer($this->parameters), 'users'); - } - /** * Transform the bill. * diff --git a/app/Transformers/BudgetLimitTransformer.php b/app/Transformers/BudgetLimitTransformer.php index 7fe980b5c8..89be58ac35 100644 --- a/app/Transformers/BudgetLimitTransformer.php +++ b/app/Transformers/BudgetLimitTransformer.php @@ -33,19 +33,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class BudgetLimitTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['budget']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = ['budget']; - /** @var ParameterBag */ protected $parameters; @@ -61,20 +48,6 @@ class BudgetLimitTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * Attach the budget. - * - * @codeCoverageIgnore - * - * @param BudgetLimit $budgetLimit - * - * @return Item - */ - public function includeBudget(BudgetLimit $budgetLimit): Item - { - return $this->item($budgetLimit->budget, new BudgetTransformer($this->parameters), 'budgets'); - } - /** * Transform the note. * diff --git a/app/Transformers/BudgetTransformer.php b/app/Transformers/BudgetTransformer.php index 09fe78c2d7..5c5205444f 100644 --- a/app/Transformers/BudgetTransformer.php +++ b/app/Transformers/BudgetTransformer.php @@ -37,19 +37,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class BudgetTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['user', 'transactions']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = ['user']; - /** @var ParameterBag */ protected $parameters; @@ -65,46 +52,6 @@ class BudgetTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * Include any transactions. - * - * @param Budget $budget - * - * @codeCoverageIgnore - * @return FractalCollection - */ - public function includeTransactions(Budget $budget): FractalCollection - { - $pageSize = (int)app('preferences')->getForUser($budget->user, 'listPageSize', 50)->data; - - // journals always use collector and limited using URL parameters. - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($budget->user); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - $collector->setAllAssetAccounts(); - $collector->setBudgets(new Collection([$budget])); - if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { - $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); - } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $transactions = $collector->getTransactions(); - - return $this->collection($transactions, new TransactionTransformer($this->parameters), 'transactions'); - } - - /** - * Include the user. - * - * @param Budget $budget - * - * @codeCoverageIgnore - * @return Item - */ - public function includeUser(Budget $budget): Item - { - return $this->item($budget->user, new UserTransformer($this->parameters), 'users'); - } - /** * Transform a budget. * diff --git a/app/Transformers/CategoryTransformer.php b/app/Transformers/CategoryTransformer.php index 6282a1b48b..a7d64400d1 100644 --- a/app/Transformers/CategoryTransformer.php +++ b/app/Transformers/CategoryTransformer.php @@ -37,19 +37,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class CategoryTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['user', 'transactions']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = ['user']; - /** @var ParameterBag */ protected $parameters; @@ -65,46 +52,6 @@ class CategoryTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * Include any transactions. - * - * @param Category $category - * - * @codeCoverageIgnore - * @return FractalCollection - */ - public function includeTransactions(Category $category): FractalCollection - { - $pageSize = (int)app('preferences')->getForUser($category->user, 'listPageSize', 50)->data; - - // journals always use collector and limited using URL parameters. - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($category->user); - $collector->withOpposingAccount()->withCategoryInformation()->withCategoryInformation(); - $collector->setAllAssetAccounts(); - $collector->setCategories(new Collection([$category])); - if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { - $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); - } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $transactions = $collector->getTransactions(); - - return $this->collection($transactions, new TransactionTransformer($this->parameters), 'transactions'); - } - - /** - * Include the user. - * - * @param Category $category - * - * @codeCoverageIgnore - * @return Item - */ - public function includeUser(Category $category): Item - { - return $this->item($category->user, new UserTransformer($this->parameters), 'users'); - } - /** * Convert category. * diff --git a/app/Transformers/CurrencyExchangeRateTransformer.php b/app/Transformers/CurrencyExchangeRateTransformer.php index e9dbd007dc..66c1eb49d3 100644 --- a/app/Transformers/CurrencyExchangeRateTransformer.php +++ b/app/Transformers/CurrencyExchangeRateTransformer.php @@ -25,7 +25,6 @@ namespace FireflyIII\Transformers; use FireflyIII\Models\CurrencyExchangeRate; -use League\Fractal\Resource\Item; use League\Fractal\TransformerAbstract; use Symfony\Component\HttpFoundation\ParameterBag; @@ -34,19 +33,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class CurrencyExchangeRateTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['from_currency', 'to_currency']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = ['from_currency', 'to_currency']; - /** @var ParameterBag */ protected $parameters; @@ -62,26 +48,6 @@ class CurrencyExchangeRateTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * @param CurrencyExchangeRate $rate - * - * @return Item - */ - public function includeFromCurrency(CurrencyExchangeRate $rate): Item - { - return $this->item($rate->fromCurrency, new CurrencyTransformer($this->parameters), 'transaction_currencies'); - } - - /** - * @param CurrencyExchangeRate $rate - * - * @return \League\Fractal\Resource\Item - */ - public function includeToCurrency(CurrencyExchangeRate $rate): Item - { - return $this->item($rate->toCurrency, new CurrencyTransformer($this->parameters), 'transaction_currencies'); - } - /** * @param CurrencyExchangeRate $rate * @@ -93,6 +59,7 @@ class CurrencyExchangeRateTransformer extends TransformerAbstract 'id' => (int)$rate->id, 'updated_at' => $rate->updated_at->toAtomString(), 'created_at' => $rate->created_at->toAtomString(), + 'date' => $rate->date->format('Y-m-d'), 'rate' => (float)$rate->rate, 'links' => [ [ diff --git a/app/Transformers/CurrencyTransformer.php b/app/Transformers/CurrencyTransformer.php index 65a469adea..a12e2ed238 100644 --- a/app/Transformers/CurrencyTransformer.php +++ b/app/Transformers/CurrencyTransformer.php @@ -32,19 +32,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class CurrencyTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = []; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = []; - /** @var ParameterBag */ protected $parameters; diff --git a/app/Transformers/JournalMetaTransformer.php b/app/Transformers/JournalMetaTransformer.php index 125304b05b..903bc349d1 100644 --- a/app/Transformers/JournalMetaTransformer.php +++ b/app/Transformers/JournalMetaTransformer.php @@ -36,19 +36,6 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class JournalMetaTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['transactions']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = []; - /** @var ParameterBag */ protected $parameters; @@ -64,34 +51,6 @@ class JournalMetaTransformer extends TransformerAbstract $this->parameters = $parameters; } - /** - * Include any transactions. - * - * @param TransactionJournalMeta $meta - * - * @codeCoverageIgnore - * @return FractalCollection - */ - public function includeTransactions(TransactionJournalMeta $meta): FractalCollection - { - $journal = $meta->transactionJournal; - $pageSize = (int)app('preferences')->getForUser($journal->user, 'listPageSize', 50)->data; - - // journals always use collector and limited using URL parameters. - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($journal->user); - $collector->withOpposingAccount()->withCategoryInformation()->withCategoryInformation(); - $collector->setAllAssetAccounts(); - $collector->setJournals(new Collection([$journal])); - if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { - $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); - } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $transactions= $collector->getTransactions(); - - return $this->collection($transactions, new TransactionTransformer($this->parameters), 'transactions'); - } - /** * Convert meta object. * diff --git a/config/firefly.php b/config/firefly.php index abb028bd36..7ff78eeee1 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -304,6 +304,7 @@ return [ // strings 'import_provider' => \FireflyIII\Support\Binder\ImportProvider::class, + 'currency_code' => \FireflyIII\Support\Binder\CurrencyCode::class, // dates 'start_date' => \FireflyIII\Support\Binder\Date::class, diff --git a/routes/api.php b/routes/api.php index f1ac12c79a..a522de9f89 100644 --- a/routes/api.php +++ b/routes/api.php @@ -258,9 +258,22 @@ Route::group( // Transaction currency API routes: Route::get('', ['uses' => 'CurrencyController@index', 'as' => 'index']); Route::post('', ['uses' => 'CurrencyController@store', 'as' => 'store']); - Route::get('{currency}', ['uses' => 'CurrencyController@show', 'as' => 'show']); - Route::put('{currency}', ['uses' => 'CurrencyController@update', 'as' => 'update']); - Route::delete('{currency}', ['uses' => 'CurrencyController@delete', 'as' => 'delete']); + Route::get('{currency_code}', ['uses' => 'CurrencyController@show', 'as' => 'show']); + Route::put('{currency_code}', ['uses' => 'CurrencyController@update', 'as' => 'update']); + Route::delete('{currency_code}', ['uses' => 'CurrencyController@delete', 'as' => 'delete']); + + Route::post('{currency_code}/enable', ['uses' => 'CurrencyController@enable', 'as' => 'enable']); + Route::post('{currency_code}/disable', ['uses' => 'CurrencyController@disable', 'as' => 'disable']); + Route::post('{currency_code}/default', ['uses' => 'CurrencyController@makeDefault', 'as' => 'default']); + + Route::get('{currency_code}/accounts', ['uses' => 'CurrencyController@accounts', 'as' => 'accounts']); + Route::get('{currency_code}/available_budgets', ['uses' => 'CurrencyController@availableBudgets', 'as' => 'available_budgets']); + Route::get('{currency_code}/bills', ['uses' => 'CurrencyController@bills', 'as' => 'bills']); + Route::get('{currency_code}/budget_limits', ['uses' => 'CurrencyController@budgetLimits', 'as' => 'budget_limits']); + Route::get('{currency_code}/cer', ['uses' => 'CurrencyController@cer', 'as' => 'cer']); + Route::get('{currency_code}/recurrences', ['uses' => 'CurrencyController@recurrences', 'as' => 'recurrences']); + Route::get('{currency_code}/rules', ['uses' => 'CurrencyController@rules', 'as' => 'rules']); + Route::get('{currency_code}/transactions', ['uses' => 'CurrencyController@transactions', 'as' => 'transactions']); } );