mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Fix auto complete
This commit is contained in:
parent
73fdbb6202
commit
45e9d4f8de
@ -101,11 +101,16 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
private function parseAccount(Account $account): array
|
private function parseAccount(Account $account): array
|
||||||
{
|
{
|
||||||
|
$currency = $this->adminRepository->getAccountCurrency($account);
|
||||||
return [
|
return [
|
||||||
'id' => (string) $account->id,
|
'id' => (string) $account->id,
|
||||||
'title' => $account->name,
|
'title' => $account->name,
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'type' => $account->accountType->type,
|
'type' => $account->accountType->type,
|
||||||
|
'currency_id' => null === $currency ? null : (string) $currency->id,
|
||||||
|
'currency_code' => $currency?->code,
|
||||||
|
'currency_symbol' => $currency?->symbol,
|
||||||
|
'currency_decimal' => $currency?->decimal_places,
|
||||||
'account_balances' => $this->getAccountBalances($account),
|
'account_balances' => $this->getAccountBalances($account),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V2\Request\Autocomplete;
|
namespace FireflyIII\Api\V2\Request\Autocomplete;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Carbon\Exceptions\InvalidFormatException;
|
||||||
use FireflyIII\JsonApi\Rules\IsValidFilter;
|
use FireflyIII\JsonApi\Rules\IsValidFilter;
|
||||||
use FireflyIII\JsonApi\Rules\IsValidPage;
|
use FireflyIII\JsonApi\Rules\IsValidPage;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
@ -33,7 +34,7 @@ use FireflyIII\Support\Request\ConvertsDataTypes;
|
|||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use LaravelJsonApi\Core\Query\QueryParameters;
|
use LaravelJsonApi\Core\Query\QueryParameters;
|
||||||
use LaravelJsonApi\Validation\Rule as JsonApiRule;
|
use LaravelJsonApi\Validation\Rule as JsonApiRule;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
/**
|
/**
|
||||||
* Class AutocompleteRequest
|
* Class AutocompleteRequest
|
||||||
*/
|
*/
|
||||||
@ -54,10 +55,15 @@ class AutocompleteRequest extends FormRequest
|
|||||||
public function getParameters(): array
|
public function getParameters(): array
|
||||||
{
|
{
|
||||||
$queryParameters = QueryParameters::cast($this->all());
|
$queryParameters = QueryParameters::cast($this->all());
|
||||||
$date = Carbon::createFromFormat('Y-m-d', $queryParameters->filter()->value('date', date('Y-m-d')), config('app.timezone'));
|
try {
|
||||||
$query = $queryParameters->filter()->value('query', '');
|
$date = Carbon::createFromFormat('Y-m-d', $queryParameters->filter()?->value('date', date('Y-m-d')), config('app.timezone'));
|
||||||
|
} catch(InvalidFormatException $e) {
|
||||||
|
Log::debug(sprintf('Invalid date format in autocomplete request. Using today: %s', $e->getMessage()));
|
||||||
|
$date = today();
|
||||||
|
}
|
||||||
|
$query = $queryParameters->filter()?->value('query', '') ?? '';
|
||||||
$size = (int) ($queryParameters->page()['size'] ?? 50);
|
$size = (int) ($queryParameters->page()['size'] ?? 50);
|
||||||
$accountTypes = $this->getAccountTypeParameter($queryParameters->filter()->value('account_types', ''));
|
$accountTypes = $this->getAccountTypeParameter($queryParameters->filter()?->value('account_types', '') ?? '');
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -37,9 +37,13 @@ class AccountBalanceCalculator
|
|||||||
// first collect normal amounts (in whatever currency), and set them.
|
// first collect normal amounts (in whatever currency), and set them.
|
||||||
|
|
||||||
// select account_id, transaction_currency_id, foreign_currency_id, sum(amount), sum(foreign_amount) from transactions group by account_id, transaction_currency_id, foreign_currency_id
|
// select account_id, transaction_currency_id, foreign_currency_id, sum(amount), sum(foreign_amount) from transactions group by account_id, transaction_currency_id, foreign_currency_id
|
||||||
$result = Transaction
|
$query = Transaction::groupBy(['account_id', 'transaction_currency_id', 'foreign_currency_id']);
|
||||||
::groupBy(['account_id', 'transaction_currency_id', 'foreign_currency_id'])
|
|
||||||
->get(['account_id', 'transaction_currency_id', 'foreign_currency_id', DB::raw('SUM(amount) as sum_amount'), DB::raw('SUM(foreign_amount) as sum_foreign_amount')]);
|
if (null !== $account) {
|
||||||
|
$query->where('account_id', $account->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $query->get(['account_id', 'transaction_currency_id', 'foreign_currency_id', DB::raw('SUM(amount) as sum_amount'), DB::raw('SUM(foreign_amount) as sum_foreign_amount')]);
|
||||||
|
|
||||||
// reset account balances:
|
// reset account balances:
|
||||||
self::resetAccountBalances($account);
|
self::resetAccountBalances($account);
|
||||||
@ -60,7 +64,7 @@ class AccountBalanceCalculator
|
|||||||
|
|
||||||
// then do foreign amount, if present:
|
// then do foreign amount, if present:
|
||||||
if ($foreignCurrency > 0) {
|
if ($foreignCurrency > 0) {
|
||||||
$entry = self::getBalance('balance', $account, $foreignCurrency);
|
$entry = self::getBalance('balance', $account, $foreignCurrency);
|
||||||
$entry->balance = bcadd($entry->balance, $sumForeignAmount);
|
$entry->balance = bcadd($entry->balance, $sumForeignAmount);
|
||||||
$entry->save();
|
$entry->save();
|
||||||
Log::debug(sprintf('Set balance entry #%d to amount %s', $entry->id, $entry->balance));
|
Log::debug(sprintf('Set balance entry #%d to amount %s', $entry->id, $entry->balance));
|
||||||
@ -68,6 +72,7 @@ class AccountBalanceCalculator
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getBalance(string $title, int $account, int $currency): AccountBalance
|
private static function getBalance(string $title, int $account, int $currency): AccountBalance
|
||||||
{
|
{
|
||||||
$entry = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_currency_id', $currency)->first();
|
$entry = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_currency_id', $currency)->first();
|
||||||
|
@ -17,9 +17,15 @@ return new class extends Migration {
|
|||||||
$table->string('title', 100)->nullable();
|
$table->string('title', 100)->nullable();
|
||||||
$table->integer('account_id', false, true);
|
$table->integer('account_id', false, true);
|
||||||
$table->integer('transaction_currency_id', false, true);
|
$table->integer('transaction_currency_id', false, true);
|
||||||
|
$table->date('date')->nullable();
|
||||||
|
$table->integer('transaction_journal_id', false, true)->nullable();
|
||||||
$table->decimal('balance', 32, 12);
|
$table->decimal('balance', 32, 12);
|
||||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||||
|
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||||
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
|
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$table->unique(['account_id', 'transaction_currency_id', 'title'], 'unique_account_currency');
|
$table->unique(['account_id', 'transaction_currency_id', 'title'], 'unique_account_currency');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -486,13 +486,15 @@ let transactions = function () {
|
|||||||
// addedSplit, is called from the HTML
|
// addedSplit, is called from the HTML
|
||||||
// for source account
|
// for source account
|
||||||
const renderAccount = function (item, b, c) {
|
const renderAccount = function (item, b, c) {
|
||||||
return item.name_with_balance + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.type) + '</small>';
|
return item.title + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.meta.type) + '</small>';
|
||||||
};
|
};
|
||||||
addAutocomplete({
|
addAutocomplete({
|
||||||
selector: 'input.ac-source',
|
selector: 'input.ac-source',
|
||||||
serverUrl: urls.account,
|
serverUrl: urls.account,
|
||||||
// filters: this.filters.source,
|
// filters: this.filters.source,
|
||||||
// onRenderItem: renderAccount,
|
onRenderItem: renderAccount,
|
||||||
|
valueField: 'id',
|
||||||
|
labelField: 'title',
|
||||||
onChange: changeSourceAccount,
|
onChange: changeSourceAccount,
|
||||||
onSelectItem: selectSourceAccount,
|
onSelectItem: selectSourceAccount,
|
||||||
hiddenValue: this.entries[count].source_account.alpine_name
|
hiddenValue: this.entries[count].source_account.alpine_name
|
||||||
@ -500,7 +502,9 @@ let transactions = function () {
|
|||||||
addAutocomplete({
|
addAutocomplete({
|
||||||
selector: 'input.ac-dest',
|
selector: 'input.ac-dest',
|
||||||
serverUrl: urls.account,
|
serverUrl: urls.account,
|
||||||
filters: this.filters.destination,
|
account_types: this.filters.destination,
|
||||||
|
valueField: 'id',
|
||||||
|
labelField: 'title',
|
||||||
onRenderItem: renderAccount,
|
onRenderItem: renderAccount,
|
||||||
onChange: changeDestinationAccount,
|
onChange: changeDestinationAccount,
|
||||||
onSelectItem: selectDestinationAccount
|
onSelectItem: selectDestinationAccount
|
||||||
|
@ -200,20 +200,23 @@ let transactions = function () {
|
|||||||
// addedSplit, is called from the HTML
|
// addedSplit, is called from the HTML
|
||||||
// for source account
|
// for source account
|
||||||
const renderAccount = function (item, b, c) {
|
const renderAccount = function (item, b, c) {
|
||||||
return item.name_with_balance + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.type) + '</small>';
|
console.log(item);
|
||||||
|
return item.title + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.meta.type) + '</small>';
|
||||||
};
|
};
|
||||||
addAutocomplete({
|
addAutocomplete({
|
||||||
selector: 'input.ac-source',
|
selector: 'input.ac-source',
|
||||||
serverUrl: urls.account,
|
serverUrl: urls.account,
|
||||||
filters: this.filters.source,
|
account_types: this.filters.source,
|
||||||
onRenderItem: renderAccount,
|
onRenderItem: renderAccount,
|
||||||
|
valueField: 'id',
|
||||||
|
labelField: 'title',
|
||||||
onChange: changeSourceAccount,
|
onChange: changeSourceAccount,
|
||||||
onSelectItem: selectSourceAccount
|
onSelectItem: selectSourceAccount
|
||||||
});
|
});
|
||||||
addAutocomplete({
|
addAutocomplete({
|
||||||
selector: 'input.ac-dest',
|
selector: 'input.ac-dest',
|
||||||
serverUrl: urls.account,
|
serverUrl: urls.account,
|
||||||
filters: this.filters.destination,
|
account_types: this.filters.destination,
|
||||||
onRenderItem: renderAccount,
|
onRenderItem: renderAccount,
|
||||||
onChange: changeDestinationAccount,
|
onChange: changeDestinationAccount,
|
||||||
onSelectItem: selectDestinationAccount
|
onSelectItem: selectDestinationAccount
|
||||||
@ -222,7 +225,7 @@ let transactions = function () {
|
|||||||
selector: 'input.ac-category',
|
selector: 'input.ac-category',
|
||||||
serverUrl: urls.category,
|
serverUrl: urls.category,
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
labelField: 'name',
|
labelField: 'title',
|
||||||
onChange: changeCategory,
|
onChange: changeCategory,
|
||||||
onSelectItem: changeCategory
|
onSelectItem: changeCategory
|
||||||
});
|
});
|
||||||
|
@ -38,13 +38,14 @@ export function addAutocomplete(options) {
|
|||||||
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content
|
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
queryParam: 'filter[query]',
|
||||||
hiddenInput: true,
|
hiddenInput: true,
|
||||||
// preventBrowserAutocomplete: true,
|
// preventBrowserAutocomplete: true,
|
||||||
highlightTyped: true,
|
highlightTyped: true,
|
||||||
liveServer: true,
|
liveServer: true,
|
||||||
};
|
};
|
||||||
if (typeof options.filters !== 'undefined' && options.filters.length > 0) {
|
if (typeof options.account_types !== 'undefined' && options.account_types.length > 0) {
|
||||||
params.serverParams.types = options.filters;
|
params.serverParams['filter[account_types]'] = options.account_types;
|
||||||
}
|
}
|
||||||
if (typeof options.onRenderItem !== 'undefined' && null !== options.onRenderItem) {
|
if (typeof options.onRenderItem !== 'undefined' && null !== options.onRenderItem) {
|
||||||
params.onRenderItem = options.onRenderItem;
|
params.onRenderItem = options.onRenderItem;
|
||||||
|
@ -55,13 +55,12 @@ export function changeDestinationAccount(item, ac) {
|
|||||||
export function selectDestinationAccount(item, ac) {
|
export function selectDestinationAccount(item, ac) {
|
||||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account = {
|
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account = {
|
||||||
id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code,
|
id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code,
|
||||||
};
|
};
|
||||||
document.querySelector('#form')._x_dataStack[0].changedDestinationAccount();
|
document.querySelector('#form')._x_dataStack[0].changedDestinationAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeSourceAccount(item, ac) {
|
export function changeSourceAccount(item, ac) {
|
||||||
// console.log('changeSourceAccount');
|
|
||||||
if (typeof item === 'undefined') {
|
if (typeof item === 'undefined') {
|
||||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||||
let source = document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account;
|
let source = document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account;
|
||||||
@ -79,7 +78,7 @@ export function changeSourceAccount(item, ac) {
|
|||||||
export function selectSourceAccount(item, ac) {
|
export function selectSourceAccount(item, ac) {
|
||||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account = {
|
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account = {
|
||||||
id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code,
|
id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code,
|
||||||
};
|
};
|
||||||
document.querySelector('#form')._x_dataStack[0].changedSourceAccount();
|
document.querySelector('#form')._x_dataStack[0].changedSourceAccount();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user