mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-12 09:52:20 +00:00
Fix most of the index with json laravel api endpoints.
This commit is contained in:
@@ -63,7 +63,7 @@ class AccountSchema extends Schema
|
|||||||
Attribute::make('current_debt')->sortable(),
|
Attribute::make('current_debt')->sortable(),
|
||||||
|
|
||||||
// dynamic data
|
// dynamic data
|
||||||
Attribute::make('last_activity'),
|
Attribute::make('last_activity')->sortable(),
|
||||||
Attribute::make('balance_difference')->sortable(), // only used for sort.
|
Attribute::make('balance_difference')->sortable(), // only used for sort.
|
||||||
|
|
||||||
// group
|
// group
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
|||||||
use FireflyIII\Support\JsonApi\ExpandsQuery;
|
use FireflyIII\Support\JsonApi\ExpandsQuery;
|
||||||
use FireflyIII\Support\JsonApi\FiltersPagination;
|
use FireflyIII\Support\JsonApi\FiltersPagination;
|
||||||
use FireflyIII\Support\JsonApi\SortsCollection;
|
use FireflyIII\Support\JsonApi\SortsCollection;
|
||||||
|
use FireflyIII\Support\JsonApi\SortsQueryResults;
|
||||||
use FireflyIII\Support\JsonApi\ValidateSortParameters;
|
use FireflyIII\Support\JsonApi\ValidateSortParameters;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use LaravelJsonApi\Contracts\Pagination\Page;
|
use LaravelJsonApi\Contracts\Pagination\Page;
|
||||||
use LaravelJsonApi\Contracts\Store\HasPagination;
|
use LaravelJsonApi\Contracts\Store\HasPagination;
|
||||||
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
|
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
|
||||||
use LaravelJsonApi\NonEloquent\Concerns\PaginatesEnumerables;
|
|
||||||
|
|
||||||
class AccountQuery extends QueryAll implements HasPagination
|
class AccountQuery extends QueryAll implements HasPagination
|
||||||
{
|
{
|
||||||
@@ -48,6 +48,8 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
use ValidateSortParameters;
|
use ValidateSortParameters;
|
||||||
use CollectsCustomParameters;
|
use CollectsCustomParameters;
|
||||||
use AccountFilter;
|
use AccountFilter;
|
||||||
|
use SortsQueryResults;
|
||||||
|
|
||||||
//use PaginatesEnumerables;
|
//use PaginatesEnumerables;
|
||||||
|
|
||||||
#[\Override]
|
#[\Override]
|
||||||
@@ -59,17 +61,15 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
public function get(): iterable
|
public function get(): iterable
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
// collect filters
|
|
||||||
$filters = $this->queryParameters->filter();
|
|
||||||
|
|
||||||
// collect sort options
|
// collect sort options
|
||||||
$sort = $this->queryParameters->sortFields();
|
$sort = $this->queryParameters->sortFields();
|
||||||
|
|
||||||
// collect pagination based on the page
|
// collect pagination based on the page
|
||||||
$pagination = $this->filtersPagination($this->queryParameters->page());
|
$pagination = $this->filtersPagination($this->queryParameters->page());
|
||||||
|
|
||||||
// check if we need all accounts, regardless of pagination
|
// check if we need all accounts, regardless of pagination
|
||||||
// This is necessary when the user wants to sort on specific params.
|
// This is necessary when the user wants to sort on specific params.
|
||||||
$needsAll = $this->needsFullDataset('account', $sort);
|
$needsAll = $this->needsFullDataset(Account::class, $sort);
|
||||||
|
|
||||||
// params that were not recognised, may be my own custom stuff.
|
// params that were not recognised, may be my own custom stuff.
|
||||||
$otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters());
|
$otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters());
|
||||||
@@ -77,34 +77,56 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
// start the query
|
// start the query
|
||||||
$query = $this->userGroup->accounts();
|
$query = $this->userGroup->accounts();
|
||||||
|
|
||||||
// if (!$needsAll) {
|
|
||||||
// Log::debug('Does not need full dataset, will paginate.');
|
|
||||||
// $query = $this->addPagination($query, $pagination);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// add sort and filter parameters to the query.
|
// add sort and filter parameters to the query.
|
||||||
$query = $this->addSortParams(Account::class, $query, $sort);
|
$query = $this->addSortParams(Account::class, $query, $sort);
|
||||||
$query = $this->addFilterParams(Account::class, $query, $filters);
|
$query = $this->addFilterParams(Account::class, $query, $this->queryParameters->filter());
|
||||||
|
|
||||||
|
|
||||||
// collect the result.
|
// collect the result.
|
||||||
$collection = $query->get(['accounts.*']);
|
$collection = $query->get(['accounts.*']);
|
||||||
// sort the data after the query, and return it right away.
|
// sort the data after the query, and return it right away.
|
||||||
$sorted = $this->sortCollection(Account::class, $collection, $sort);
|
$collection = $this->sortCollection(Account::class, $collection, $sort);
|
||||||
|
|
||||||
|
// if the entire collection needs to be enriched and sorted, do so now:
|
||||||
|
$totalCount = $collection->count();
|
||||||
|
Log::debug(sprintf('Total is %d', $totalCount));
|
||||||
|
if ($needsAll) {
|
||||||
|
Log::debug('Needs the entire collection');
|
||||||
|
// enrich the entire collection
|
||||||
|
$enrichment = new AccountEnrichment();
|
||||||
|
$enrichment->setStart($otherParams['start'] ?? null);
|
||||||
|
$enrichment->setEnd($otherParams['end'] ?? null);
|
||||||
|
$collection = $enrichment->enrich($collection);
|
||||||
|
|
||||||
|
// TODO sort the set based on post-query sort options:
|
||||||
|
$collection = $this->postQuerySort(Account::class, $collection, $sort);
|
||||||
|
|
||||||
|
// take the current page from the enriched set.
|
||||||
|
$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!$needsAll) {
|
||||||
|
Log::debug('Needs only partial collection');
|
||||||
// take from the collection the filtered page + page number:
|
// take from the collection the filtered page + page number:
|
||||||
$currentPage = $sorted->skip($pagination['number'] - 1 * $pagination['size'])->take($pagination['size']);
|
$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
|
||||||
|
|
||||||
// enrich the current page.
|
// enrich only the current page.
|
||||||
$enrichment = new AccountEnrichment();
|
$enrichment = new AccountEnrichment();
|
||||||
$enrichment->setStart($otherParams['start'] ?? null);
|
$enrichment->setStart($otherParams['start'] ?? null);
|
||||||
$enrichment->setEnd($otherParams['end'] ?? null);
|
$enrichment->setEnd($otherParams['end'] ?? null);
|
||||||
$currentPage = $enrichment->enrich($currentPage);
|
$currentPage = $enrichment->enrich($currentPage);
|
||||||
|
}
|
||||||
|
// get current page?
|
||||||
|
Log::debug(sprintf('Skip %d, take %d', ($pagination['number'] - 1) * $pagination['size'], $pagination['size']));
|
||||||
|
//$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
|
||||||
|
Log::debug(sprintf('New collection size: %d', $currentPage->count()));
|
||||||
|
|
||||||
|
|
||||||
// TODO add filters after the query, if there are filters that cannot be applied to the database
|
// TODO add filters after the query, if there are filters that cannot be applied to the database
|
||||||
// TODO same for sort things.
|
// TODO same for sort things.
|
||||||
|
|
||||||
|
return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']);
|
||||||
return new LengthAwarePaginator($currentPage,$sorted->count(),$pagination['size'],$pagination['number']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,12 +37,14 @@ class IsValidAccountType implements ValidationRule
|
|||||||
#[\Override] public function validate(string $attribute, mixed $value, Closure $fail): void
|
#[\Override] public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!is_array($value)) {
|
|
||||||
$value = [$value];
|
|
||||||
}
|
|
||||||
// only check the type.
|
// only check the type.
|
||||||
if (array_key_exists('type', $value)) {
|
if (array_key_exists('type', $value)) {
|
||||||
$value = $value['type'];
|
$value = $value['type'];
|
||||||
|
if (!is_array($value)) {
|
||||||
|
$value = [$value];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$filtered = [];
|
$filtered = [];
|
||||||
$keys = array_keys($this->types);
|
$keys = array_keys($this->types);
|
||||||
/** @var mixed $entry */
|
/** @var mixed $entry */
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ trait CollectsCustomParameters
|
|||||||
if (array_key_exists('endPeriod', $params)) {
|
if (array_key_exists('endPeriod', $params)) {
|
||||||
$return['end'] = Carbon::parse($params['endPeriod']);
|
$return['end'] = Carbon::parse($params['endPeriod']);
|
||||||
}
|
}
|
||||||
|
if(array_key_exists('currentMoment', $params)) {
|
||||||
|
$return['today'] = Carbon::parse($params['currentMoment']);
|
||||||
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|||||||
133
app/Support/JsonApi/SortsQueryResults.php
Normal file
133
app/Support/JsonApi/SortsQueryResults.php
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SortsQueryResults.php
|
||||||
|
* Copyright (c) 2024 james@firefly-iii.org.
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\JsonApi;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use LaravelJsonApi\Core\Query\SortField;
|
||||||
|
use LaravelJsonApi\Core\Query\SortFields;
|
||||||
|
|
||||||
|
trait SortsQueryResults
|
||||||
|
{
|
||||||
|
|
||||||
|
final protected function postQuerySort(string $class, Collection $collection, SortFields $parameters): Collection
|
||||||
|
{
|
||||||
|
Log::debug(__METHOD__);
|
||||||
|
foreach ($parameters->all() as $field) {
|
||||||
|
$collection = $this->sortQueryCollection($class, $collection, $field);
|
||||||
|
}
|
||||||
|
return $collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO improve this.
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
* @param Collection $collection
|
||||||
|
* @param SortField $field
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
private function sortQueryCollection(string $class, Collection $collection, SortField $field): Collection
|
||||||
|
{
|
||||||
|
// here be custom sort things.
|
||||||
|
// sort by balance
|
||||||
|
if (Account::class === $class && 'balance' === $field->name()) {
|
||||||
|
$ascending = $field->isAscending();
|
||||||
|
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
|
||||||
|
$leftSum = $this->sumBalance($left->balance);
|
||||||
|
$rightSum = $this->sumBalance($right->balance);
|
||||||
|
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Account::class === $class && 'balance_difference' === $field->name()) {
|
||||||
|
$ascending = $field->isAscending();
|
||||||
|
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
|
||||||
|
$leftSum = $this->sumBalanceDifference($left->balance);
|
||||||
|
$rightSum = $this->sumBalanceDifference($right->balance);
|
||||||
|
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// sort by account number
|
||||||
|
if (Account::class === $class && 'account_number' === $field->name()) {
|
||||||
|
$ascending = $field->isAscending();
|
||||||
|
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
|
||||||
|
$leftNr = sprintf('%s%s', $left->iban, $left->account_number);
|
||||||
|
$rightNr = sprintf('%s%s', $right->iban, $right->account_number);
|
||||||
|
return $ascending ? strcmp($leftNr, $rightNr) : strcmp($rightNr, $leftNr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort by last activity
|
||||||
|
if (Account::class === $class && 'last_activity' === $field->name()) {
|
||||||
|
$ascending = $field->isAscending();
|
||||||
|
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
|
||||||
|
$leftNr = (int)$left->last_activity?->format('U');
|
||||||
|
$rightNr = (int)$right->last_activity?->format('U');
|
||||||
|
if($ascending){
|
||||||
|
return $leftNr <=> $rightNr;
|
||||||
|
}
|
||||||
|
return $rightNr <=> $leftNr;
|
||||||
|
//return (int) ($ascending ? $rightNr < $leftNr : $leftNr < $rightNr );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort by balance difference.
|
||||||
|
|
||||||
|
|
||||||
|
return $collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sumBalance(?array $balance): string
|
||||||
|
{
|
||||||
|
if (null === $balance) {
|
||||||
|
return '-10000000000'; // minus one billion
|
||||||
|
}
|
||||||
|
if (0 === count($balance)) {
|
||||||
|
return '-10000000000'; // minus one billion
|
||||||
|
}
|
||||||
|
$sum = '0';
|
||||||
|
foreach ($balance as $entry) {
|
||||||
|
$sum = bcadd($sum, $entry['balance']);
|
||||||
|
}
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sumBalanceDifference(?array $balance): string
|
||||||
|
{
|
||||||
|
if (null === $balance) {
|
||||||
|
return '-10000000000'; // minus one billion
|
||||||
|
}
|
||||||
|
if (0 === count($balance)) {
|
||||||
|
return '-10000000000'; // minus one billion
|
||||||
|
}
|
||||||
|
$sum = '0';
|
||||||
|
foreach ($balance as $entry) {
|
||||||
|
$sum = bcadd($sum, $entry['balance_difference']);
|
||||||
|
}
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -34,9 +34,7 @@ trait ValidateSortParameters
|
|||||||
if (null === $params) {
|
if (null === $params) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$config = config('api.full_data_set')[$class] ?? [];
|
||||||
$config = config(sprintf('api.full_data_set.%s', $class)) ?? [];
|
|
||||||
|
|
||||||
foreach ($params->all() as $field) {
|
foreach ($params->all() as $field) {
|
||||||
if (in_array($field->name(), $config, true)) {
|
if (in_array($field->name(), $config, true)) {
|
||||||
Log::debug('TRUE');
|
Log::debug('TRUE');
|
||||||
|
|||||||
@@ -46,15 +46,16 @@ return [
|
|||||||
'accounts' => ['name', 'active', 'iban', 'order', 'account_number', 'balance', 'last_activity', 'balance_difference', 'current_debt'],
|
'accounts' => ['name', 'active', 'iban', 'order', 'account_number', 'balance', 'last_activity', 'balance_difference', 'current_debt'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
// valid query columns for sorting:
|
// valid query columns for sorting the query
|
||||||
'valid_query_sort' => [
|
'valid_query_sort' => [
|
||||||
Account::class => ['id','name', 'active', 'iban', 'order'],
|
Account::class => ['id', 'name', 'active', 'iban', 'order'],
|
||||||
],
|
],
|
||||||
|
// valid query columns for sorting the query results
|
||||||
'valid_api_sort' => [
|
'valid_api_sort' => [
|
||||||
Account::class => [],
|
Account::class => ['account_number'],
|
||||||
],
|
],
|
||||||
'full_data_set' => [
|
'full_data_set' => [
|
||||||
'account' => ['last_activity', 'balance_difference', 'current_balance', 'current_debt'],
|
Account::class => ['last_activity', 'balance', 'balance_difference', 'current_debt', 'account_number'],
|
||||||
],
|
],
|
||||||
'valid_query_filters' => [
|
'valid_query_filters' => [
|
||||||
Account::class => ['id', 'name', 'iban', 'active'],
|
Account::class => ['id', 'name', 'iban', 'active'],
|
||||||
|
|||||||
@@ -48,7 +48,12 @@ const params = new Proxy(new URLSearchParams(window.location.search), {
|
|||||||
get: (searchParams, prop) => searchParams.get(prop),
|
get: (searchParams, prop) => searchParams.get(prop),
|
||||||
});
|
});
|
||||||
sortingColumn = params.column ?? '';
|
sortingColumn = params.column ?? '';
|
||||||
sortDirection = params.direction ?? '';
|
sortDirection = 'asc';
|
||||||
|
if(sortingColumn[0] === '-') {
|
||||||
|
sortingColumn = sortingColumn.substring(1);
|
||||||
|
sortDirection = 'desc';
|
||||||
|
}
|
||||||
|
|
||||||
page = parseInt(params.page ?? 1);
|
page = parseInt(params.page ?? 1);
|
||||||
|
|
||||||
|
|
||||||
@@ -77,6 +82,7 @@ let index = function () {
|
|||||||
filters: {
|
filters: {
|
||||||
active: null,
|
active: null,
|
||||||
name: null,
|
name: null,
|
||||||
|
type: type,
|
||||||
},
|
},
|
||||||
pageOptions: {
|
pageOptions: {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
@@ -345,10 +351,11 @@ let index = function () {
|
|||||||
//const sorting = [{column: this.pageOptions.sortingColumn, direction: this.pageOptions.sortDirection}];
|
//const sorting = [{column: this.pageOptions.sortingColumn, direction: this.pageOptions.sortDirection}];
|
||||||
|
|
||||||
// filter instructions
|
// filter instructions
|
||||||
let filters = [];
|
let filters = {};
|
||||||
for (let k in this.filters) {
|
for (let k in this.filters) {
|
||||||
if (this.filters.hasOwnProperty(k) && null !== this.filters[k]) {
|
if (this.filters.hasOwnProperty(k) && null !== this.filters[k]) {
|
||||||
filters.push({column: k, filter: this.filters[k]});
|
filters[k] = this.filters[k];
|
||||||
|
//filters.push({column: k, filter: this.filters[k]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,9 +365,9 @@ let index = function () {
|
|||||||
const today = new Date();
|
const today = new Date();
|
||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
sorting: sorting,
|
sort: sorting,
|
||||||
filters: filters,
|
filter: filters,
|
||||||
// today: today,
|
currentMoment: today,
|
||||||
// type: type,
|
// type: type,
|
||||||
page: {number: this.page},
|
page: {number: this.page},
|
||||||
startPeriod: start,
|
startPeriod: start,
|
||||||
@@ -368,8 +375,8 @@ let index = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!this.tableColumns.balance_difference.enabled) {
|
if (!this.tableColumns.balance_difference.enabled) {
|
||||||
delete params.start;
|
delete params.startPeriod;
|
||||||
delete params.end;
|
delete params.enPeriod;
|
||||||
}
|
}
|
||||||
this.accounts = [];
|
this.accounts = [];
|
||||||
let groupedAccounts = {};
|
let groupedAccounts = {};
|
||||||
@@ -404,7 +411,6 @@ let index = function () {
|
|||||||
balance: current.attributes.balance,
|
balance: current.attributes.balance,
|
||||||
native_balance: current.attributes.native_balance,
|
native_balance: current.attributes.native_balance,
|
||||||
};
|
};
|
||||||
|
|
||||||
// get group info:
|
// get group info:
|
||||||
let groupId = current.attributes.object_group_id;
|
let groupId = current.attributes.object_group_id;
|
||||||
if(!this.pageOptions.groupedAccounts) {
|
if(!this.pageOptions.groupedAccounts) {
|
||||||
|
|||||||
@@ -125,12 +125,12 @@
|
|||||||
{{ __('list.interest') }}
|
{{ __('list.interest') }}
|
||||||
</th>
|
</th>
|
||||||
<th x-show="tableColumns.number.visible && tableColumns.number.enabled">
|
<th x-show="tableColumns.number.visible && tableColumns.number.enabled">
|
||||||
<a href="#" x-on:click.prevent="sort('iban')">
|
<a href="#" x-on:click.prevent="sort('account_number')">
|
||||||
{{ __('list.account_number') }}
|
{{ __('list.account_number') }}
|
||||||
</a>
|
</a>
|
||||||
<em x-show="pageOptions.sortingColumn === 'iban' && pageOptions.sortDirection === 'asc'"
|
<em x-show="pageOptions.sortingColumn === 'account_number' && pageOptions.sortDirection === 'asc'"
|
||||||
class="fa-solid fa-arrow-down-a-z"></em>
|
class="fa-solid fa-arrow-down-a-z"></em>
|
||||||
<em x-show="pageOptions.sortingColumn === 'iban' && pageOptions.sortDirection === 'desc'"
|
<em x-show="pageOptions.sortingColumn === 'account_number' && pageOptions.sortDirection === 'desc'"
|
||||||
class="fa-solid fa-arrow-down-z-a"></em>
|
class="fa-solid fa-arrow-down-z-a"></em>
|
||||||
</th>
|
</th>
|
||||||
<th x-show="tableColumns.current_balance.visible && tableColumns.current_balance.enabled">
|
<th x-show="tableColumns.current_balance.visible && tableColumns.current_balance.enabled">
|
||||||
@@ -262,13 +262,17 @@
|
|||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td x-show="tableColumns.current_balance.visible && tableColumns.current_balance.enabled">
|
<td x-show="tableColumns.current_balance.visible && tableColumns.current_balance.enabled">
|
||||||
|
<template x-if="null !== account.balance">
|
||||||
<template x-for="balance in account.balance">
|
<template x-for="balance in account.balance">
|
||||||
<span x-show="balance.balance < 0" class="text-danger"
|
<span>
|
||||||
|
<span x-show="parseFloat(balance.balance) < 0.0" class="text-danger"
|
||||||
x-text="formatMoney(balance.balance, balance.currency_code)"></span>
|
x-text="formatMoney(balance.balance, balance.currency_code)"></span>
|
||||||
<span x-show="balance.balance == 0" class="text-muted"
|
<span x-show="parseFloat(balance.balance) === 0.0" class="text-muted"
|
||||||
x-text="formatMoney(balance.balance, balance.currency_code)"></span>
|
x-text="formatMoney(balance.balance, balance.currency_code)"></span>
|
||||||
<span x-show="balance.balance > 0" class="text-success"
|
<span x-show="parseFloat(balance.balance) > 0.0" class="text-success"
|
||||||
x-text="formatMoney(balance.balance, balance.currency_code)"></span>
|
x-text="formatMoney(balance.balance, balance.currency_code)"></span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td x-show="tableColumns.amount_due.visible && tableColumns.amount_due.enabled">
|
<td x-show="tableColumns.amount_due.visible && tableColumns.amount_due.enabled">
|
||||||
@@ -284,14 +288,17 @@
|
|||||||
<span x-text="account.last_activity"></span>
|
<span x-text="account.last_activity"></span>
|
||||||
</td>
|
</td>
|
||||||
<td x-show="tableColumns.balance_difference.visible && tableColumns.balance_difference.enabled">
|
<td x-show="tableColumns.balance_difference.visible && tableColumns.balance_difference.enabled">
|
||||||
|
<template x-if="null !== account.balance">
|
||||||
<template x-for="balance in account.balance">
|
<template x-for="balance in account.balance">
|
||||||
|
<span>
|
||||||
<span x-show="null != balance.balance_difference && balance.balance_difference < 0" class="text-danger"
|
<span x-show="null != balance.balance_difference && balance.balance_difference < 0" class="text-danger"
|
||||||
x-text="formatMoney(balance.balance_difference, balance.currency_code)"></span>
|
x-text="formatMoney(balance.balance_difference, balance.currency_code)"></span>
|
||||||
<span x-show="null != balance.balance_difference && balance.balance_difference == 0" class="text-muted"
|
<span x-show="null != balance.balance_difference && balance.balance_difference == 0" class="text-muted"
|
||||||
x-text="formatMoney(balance.balance_difference, balance.currency_code)"></span>
|
x-text="formatMoney(balance.balance_difference, balance.currency_code)"></span>
|
||||||
<span x-show="null != balance.balance_difference && balance.balance_difference > 0" class="text-success"
|
<span x-show="null != balance.balance_difference && balance.balance_difference > 0" class="text-success"
|
||||||
x-text="formatMoney(balance.balance_difference, balance.currency_code)"></span>
|
x-text="formatMoney(balance.balance_difference, balance.currency_code)"></span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td x-show="tableColumns.menu.visible && tableColumns.menu.enabled">
|
<td x-show="tableColumns.menu.visible && tableColumns.menu.enabled">
|
||||||
|
|||||||
Reference in New Issue
Block a user