From 3b15415a1ba4f58a294a7345159a9b10adca6384 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 8 Dec 2018 08:22:53 +0100 Subject: [PATCH] Build import job API endpoint. --- app/Api/V1/Controllers/ImportController.php | 173 ++++++++++++++++++ app/Models/ImportJob.php | 1 + .../ImportJob/ImportJobRepository.php | 10 + .../ImportJobRepositoryInterface.php | 8 +- app/Transformers/ImportJobTransformer.php | 93 ++++++++++ routes/api.php | 8 +- 6 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 app/Api/V1/Controllers/ImportController.php create mode 100644 app/Transformers/ImportJobTransformer.php diff --git a/app/Api/V1/Controllers/ImportController.php b/app/Api/V1/Controllers/ImportController.php new file mode 100644 index 0000000000..fa82b6c41e --- /dev/null +++ b/app/Api/V1/Controllers/ImportController.php @@ -0,0 +1,173 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use FireflyIII\Helpers\Collector\TransactionCollectorInterface; +use FireflyIII\Helpers\Filter\InternalTransferFilter; +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\Transformers\ImportJobTransformer; +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; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; + +/** + * Class ImportController + */ +class ImportController extends Controller +{ + use Transactions; + /** @var ImportJobRepositoryInterface Import job repository. */ + private $repository; + + /** + * LinkTypeController constructor. + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + /** + * @param Request $request + * + * @return JsonResponse + */ + public function listAll(Request $request): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of accounts. Count it and split it. + $collection = $this->repository->get(); + $count = $collection->count(); + $importJobs = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($importJobs, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.import.list') . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($importJobs, new ImportJobTransformer($this->parameters), 'import_jobs'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param Request $request + * @param ImportJob $importJob + * + * @return JsonResponse + */ + public function show(Request $request, ImportJob $importJob): JsonResponse + { + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new Item($importJob, new ImportJobTransformer($this->parameters), 'import_jobs'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * Show all transactions + * + * @param ImportJob $importJob + * + * @return JsonResponse + */ + public function transactions(Request $request, ImportJob $importJob): JsonResponse + { + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $type = $request->get('type') ?? 'default'; + $this->parameters->set('type', $type); + + $types = $this->mapTypes($this->parameters->get('type')); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $tag = $importJob->tag; + $transactions = new Collection(); + $paginator = new LengthAwarePaginator($transactions, 0, $pageSize); + $paginator->setPath(route('api.v1.import.transactions', [$importJob->key]) . $this->buildParams()); + + if (null !== $tag) { + /** @var User $admin */ + $admin = auth()->user(); + /** @var TransactionCollectorInterface $collector */ + $collector = app(TransactionCollectorInterface::class); + $collector->setUser($admin); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + $collector->setAllAssetAccounts(); + $collector->setTag($tag); + + 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.transactions.index') . $this->buildParams()); + $transactions = $paginator->getCollection(); + } + + + $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'); + } + +} \ No newline at end of file diff --git a/app/Models/ImportJob.php b/app/Models/ImportJob.php index b45502a5cf..90f5cefd3c 100644 --- a/app/Models/ImportJob.php +++ b/app/Models/ImportJob.php @@ -47,6 +47,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property array extended_status * @property int id * @property Carbon $created_at + * @property Carbon $updated_at */ class ImportJob extends Model { diff --git a/app/Repositories/ImportJob/ImportJobRepository.php b/app/Repositories/ImportJob/ImportJobRepository.php index 2a9fec1634..81dc62f07b 100644 --- a/app/Repositories/ImportJob/ImportJobRepository.php +++ b/app/Repositories/ImportJob/ImportJobRepository.php @@ -170,6 +170,16 @@ class ImportJobRepository implements ImportJobRepositoryInterface return $result; } + /** + * Return all import jobs. + * + * @return Collection + */ + public function get(): Collection + { + return $this->user->importJobs()->get(); + } + /** * Return all attachments for job. * diff --git a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php index ad621010f1..e1cec397cb 100644 --- a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php +++ b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php @@ -35,7 +35,6 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; */ interface ImportJobRepositoryInterface { - /** * Add message to job. * @@ -77,6 +76,13 @@ interface ImportJobRepositoryInterface */ public function findByKey(string $key): ?ImportJob; + /** + * Return all import jobs. + * + * @return Collection + */ + public function get(): Collection; + /** * Return all attachments for job. * diff --git a/app/Transformers/ImportJobTransformer.php b/app/Transformers/ImportJobTransformer.php new file mode 100644 index 0000000000..eea2f82d4a --- /dev/null +++ b/app/Transformers/ImportJobTransformer.php @@ -0,0 +1,93 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Models\ImportJob; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class ImportJobTransformer + */ +class ImportJobTransformer extends TransformerAbstract +{ + /** @var ParameterBag */ + protected $parameters; + + /** + * PiggyBankTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + + /** + * Transform the import job. + * + * @param ImportJob $importJob + * + * @return array + */ + public function transform(ImportJob $importJob): array + { + $tag= $importJob->tag; + $tagId = null; + $tagTag = null; + if(null !== $tag) { + $tagId = $tag->id; + $tagTag = $tag->tag; + } + $data = [ + 'id' => (int)$importJob->id, + 'updated_at' => $importJob->updated_at->toAtomString(), + 'created_at' => $importJob->created_at->toAtomString(), + 'key' => $importJob->key, + 'file_type' => $importJob->file_type, + 'provider' => $importJob->provider, + 'status' => $importJob->status, + 'stage' => $importJob->stage, + 'configuration' => $importJob->configuration, + 'extended_status' => $importJob->extended_status, + 'transactions' => $importJob->transactions, + 'errors' => $importJob->errors, + 'tag_id' => $tagId, + 'tag_tag' => $tagTag, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/import/' . $importJob->key, + ], + ], + ]; + + return $data; + } +} diff --git a/routes/api.php b/routes/api.php index 81e9fcbf26..f1ac12c79a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -144,13 +144,15 @@ Route::group( ); Route::group( - ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'journal_links', 'as' => 'api.v1.journal_links.'], + ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'import', 'as' => 'api.v1.import.'], function () { - + // Transaction Links API routes: + Route::get('list', ['uses' => 'ImportController@listAll', 'as' => 'list']); + Route::get('{importJob}', ['uses' => 'ImportController@show', 'as' => 'show']); + Route::get('{importJob}/transactions', ['uses' => 'ImportController@transactions', 'as' => 'transactions']); } ); - Route::group( ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'link_types', 'as' => 'api.v1.link_types.'], function () {