Refactored and extended link types.

This commit is contained in:
James Cole 2018-12-08 07:57:29 +01:00
parent 07450f9f23
commit 494aa15567
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
10 changed files with 158 additions and 94 deletions

View File

@ -25,10 +25,16 @@ namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\LinkTypeRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Helpers\Filter\InternalTransferFilter;
use FireflyIII\Models\LinkType;
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\Transformers\LinkTypeTransformer;
use FireflyIII\Transformers\TransactionTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@ -46,6 +52,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
*/
class LinkTypeController extends Controller
{
use Transactions;
/** @var LinkTypeRepositoryInterface The link type repository */
private $repository;
@ -174,6 +181,58 @@ class LinkTypeController extends Controller
}
/**
* Delete the resource.
*
* @param LinkType $linkType
*
* @return JsonResponse
*/
public function transactions(Request $request, LinkType $linkType): 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));
// whatever is returned by the query, it must be part of these journals:
$journalIds = $this->repository->getJournalIds($linkType);
/** @var User $admin */
$admin = auth()->user();
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
$collector->setUser($admin);
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
$collector->setAllAssetAccounts();
$collector->setJournalIds($journalIds);
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');
}
/**
* Update object.
*

View File

@ -27,6 +27,7 @@ use FireflyIII\Api\V1\Requests\PiggyBankRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Transformers\PiggyBankEventTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@ -117,6 +118,38 @@ class PiggyBankController extends Controller
}
/**
* List single resource.
*
* @param Request $request
* @param PiggyBank $piggyBank
*
* @return JsonResponse
*/
public function piggyBankEvents(Request $request, PiggyBank $piggyBank): JsonResponse
{
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$collection = $piggyBank->piggyBankEvents()->get();
$count = $collection->count();
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy_banks.events', [$piggyBank->id]) . $this->buildParams());
$resource = new FractalCollection($events, new PiggyBankEventTransformer($this->parameters), 'piggy_bank_events');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List single resource.
*

View File

@ -138,10 +138,6 @@ class RuleController extends Controller
public function show(Request $request, Rule $rule): JsonResponse
{
$manager = new Manager();
// add include parameter:
$include = $request->get('include') ?? '';
$manager->parseIncludes($include);
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));

View File

@ -1,6 +1,6 @@
<?php
/**
* JournalLinkController.php
* TransactionLinkController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
@ -28,6 +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\Transformers\JournalLinkTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@ -40,12 +41,12 @@ use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
/**
* Class JournalLinkController.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* Class TransactionLinkController
*/
class JournalLinkController extends Controller
class TransactionLinkController extends Controller
{
use Transactions;
/** @var JournalRepositoryInterface The journal repository */
private $journalRepository;
/** @var LinkTypeRepositoryInterface The link type repository */
@ -105,21 +106,20 @@ class JournalLinkController extends Controller
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$linkType = $this->repository->findByName($name);
// get list of accounts. Count it and split it.
// get list of transaction links. Count it and split it.
$collection = $this->repository->getJournalLinks($linkType);
$count = $collection->count();
$journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.journal_links.index') . $this->buildParams());
$paginator->setPath(route('api.v1.transaction_links.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$resource = new FractalCollection($journalLinks, new JournalLinkTransformer($this->parameters), 'journal_links');
$resource = new FractalCollection($journalLinks, new JournalLinkTransformer($this->parameters), 'transaction_links');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
@ -144,7 +144,7 @@ class JournalLinkController extends Controller
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'transaction_links');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
@ -175,7 +175,7 @@ class JournalLinkController extends Controller
$data['direction'] = 'inward';
$journalLink = $this->repository->storeLink($data, $inward, $outward);
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'transaction_links');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
@ -208,7 +208,7 @@ class JournalLinkController extends Controller
$data['direction'] = 'inward';
$journalLink = $this->repository->updateLink($journalLink, $data);
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'transaction_links');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');

View File

@ -71,8 +71,8 @@ class JournalLinkRequest extends Request
return [
'link_type_id' => 'exists:link_types,id|required_without:link_type_name',
'link_type_name' => 'exists:link_types,name|required_without:link_type_id',
'inward_id' => 'required|belongsToUser:transaction_journals,id',
'outward_id' => 'required|belongsToUser:transaction_journals,id',
'inward_id' => 'required|belongsToUser:transaction_journals,id|different:outward_id',
'outward_id' => 'required|belongsToUser:transaction_journals,id|different:inward_id',
'notes' => 'between:0,65000',
];
}
@ -124,8 +124,12 @@ class JournalLinkRequest extends Request
}
if ($repository->findLink($inward, $outward)) {
$validator->errors()->add('outward_id', 'Already have a link between inward and outward.');
$validator->errors()->add('inward_id', 'Already have a link between inward and outward.');
// only if not updating:
$link = $this->route()->parameter('journalLink');
if (null === $link) {
$validator->errors()->add('outward_id', 'Already have a link between inward and outward.');
$validator->errors()->add('inward_id', 'Already have a link between inward and outward.');
}
}
}
}

View File

@ -156,6 +156,22 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface
return LinkType::orderBy('name', 'ASC')->get();
}
/**
* Return array of all journal ID's for this type of link.
*
* @param LinkType $linkType
*
* @return array
*/
public function getJournalIds(LinkType $linkType): array
{
$links = $linkType->transactionJournalLinks()->get(['source_id', 'destination_id']);
$sources = $links->pluck('source_id')->toArray();
$destinations = $links->pluck('destination_id')->toArray();
return array_unique(array_merge($sources, $destinations));
}
/**
* Returns all the journal links (of a specific type).
*

View File

@ -97,6 +97,15 @@ interface LinkTypeRepositoryInterface
*/
public function get(): Collection;
/**
* Return array of all journal ID's for this type of link.
*
* @param LinkType $linkType
*
* @return array
*/
public function getJournalIds(LinkType $linkType): array;
/**
* @param LinkType|null $linkType
*

View File

@ -24,11 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Transformers;
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Models\Note;
use FireflyIII\Models\TransactionJournalLink;
use Illuminate\Support\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
use Symfony\Component\HttpFoundation\ParameterBag;
@ -38,19 +35,6 @@ use Symfony\Component\HttpFoundation\ParameterBag;
*/
class JournalLinkTransformer extends TransformerAbstract
{
/**
* List of resources possible to include
*
* @var array
*/
protected $availableIncludes = ['inward', 'outward', 'link_type'];
/**
* List of resources to automatically include
*
* @var array
*/
protected $defaultIncludes = ['inward', 'outward', 'link_type'];
/** @var ParameterBag */
protected $parameters;
@ -66,54 +50,6 @@ class JournalLinkTransformer extends TransformerAbstract
$this->parameters = $parameters;
}
/**
* @param TransactionJournalLink $link
*
* @return Item
*/
public function includeInward(TransactionJournalLink $link): Item
{
// need to use the collector to get the transaction :(
// journals always use collector and limited using URL parameters.
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
$collector->setUser($link->source->user);
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
$collector->setJournals(new Collection([$link->source]));
$transactions = $collector->getTransactions();
return $this->item($transactions->first(), new TransactionTransformer($this->parameters), 'transactions');
}
/**
* @param TransactionJournalLink $link
*
* @return Item
*/
public function includeLinkType(TransactionJournalLink $link): Item
{
return $this->item($link->linkType, new LinkTypeTransformer($this->parameters), 'link_types');
}
/**
* @param TransactionJournalLink $link
*
* @return Item
*/
public function includeOutward(TransactionJournalLink $link): Item
{
// need to use the collector to get the transaction :(
// journals always use collector and limited using URL parameters.
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
$collector->setUser($link->source->user);
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
$collector->setJournals(new Collection([$link->destination]));
$transactions = $collector->getTransactions();
return $this->item($transactions->first(), new TransactionTransformer($this->parameters), 'transactions');
}
/**
* @param TransactionJournalLink $link
*
@ -121,7 +57,7 @@ class JournalLinkTransformer extends TransformerAbstract
*/
public function transform(TransactionJournalLink $link): array
{
$notes = '';
$notes = null;
/** @var Note $note */
$note = $link->notes()->first();
if (null !== $note) {
@ -132,11 +68,13 @@ class JournalLinkTransformer extends TransformerAbstract
'id' => (int)$link->id,
'updated_at' => $link->updated_at->toAtomString(),
'created_at' => $link->created_at->toAtomString(),
'inward_id' => $link->source_id,
'outward_id' => $link->destination_id,
'notes' => $notes,
'links' => [
[
'rel' => 'self',
'uri' => '/journal_links/' . $link->id,
'uri' => '/transaction_links/' . $link->id,
],
],
];

View File

@ -40,8 +40,6 @@ use Symfony\Component\HttpFoundation\ParameterBag;
*/
class PiggyBankTransformer extends TransformerAbstract
{
/** @var ParameterBag */
protected $parameters;

View File

@ -147,12 +147,7 @@ Route::group(
['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'journal_links', 'as' => 'api.v1.journal_links.'],
function () {
// Journal Link API routes:
Route::get('', ['uses' => 'JournalLinkController@index', 'as' => 'index']);
Route::post('', ['uses' => 'JournalLinkController@store', 'as' => 'store']);
Route::get('{journalLink}', ['uses' => 'JournalLinkController@show', 'as' => 'show']);
Route::put('{journalLink}', ['uses' => 'JournalLinkController@update', 'as' => 'update']);
Route::delete('{journalLink}', ['uses' => 'JournalLinkController@delete', 'as' => 'delete']);
}
);
@ -166,6 +161,21 @@ Route::group(
Route::get('{linkType}', ['uses' => 'LinkTypeController@show', 'as' => 'show']);
Route::put('{linkType}', ['uses' => 'LinkTypeController@update', 'as' => 'update']);
Route::delete('{linkType}', ['uses' => 'LinkTypeController@delete', 'as' => 'delete']);
Route::get('{linkType}/transactions', ['uses' => 'LinkTypeController@transactions', 'as' => 'transactions']);
}
);
Route::group(
['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'transaction_links', 'as' => 'api.v1.transaction_links.'],
function () {
// Transaction Links API routes:
Route::get('', ['uses' => 'TransactionLinkController@index', 'as' => 'index']);
Route::post('', ['uses' => 'TransactionLinkController@store', 'as' => 'store']);
Route::get('{journalLink}', ['uses' => 'TransactionLinkController@show', 'as' => 'show']);
Route::put('{journalLink}', ['uses' => 'TransactionLinkController@update', 'as' => 'update']);
Route::delete('{journalLink}', ['uses' => 'TransactionLinkController@delete', 'as' => 'delete']);
}
);
@ -177,6 +187,7 @@ Route::group(
Route::get('', ['uses' => 'PiggyBankController@index', 'as' => 'index']);
Route::post('', ['uses' => 'PiggyBankController@store', 'as' => 'store']);
Route::get('{piggyBank}', ['uses' => 'PiggyBankController@show', 'as' => 'show']);
Route::get('{piggyBank}/events', ['uses' => 'PiggyBankController@piggyBankEvents', 'as' => 'events']);
Route::put('{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'update']);
Route::delete('{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'delete']);
}