From c0d6d0e28e11605574826f0ad929c5728e31730a Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 3 Dec 2018 15:57:15 +0100 Subject: [PATCH] Update API to match new end points. --- .../V1/Controllers/TransactionController.php | 24 +--- app/Api/V1/Controllers/UserController.php | 12 -- app/Api/V1/Requests/TransactionRequest.php | 31 +++- app/Factory/TransactionFactory.php | 15 +- .../Transaction/MassController.php | 2 +- .../Controllers/TransactionController.php | 2 +- .../Journal/JournalRepository.php | 18 +++ .../Journal/JournalRepositoryInterface.php | 33 +++-- .../Http/Controllers/RequestInformation.php | 4 +- app/Transformers/AccountTransformer.php | 5 +- app/Transformers/TransactionTransformer.php | 136 +++++------------- 11 files changed, 123 insertions(+), 159 deletions(-) diff --git a/app/Api/V1/Controllers/TransactionController.php b/app/Api/V1/Controllers/TransactionController.php index 870c4c635c..59a64a288a 100644 --- a/app/Api/V1/Controllers/TransactionController.php +++ b/app/Api/V1/Controllers/TransactionController.php @@ -129,7 +129,7 @@ class TransactionController extends Controller $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); $transactions = $paginator->getCollection(); - $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $this->repository), 'transactions'); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); @@ -141,21 +141,15 @@ class TransactionController extends Controller * * @param Request $request * @param Transaction $transaction - * @param string $include * * @return JsonResponse */ - public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse + public function show(Request $request, Transaction $transaction): JsonResponse { $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // add include parameter: - $include = $include ?? ''; - $include = $request->get('include') ?? $include; - $manager->parseIncludes($include); - // collect transactions using the journal collector $collector = app(TransactionCollectorInterface::class); $collector->setUser(auth()->user()); @@ -173,7 +167,7 @@ class TransactionController extends Controller } $transactions = $collector->getTransactions(); - $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $this->repository), 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } @@ -200,10 +194,6 @@ class TransactionController extends Controller $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // add include parameter: - $include = $request->get('include') ?? ''; - $manager->parseIncludes($include); - // collect transactions using the journal collector $collector = app(TransactionCollectorInterface::class); $collector->setUser(auth()->user()); @@ -221,7 +211,7 @@ class TransactionController extends Controller } $transactions = $collector->getTransactions(); - $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $this->repository), 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } @@ -247,10 +237,6 @@ class TransactionController extends Controller event(new UpdatedTransactionJournal($journal)); - // add include parameter: - $include = $request->get('include') ?? ''; - $manager->parseIncludes($include); - // needs a lot of extra data to match the journal collector. Or just expand that one. // collect transactions using the journal collector $collector = app(TransactionCollectorInterface::class); @@ -269,7 +255,7 @@ class TransactionController extends Controller } $transactions = $collector->getTransactions(); - $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters, $this->repository), 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); diff --git a/app/Api/V1/Controllers/UserController.php b/app/Api/V1/Controllers/UserController.php index 22bc71200f..9624fc04e6 100644 --- a/app/Api/V1/Controllers/UserController.php +++ b/app/Api/V1/Controllers/UserController.php @@ -134,10 +134,6 @@ class UserController extends Controller $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // add include parameter: - $include = $request->get('include') ?? ''; - $manager->parseIncludes($include); - // make resource $resource = new Item($user, new UserTransformer($this->parameters), 'users'); @@ -161,10 +157,6 @@ class UserController extends Controller $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // add include parameter: - $include = $request->get('include') ?? ''; - $manager->parseIncludes($include); - // make resource $resource = new Item($user, new UserTransformer($this->parameters), 'users'); @@ -189,10 +181,6 @@ class UserController extends Controller $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // add include parameter: - $include = $request->get('include') ?? ''; - $manager->parseIncludes($include); - // make resource $resource = new Item($user, new UserTransformer($this->parameters), 'users'); diff --git a/app/Api/V1/Requests/TransactionRequest.php b/app/Api/V1/Requests/TransactionRequest.php index 293c43f1c0..a3702ee9cd 100644 --- a/app/Api/V1/Requests/TransactionRequest.php +++ b/app/Api/V1/Requests/TransactionRequest.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; use FireflyIII\Rules\BelongsUser; +use FireflyIII\Rules\IsBoolean; use FireflyIII\Validation\TransactionValidation; use Illuminate\Validation\Validator; @@ -73,8 +74,21 @@ class TransactionRequest extends Request 'invoice_date' => $this->date('invoice_date'), 'internal_reference' => $this->string('internal_reference'), 'notes' => $this->string('notes'), - 'original-source' => sprintf('api-v%s', config('firefly.api_version')), + 'original-source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'),config('firefly.api_version')), 'transactions' => $this->getTransactionData(), + + // SEPA fields: + 'sepa-cc' => $this->string('sepa_cc'), + 'sepa-ct-op' => $this->string('sepa_ct_op'), + 'sepa-db' => $this->string('sepa_db'), + 'sepa-country' => $this->string('sepa_country'), + 'sepa-ep' => $this->string('sepa_ep'), + 'sepa-ci' => $this->string('sepa_ci'), + 'sepa-batch-id' => $this->string('sepa_batch_id'), + + // others: + 'bunq_payment_id' => $this->string('bunq_payment_id'), + 'external_id' => $this->string('external_id'), ]; return $data; @@ -109,11 +123,20 @@ class TransactionRequest extends Request 'internal_reference' => 'min:1,max:255|nullable', 'notes' => 'min:1,max:50000|nullable', + // SEPA fields: + 'sepa_cc' => 'min:1,max:255|nullable', + 'sepa_ct_op' => 'min:1,max:255|nullable', + 'sepa_db' => 'min:1,max:255|nullable', + 'sepa_country' => 'min:1,max:255|nullable', + 'sepa_ep' => 'min:1,max:255|nullable', + 'sepa_ci' => 'min:1,max:255|nullable', + 'sepa_batch_id' => 'min:1,max:255|nullable', + // transaction rules (in array for splits): 'transactions.*.description' => 'nullable|between:1,255', 'transactions.*.amount' => 'required|numeric|more:0', - 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code', - 'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id', + 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id', + 'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'transactions.*.foreign_amount' => 'numeric|more:0', 'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id', 'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code', @@ -121,7 +144,7 @@ class TransactionRequest extends Request 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser], 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser], 'transactions.*.category_name' => 'between:1,255|nullable', - 'transactions.*.reconciled' => 'boolean|nullable', + 'transactions.*.reconciled' => [new IsBoolean], // basic rules will be expanded later. 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser], 'transactions.*.source_name' => 'between:1,255|nullable', diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index 0f2e719f3a..6d067731bd 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -40,6 +40,11 @@ use Log; */ class TransactionFactory { + /** @var User */ + private $user; + + use TransactionServiceTrait; + /** * Constructor. */ @@ -50,11 +55,6 @@ class TransactionFactory } } - use TransactionServiceTrait; - - /** @var User */ - private $user; - /** * @param array $data * @@ -109,8 +109,9 @@ class TransactionFactory Log::debug('Start of TransactionFactory::createPair()', $data); // all this data is the same for both transactions: Log::debug('Searching for currency info.'); - $currency = $this->findCurrency($data['currency_id'], $data['currency_code']); - //$description = $data['description']; + $defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user); + $currency = $this->findCurrency($data['currency_id'], $data['currency_code']); + $currency = $currency ?? $defaultCurrency; // type of source account and destination account depends on journal type: $sourceType = $this->accountType($journal, 'source'); diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index f70652c4f8..8f3274ee18 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -142,7 +142,7 @@ class MassController extends Controller $this->rememberPreviousUri('transactions.mass-edit.uri'); - $transformer = new TransactionTransformer(new ParameterBag); + $transformer = new TransactionTransformer(new ParameterBag, $this->repository); /** @var TransactionCollectorInterface $collector */ $collector = app(TransactionCollectorInterface::class); $collector->setUser($user); diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 2cabef11f7..0a96f29113 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -253,7 +253,7 @@ class TransactionController extends Controller $collector->setJournals(new Collection([$journal])); $set = $collector->getTransactions(); $transactions = []; - $transformer = new TransactionTransformer(new ParameterBag); + $transformer = new TransactionTransformer(new ParameterBag, $this->repository); /** @var Transaction $transaction */ foreach ($set as $transaction) { $transactions[] = $transformer->transform($transaction); diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 61fe3e768a..0cb89a007d 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -474,6 +474,24 @@ class JournalRepository implements JournalRepositoryInterface return $value; } + /** + * Return string value of a meta date (or NULL). + * + * @param TransactionJournal $journal + * @param string $field + * + * @return null|string + */ + public function getMetaDateString(TransactionJournal $journal, string $field): ?string + { + $date = $this->getMetaDate($journal, $field); + if (null === $date) { + return null; + } + + return $date->format('Y-m-d'); + } + /** * Return value of a meta field (or NULL) as a string. * diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 42d1d59322..69d2958b71 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -38,17 +38,6 @@ use Illuminate\Support\MessageBag; */ interface JournalRepositoryInterface { - /** - * Return all attachments for journal. - * - * @param TransactionJournal $journal - * - * @return Collection - */ - public function getAttachments(TransactionJournal $journal): Collection; - - - /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param TransactionJournal $journal * @param TransactionType $type @@ -59,6 +48,9 @@ interface JournalRepositoryInterface */ public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag; + + /** @noinspection MoreThanThreeArgumentsInspection */ + /** * @param TransactionJournal $journal * @@ -121,6 +113,15 @@ interface JournalRepositoryInterface */ public function getAssetTransaction(TransactionJournal $journal): ?Transaction; + /** + * Return all attachments for journal. + * + * @param TransactionJournal $journal + * + * @return Collection + */ + public function getAttachments(TransactionJournal $journal): Collection; + /** * Returns the first positive transaction for the journal. Useful when editing journals. * @@ -196,6 +197,16 @@ interface JournalRepositoryInterface */ public function getMetaDate(TransactionJournal $journal, string $field): ?Carbon; + /** + * Return string value of a meta date (or NULL). + * + * @param TransactionJournal $journal + * @param string $field + * + * @return null|string + */ + public function getMetaDateString(TransactionJournal $journal, string $field): ?string; + /** * Return value of a meta field (or NULL). * diff --git a/app/Support/Http/Controllers/RequestInformation.php b/app/Support/Http/Controllers/RequestInformation.php index 76004eddfa..900fbad168 100644 --- a/app/Support/Http/Controllers/RequestInformation.php +++ b/app/Support/Http/Controllers/RequestInformation.php @@ -33,6 +33,7 @@ use FireflyIII\Http\Requests\TestRuleFormRequest; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\Binder\AccountList; use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; @@ -221,6 +222,7 @@ trait RequestInformation */ protected function getTransactionDataFromJournal(TransactionJournal $journal): array // convert object { + $repository = app(JournalRepositoryInterface::class); // use collector to collect transactions. $collector = app(TransactionCollectorInterface::class); $collector->setUser(auth()->user()); @@ -229,7 +231,7 @@ trait RequestInformation $collector->setJournals(new Collection([$journal])); $set = $collector->getTransactions(); $transactions = []; - $transformer = new TransactionTransformer(new ParameterBag); + $transformer = new TransactionTransformer(new ParameterBag, $repository); /** @var Transaction $transaction */ foreach ($set as $transaction) { $res = []; diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index a621389935..951e9454b5 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Support\Collection; use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; @@ -118,7 +119,9 @@ class AccountTransformer extends TransformerAbstract $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); $transactions = $collector->getTransactions(); - return $this->collection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + $journalRepos = app(JournalRepositoryInterface::class); + + return $this->collection($transactions, new TransactionTransformer($this->parameters, $journalRepos), 'transactions'); } /** diff --git a/app/Transformers/TransactionTransformer.php b/app/Transformers/TransactionTransformer.php index 60a5f75f16..24e8148457 100644 --- a/app/Transformers/TransactionTransformer.php +++ b/app/Transformers/TransactionTransformer.php @@ -25,11 +25,9 @@ namespace FireflyIII\Transformers; use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Note; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; -use League\Fractal\Resource\Collection as FractalCollection; -use League\Fractal\Resource\Item; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use League\Fractal\TransformerAbstract; use Log; use Symfony\Component\HttpFoundation\ParameterBag; @@ -39,111 +37,26 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ class TransactionTransformer extends TransformerAbstract { - /** - * List of resources possible to include - * - * @var array - */ - protected $availableIncludes = ['attachments', 'user', 'tags', 'journal_meta', 'piggy_bank_events']; - /** - * List of resources to automatically include - * - * @var array - */ - protected $defaultIncludes = []; - /** @var ParameterBag */ protected $parameters; + /** @var JournalRepositoryInterface */ + protected $repository; + /** * TransactionTransformer constructor. * * @codeCoverageIgnore * - * @param ParameterBag $parameters + * @param ParameterBag $parameters + * @param JournalRepositoryInterface $repository */ - public function __construct(ParameterBag $parameters) + public function __construct(ParameterBag $parameters, JournalRepositoryInterface $repository) { $this->parameters = $parameters; + $this->repository = $repository; } - /** - * Include attachments. - * - * @codeCoverageIgnore - * - * @param Transaction $transaction - * - * @return FractalCollection - */ - public function includeAttachments(Transaction $transaction): FractalCollection - { - return $this->collection($transaction->transactionJournal->attachments, new AttachmentTransformer($this->parameters), 'attachments'); - } - - /** - * Include meta data - * - * @codeCoverageIgnore - * - * @param Transaction $transaction - * - * @return FractalCollection - */ - public function includeJournalMeta(Transaction $transaction): FractalCollection - { - $meta = $transaction->transactionJournal->transactionJournalMeta()->get(); - - return $this->collection($meta, new JournalMetaTransformer($this->parameters), 'journal_meta'); - } - - /** - * Include piggy bank events - * - * @codeCoverageIgnore - * - * @param Transaction $transaction - * - * @return FractalCollection - */ - public function includePiggyBankEvents(Transaction $transaction): FractalCollection - { - $events = $transaction->transactionJournal->piggyBankEvents()->get(); - - return $this->collection($events, new PiggyBankEventTransformer($this->parameters), 'piggy_bank_events'); - } - - /** - * Include tags - * - * @codeCoverageIgnore - * - * @param Transaction $transaction - * - * @return FractalCollection - */ - public function includeTags(Transaction $transaction): FractalCollection - { - $set = $transaction->transactionJournal->tags; - - return $this->collection($set, new TagTransformer($this->parameters), 'tags'); - } - - /** - * Include the user. - * - * @codeCoverageIgnore - * - * @param Transaction $transaction - * - * @return \League\Fractal\Resource\Item - */ - public function includeUser(Transaction $transaction): Item - { - return $this->item($transaction->transactionJournal->user, new UserTransformer($this->parameters), 'users'); - } - - /** * Transform the journal. * @@ -160,17 +73,15 @@ class TransactionTransformer extends TransformerAbstract $budgetName = null; $categoryId = $transaction->transaction_category_id ?? $transaction->transaction_journal_category_id; $categoryName = $transaction->transaction_category_name ?? $transaction->transaction_journal_category_name; - + $journal = $transaction->transactionJournal; + $notes = $this->repository->getNoteText($journal); if ($transaction->transaction_type_type === TransactionType::WITHDRAWAL) { $budgetId = $transaction->transaction_budget_id ?? $transaction->transaction_journal_budget_id; $budgetName = $transaction->transaction_budget_name ?? $transaction->transaction_journal_budget_name; } - /** @var Note $dbNote */ - $dbNote = $transaction->transactionJournal->notes()->first(); - $notes = null; - if (null !== $dbNote) { - $notes = $dbNote->text; - } + // get tags: + $tags = implode(',', $journal->tags->pluck('tag')->toArray()); + $data = [ 'id' => (int)$transaction->id, @@ -200,6 +111,27 @@ class TransactionTransformer extends TransformerAbstract 'budget_id' => $budgetId, 'budget_name' => $budgetName, 'notes' => $notes, + 'sepa_cc' => $this->repository->getMetaField($journal, 'sepa-cc'), + 'sepa_ct_op' => $this->repository->getMetaField($journal, 'sepa-ct-op'), + 'sepa_ct_id' => $this->repository->getMetaField($journal, 'sepa-ct-ud'), + 'sepa_db' => $this->repository->getMetaField($journal, 'sepa-db'), + 'sepa_country' => $this->repository->getMetaField($journal, 'sepa-country'), + 'sepa_ep' => $this->repository->getMetaField($journal, 'sepa-ep'), + 'sepa_ci' => $this->repository->getMetaField($journal, 'sepa-ci'), + 'sepa_batch_id' => $this->repository->getMetaField($journal, 'sepa-batch-id'), + 'interest_date' => $this->repository->getMetaDateString($journal, 'interest_date'), + 'book_date' => $this->repository->getMetaDateString($journal, 'book_date'), + 'process_date' => $this->repository->getMetaDateString($journal, 'process_date'), + 'due_date' => $this->repository->getMetaDateString($journal, 'due_date'), + 'payment_date' => $this->repository->getMetaDateString($journal, 'payment_date'), + 'invoice_date' => $this->repository->getMetaDateString($journal, 'invoice_date'), + 'internal_reference' => $this->repository->getMetaField($journal, 'internal_reference'), + 'bunq_payment_id' => $this->repository->getMetaField($journal, 'bunq_payment_id'), + 'importHashV2' => $this->repository->getMetaField($journal, 'importHashV2'), + 'recurrence_id' => (int)$this->repository->getMetaField($journal, 'recurrence_id'), + 'external_id' => $this->repository->getMetaField($journal, 'external_id'), + 'original_source' => $this->repository->getMetaField($journal, 'original-source'), + 'tags' => '' === $tags ? null : $tags, 'links' => [ [ 'rel' => 'self',