Various new stuff

This commit is contained in:
James Cole
2022-07-21 16:41:28 +02:00
parent eb8f595541
commit 20ab457222
10 changed files with 192 additions and 41 deletions

View File

@@ -22,15 +22,22 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers; namespace FireflyIII\Api\V2\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Transformers\V2\AbstractTransformer; use FireflyIII\Transformers\V2\AbstractTransformer;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Collection;
use League\Fractal\Manager; use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer; use League\Fractal\Serializer\JsonApiSerializer;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
/** /**
* Class Controller * Class Controller
@@ -38,14 +45,16 @@ use League\Fractal\Serializer\JsonApiSerializer;
class Controller extends BaseController class Controller extends BaseController
{ {
protected const CONTENT_TYPE = 'application/vnd.api+json'; protected const CONTENT_TYPE = 'application/vnd.api+json';
protected int $pageSize; protected int $pageSize;
protected ParameterBag $parameters;
/** /**
* *
*/ */
public function __construct() public function __construct()
{ {
$this->pageSize = 50; $this->parameters = $this->getParameters();
$this->pageSize = 50;
if (auth()->check()) { if (auth()->check()) {
$this->pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $this->pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
} }
@@ -66,6 +75,8 @@ class Controller extends BaseController
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v2'; $baseUrl = request()->getSchemeAndHttpHost() . '/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl)); $manager->setSerializer(new JsonApiSerializer($baseUrl));
$transformer->collectMetaData(new Collection([$object]));
$resource = new Item($object, $transformer, $key); $resource = new Item($object, $transformer, $key);
return $manager->createData($resource)->toArray(); return $manager->createData($resource)->toArray();
} }
@@ -82,7 +93,7 @@ class Controller extends BaseController
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v2'; $baseUrl = request()->getSchemeAndHttpHost() . '/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl)); $manager->setSerializer(new JsonApiSerializer($baseUrl));
$objects = $paginator->getCollection(); $objects = $paginator->getCollection();
// the transformer, at this point, needs to collect information that ALL items in the collection // the transformer, at this point, needs to collect information that ALL items in the collection
// require, like meta data and stuff like that, and save it for later. // require, like meta data and stuff like that, and save it for later.
@@ -94,4 +105,59 @@ class Controller extends BaseController
return $manager->createData($resource)->toArray(); return $manager->createData($resource)->toArray();
} }
/**
* TODO duplicate from V1 controller
* Method to grab all parameters from the URL.
*
* @return ParameterBag
*/
private function getParameters(): ParameterBag
{
$bag = new ParameterBag;
try {
$page = (int) request()->get('page');
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
$page = 1;
}
$integers = ['limit'];
$dates = ['start', 'end', 'date'];
if ($page < 1) {
$page = 1;
}
if ($page > (2 ^ 16)) {
$page = (2 ^ 16);
}
$bag->set('page', $page);
// some date fields:
foreach ($dates as $field) {
$date = request()->query->get($field);
$obj = null;
if (null !== $date) {
try {
$obj = Carbon::parse($date);
} catch (InvalidDateException|InvalidFormatException $e) {
// don't care
Log::warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', $date, $e->getMessage()));
}
}
$bag->set($field, $obj);
}
// integer fields:
foreach ($integers as $integer) {
$value = request()->query->get($integer);
if (null !== $value) {
$bag->set($integer, (int) $value);
}
}
// sort fields:
// return $this->getSortParameters($bag);
return $bag;
}
} }

View File

@@ -26,6 +26,7 @@ use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Transformers\V2\AccountTransformer; use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/** /**
* Class ShowController * Class ShowController
@@ -37,9 +38,11 @@ class ShowController extends Controller
* @param Account $account * @param Account $account
* @return JsonResponse * @return JsonResponse
*/ */
public function show(Account $account): JsonResponse public function show(Request $request, Account $account): JsonResponse
{ {
$transformer = new AccountTransformer; $transformer = new AccountTransformer;
$transformer->setParameters($this->parameters);
return response() return response()
->api($this->jsonApiObject('accounts', $account, $transformer)) ->api($this->jsonApiObject('accounts', $account, $transformer))
->header('Content-Type', self::CONTENT_TYPE); ->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -139,7 +139,6 @@ class Amount
/** /**
* @return TransactionCurrency * @return TransactionCurrency
* @throws FireflyException * @throws FireflyException
* @throws JsonException
*/ */
public function getDefaultCurrency(): TransactionCurrency public function getDefaultCurrency(): TransactionCurrency
{ {

View File

@@ -206,7 +206,6 @@ class Steam
* *
* @return string * @return string
* @throws FireflyException * @throws FireflyException
* @throws JsonException
*/ */
public function balance(Account $account, Carbon $date, ?TransactionCurrency $currency = null): string public function balance(Account $account, Carbon $date, ?TransactionCurrency $currency = null): string
{ {
@@ -255,7 +254,6 @@ class Steam
* @param Carbon $date * @param Carbon $date
* *
* @return array * @return array
* @throws JsonException
*/ */
public function balancesByAccounts(Collection $accounts, Carbon $date): array public function balancesByAccounts(Collection $accounts, Carbon $date): array
{ {

View File

@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use JsonException; use JsonException;
use Symfony\Component\HttpFoundation\ParameterBag;
/** /**
* Class AccountTransformer * Class AccountTransformer
@@ -44,6 +45,7 @@ class AccountTransformer extends AbstractTransformer
*/ */
public function __construct() public function __construct()
{ {
$this->parameters = new ParameterBag;
$this->repository = app(AccountRepositoryInterface::class); $this->repository = app(AccountRepositoryInterface::class);
} }
@@ -154,6 +156,7 @@ class AccountTransformer extends AbstractTransformer
} }
/** /**
* TODO duplicated in the V2 transformer.
* @return Carbon * @return Carbon
*/ */
private function getDate(): Carbon private function getDate(): Carbon

View File

@@ -24,16 +24,35 @@ namespace FireflyIII\Transformers\V2;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use League\Fractal\TransformerAbstract; use League\Fractal\TransformerAbstract;
use Symfony\Component\HttpFoundation\ParameterBag;
/** /**
* Class AbstractTransformer * Class AbstractTransformer
*/ */
abstract class AbstractTransformer extends TransformerAbstract abstract class AbstractTransformer extends TransformerAbstract
{ {
protected ParameterBag $parameters;
/** /**
* @param Collection $objects * @param Collection $objects
* @return void * @return void
*/ */
abstract public function collectMetaData(Collection $objects): void; abstract public function collectMetaData(Collection $objects): void;
/**
* @return ParameterBag
*/
final public function getParameters(): ParameterBag
{
return $this->parameters;
}
/**
* @param ParameterBag $parameters
*/
final public function setParameters(ParameterBag $parameters): void
{
$this->parameters = $parameters;
}
} }

View File

@@ -22,7 +22,12 @@ declare(strict_types=1);
namespace FireflyIII\Transformers\V2; namespace FireflyIII\Transformers\V2;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -30,6 +35,11 @@ use Illuminate\Support\Collection;
*/ */
class AccountTransformer extends AbstractTransformer class AccountTransformer extends AbstractTransformer
{ {
private array $currencies;
private array $accountMeta;
private ?TransactionCurrency $currency;
private array $balances;
/** /**
* Transform the account. * Transform the account.
* *
@@ -39,8 +49,15 @@ class AccountTransformer extends AbstractTransformer
*/ */
public function transform(Account $account): array public function transform(Account $account): array
{ {
$fullType = $account->accountType->type; //$fullType = $account->accountType->type;
$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); //$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType));
$id = (int) $account->id;
// no currency? use default
$currency = $this->currency;
if (0 !== (int) $this->accountMeta[$id]['currency_id']) {
$currency = $this->currencies[(int) $this->accountMeta[$id]['currency_id']];
}
return [ return [
'id' => (string) $account->id, 'id' => (string) $account->id,
@@ -49,32 +66,32 @@ class AccountTransformer extends AbstractTransformer
'active' => $account->active, 'active' => $account->active,
//'order' => $order, //'order' => $order,
'name' => $account->name, 'name' => $account->name,
'type' => strtolower($accountType), // 'type' => strtolower($accountType),
// 'account_role' => $accountRole, // 'account_role' => $accountRole,
// 'currency_id' => $currencyId, 'currency_id' => $currency->id,
// 'currency_code' => $currencyCode, 'currency_code' => $currency->code,
// 'currency_symbol' => $currencySymbol, 'currency_symbol' => $currency->symbol,
// 'currency_decimal_places' => $decimalPlaces, 'currency_decimal_places' => $currency->decimal_places,
// 'current_balance' => number_format((float) app('steam')->balance($account, $date), $decimalPlaces, '.', ''), 'current_balance' => $this->balances[$id] ?? null,
// 'current_balance_date' => $date->toAtomString(), 'current_balance_date' => $this->getDate(),
// 'notes' => $this->repository->getNoteText($account), // 'notes' => $this->repository->getNoteText($account),
// 'monthly_payment_date' => $monthlyPaymentDate, // 'monthly_payment_date' => $monthlyPaymentDate,
// 'credit_card_type' => $creditCardType, // 'credit_card_type' => $creditCardType,
// 'account_number' => $this->repository->getMetaValue($account, 'account_number'), // 'account_number' => $this->repository->getMetaValue($account, 'account_number'),
'iban' => '' === $account->iban ? null : $account->iban, 'iban' => '' === $account->iban ? null : $account->iban,
// 'bic' => $this->repository->getMetaValue($account, 'BIC'), // 'bic' => $this->repository->getMetaValue($account, 'BIC'),
// 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''), // 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''),
// 'opening_balance' => $openingBalance, // 'opening_balance' => $openingBalance,
// 'opening_balance_date' => $openingBalanceDate, // 'opening_balance_date' => $openingBalanceDate,
// 'liability_type' => $liabilityType, // 'liability_type' => $liabilityType,
// 'liability_direction' => $liabilityDirection, // 'liability_direction' => $liabilityDirection,
// 'interest' => $interest, // 'interest' => $interest,
// 'interest_period' => $interestPeriod, // 'interest_period' => $interestPeriod,
// 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'), // 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'),
// 'include_net_worth' => $includeNetWorth, // 'include_net_worth' => $includeNetWorth,
// 'longitude' => $longitude, // 'longitude' => $longitude,
// 'latitude' => $latitude, // 'latitude' => $latitude,
// 'zoom_level' => $zoomLevel, // 'zoom_level' => $zoomLevel,
'links' => [ 'links' => [
[ [
'rel' => 'self', 'rel' => 'self',
@@ -84,11 +101,48 @@ class AccountTransformer extends AbstractTransformer
]; ];
} }
/**
* @return Carbon
*/
private function getDate(): Carbon
{
$date = today(config('app.timezone'));
if (null !== $this->parameters->get('date')) {
$date = $this->parameters->get('date');
}
return $date;
}
/** /**
* @inheritDoc * @inheritDoc
* @throws FireflyException
*/ */
public function collectMetaData(Collection $objects): void public function collectMetaData(Collection $objects): void
{ {
// TODO: Implement collectMetaData() method. $this->currency = null;
$this->currencies = [];
$this->accountMeta = [];
$this->balances = app('steam')->balancesByAccounts($objects, $this->getDate());
$repository = app(CurrencyRepositoryInterface::class);
$this->currency = app('amount')->getDefaultCurrency();
// get currencies:
$accountIds = $objects->pluck('id')->toArray();
$meta = AccountMeta
::whereIn('account_id', $accountIds)
->where('name', 'currency_id')
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']);
$currencyIds = $meta->pluck('data')->toArray();
$currencies = $repository->getByIds($currencyIds);
foreach ($currencies as $currency) {
$id = (int) $currency->id;
$this->currencies[$id] = $currency;
}
foreach ($meta as $entry) {
$id = (int) $entry->account_id;
$this->accountMeta[$id][$entry->name] = $entry->data;
}
} }
} }

View File

@@ -11,7 +11,7 @@
}, },
"dependencies": { "dependencies": {
"@popperjs/core": "^2.11.2", "@popperjs/core": "^2.11.2",
"@quasar/extras": "^1.14.2", "@quasar/extras": "^1.14.3",
"apexcharts": "^3.32.1", "apexcharts": "^3.32.1",
"axios": "^0.21.1", "axios": "^0.21.1",
"axios-cache-adapter": "^2.7.3", "axios-cache-adapter": "^2.7.3",

View File

@@ -23,7 +23,11 @@
<q-card bordered> <q-card bordered>
<q-item> <q-item>
<q-item-section> <q-item-section>
<q-item-label><strong>{{ accountName }}</strong> (balance)</q-item-label> <q-item-label><strong>{{ accountName }}</strong>
<span v-if="accountCurrencyCode !== ''">
({{ formatAmount(accountCurrencyCode,accountBalance) }})
</span>
</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-separator/> <q-separator/>
@@ -110,6 +114,8 @@ export default {
store: null, store: null,
accountName: '', accountName: '',
transactions: [], transactions: [],
accountCurrencyCode: '',
accountBalance: 0.0
} }
}, },
mounted() { mounted() {
@@ -135,7 +141,10 @@ export default {
(new Get).get(this.accountId).then((response) => this.parseAccount(response.data)); (new Get).get(this.accountId).then((response) => this.parseAccount(response.data));
}, },
parseAccount: function (data) { parseAccount: function (data) {
console.log(data.data.attributes);
this.accountName = data.data.attributes.name; this.accountName = data.data.attributes.name;
this.accountBalance = data.data.attributes.current_balance;
this.accountCurrencyCode = data.data.attributes.currency_code;
}, },
getTransactions: function () { getTransactions: function () {
if (null !== this.store.getRange.start && null !== this.store.getRange.end) { if (null !== this.store.getRange.start && null !== this.store.getRange.end) {

View File

@@ -1252,10 +1252,10 @@
core-js "^3.6.5" core-js "^3.6.5"
core-js-compat "^3.6.5" core-js-compat "^3.6.5"
"@quasar/extras@^1.14.2": "@quasar/extras@^1.14.3":
version "1.14.2" version "1.14.3"
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.14.2.tgz#a5382ec83ddf967f8bc17d0dbe6ef88ddb31b796" resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.14.3.tgz#2a4d7a2f773a789ca43e3a02d5b797c9d2888884"
integrity sha512-F9T1aIhRIiuJeuxPCu2CBlPj5js6mBZWQOAHHyVlreNa5qhVEHhr/9GfljG6RTnjvTNOjJraTl0hi8g0IuUfLw== integrity sha512-OHyR/pfW0R8E5DvnsV1wg9ISnLL/yXHyOMZsqPY3gUtmfdF2634x2osdVg4YpBYW29vIQeV5feGWGIx8nuprdA==
"@quasar/fastclick@1.1.5": "@quasar/fastclick@1.1.5":
version "1.1.5" version "1.1.5"