From d02521136cfd272409c810c1a4dcf30be4eed33e Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 3 Oct 2026 07:44:21 +0200 Subject: [PATCH] Better filters for AC, fix #12957 --- .../assets/v3/js/form/create-autocomplete.js | 5 +- .../v3/js/form/get-expected-account-types.js | 43 +++++++++++++++++ .../transactions/shared/add-autocomplete.js | 23 ++++------ .../shared/create-link-autocomplete.js | 2 +- .../shared/disable-split-inputs.js | 46 ++++++------------- 5 files changed, 70 insertions(+), 49 deletions(-) create mode 100644 resources/assets/v3/js/form/get-expected-account-types.js diff --git a/resources/assets/v3/js/form/create-autocomplete.js b/resources/assets/v3/js/form/create-autocomplete.js index 7c37875d7c..7b34ec8a38 100644 --- a/resources/assets/v3/js/form/create-autocomplete.js +++ b/resources/assets/v3/js/form/create-autocomplete.js @@ -21,9 +21,8 @@ import Autocomplete from "bootstrap5-autocomplete"; function createAutocomplete(fieldIdentifier, url) { - let token = document.querySelector('meta[name="csrf-token"]').getAttribute("content"); Autocomplete.init("#" + fieldIdentifier, { - server: url + "?_token=" + token, + server: url, labelField: "name", valueField: "name", liveServer: true, @@ -33,7 +32,7 @@ function createAutocomplete(fieldIdentifier, url) { headers: { "Content-Type": "application/json", Accept: "application/json", - "X-CSRF-TOKEN": token, + "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content"), }, }, }); diff --git a/resources/assets/v3/js/form/get-expected-account-types.js b/resources/assets/v3/js/form/get-expected-account-types.js new file mode 100644 index 0000000000..d5190a2d58 --- /dev/null +++ b/resources/assets/v3/js/form/get-expected-account-types.js @@ -0,0 +1,43 @@ +/* + * get-expected-account-types.js + * Copyright (c) 2026 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 . + */ + +export default function getExpectedAccountTypes(transactionType, sourceType, destinationType) { + transactionType = transactionType.toLowerCase(); + console.log('getExpectedAccountTypes: transactionType=' + transactionType + ', sourceType=' + sourceType + ', destinationType=' + destinationType); + + // is withdrawal and source is asset? limit destination types + if ("withdrawal" === transactionType && "Asset account" === sourceType) { + return ["Expense account", "Asset account", "Loan", "Debt", "Mortgage"]; + } + // is withdrawal and source is liability? Limit destination types + if ("withdrawal" === transactionType && ["Loan", "Debt", "Mortgage"].includes(sourceType)) { + return ["Expense account"]; + } + + // is deposit? limit destination types. + if ("deposit" === transactionType) { + return ["Asset account", "Loan", "Debt", "Mortgage"]; + } + // is transfer or withdrawal? No limit to source types. + // if ("deposit" !== transactionType) { + // return ["Expense account", "Loan", "Debt", "Mortgage", "Asset account"]; + // } + return ["Expense account", "Loan", "Debt", "Mortgage", "Asset account"]; +} diff --git a/resources/assets/v3/js/pages/transactions/shared/add-autocomplete.js b/resources/assets/v3/js/pages/transactions/shared/add-autocomplete.js index d984b969e9..644a412b00 100644 --- a/resources/assets/v3/js/pages/transactions/shared/add-autocomplete.js +++ b/resources/assets/v3/js/pages/transactions/shared/add-autocomplete.js @@ -29,6 +29,7 @@ import { selectSourceAccount, } from "./autocomplete-functions.js"; import Tags from "bootstrap5-tags"; +import getExpectedAccountTypes from "../../../form/get-expected-account-types.js"; export function getUrls() { return { @@ -51,19 +52,13 @@ export function addAllAutocompleteToForm() { // depending on the type of the transaction, // the filters are changed. For edit form, this means // the available account types may be limited. - if ("edit" === this.formBehaviour.formType) { - if ("withdrawal" === this.groupProperties.transactionType) { - // filters.destination = ['Expense account']; - } - if ("deposit" === this.groupProperties.transactionType) { - // filters.source = ['Revenue account']; - } - if ("transfer" === this.groupProperties.transactionType) { - filters.source = [this.entries[0].source_account.type]; - filters.destination = [this.entries[0].source_account.type]; - } - } - // console.log("Filters for autocomplete: ", filters); + + let transactionType = this.groupProperties.transactionType; + let sourceType = this.entries[0].source_account.type ?? 'unknown'; + let destinationType = this.entries[0].destination_account.type ?? 'unknown'; + filters.destination = getExpectedAccountTypes(transactionType, sourceType, destinationType); + + console.log("Filters for autocomplete: ", filters); const urls = getUrls(); setTimeout(() => { @@ -148,6 +143,7 @@ export function addAllAutocompleteToForm() { } export function addAutocomplete(options) { + console.log('addAutocomplete("'+options.serverUrl+'")'); const params = { server: options.serverUrl, serverParams: {}, @@ -169,6 +165,7 @@ export function addAutocomplete(options) { liveServer: true, }; if (typeof options.account_types !== "undefined" && options.account_types.length > 0) { + console.log('Add account types'); params.serverParams["types"] = options.account_types; } if (typeof options.onRenderItem !== "undefined" && null !== options.onRenderItem) { diff --git a/resources/assets/v3/js/pages/transactions/shared/create-link-autocomplete.js b/resources/assets/v3/js/pages/transactions/shared/create-link-autocomplete.js index 6feeb4296d..cb511899b0 100644 --- a/resources/assets/v3/js/pages/transactions/shared/create-link-autocomplete.js +++ b/resources/assets/v3/js/pages/transactions/shared/create-link-autocomplete.js @@ -37,7 +37,7 @@ export function createLinkAutocomplete(fieldIdentifier, url) { "" ); }; - console.log("Created link AC", fieldIdentifier); + // console.log("Created link AC", fieldIdentifier); Autocomplete.init("#" + fieldIdentifier, { server: url, labelField: "name", diff --git a/resources/assets/v3/js/pages/transactions/shared/disable-split-inputs.js b/resources/assets/v3/js/pages/transactions/shared/disable-split-inputs.js index 89bdc1c865..236227a71b 100644 --- a/resources/assets/v3/js/pages/transactions/shared/disable-split-inputs.js +++ b/resources/assets/v3/js/pages/transactions/shared/disable-split-inputs.js @@ -20,6 +20,8 @@ // what happens when a user adds more than one split? import Autocomplete from "bootstrap5-autocomplete"; +import getExpectedAccountTypes from "../../../form/get-expected-account-types.js"; + export function disableSplitInputs() { let isTransferOrWithdrawal = @@ -29,38 +31,18 @@ export function disableSplitInputs() { //console.log('Activate disableSplitInputs'); // disable source and/or destination, based on account type. for (let i = 0; i < this.entries.length; i++) { - // is withdrawal? limit destination types to expense, loan debt mortgage - if ("withdrawal" === this.groupProperties.transactionType) { - const el = document.getElementById("dest_" + i); - const inst = Autocomplete.getInstance(el); - if (null !== inst) { - let params = inst.getConfig("serverParams"); - params.types = ["Expense account", "Loan", "Debt", "Mortgage"]; - inst.setConfig("serverParams", params); - } - } - // is deposit? limit destination types. - if ("deposit" === this.groupProperties.transactionType) { - const el = document.getElementById("dest_" + i); - const inst = Autocomplete.getInstance(el); - if (null !== inst) { - let params = inst.getConfig("serverParams"); - params.types = ["Asset account", "Loan", "Debt", "Mortgage"]; - inst.setConfig("serverParams", params); - } - } - // is transfer? No limit to source types. - if ( - "deposit" !== this.groupProperties.transactionType && - "withdrawal" === this.groupProperties.transactionType - ) { - const el = document.getElementById("dest_" + i); - const inst = Autocomplete.getInstance(el); - if (null !== inst) { - let params = inst.getConfig("serverParams"); - params.types = []; - inst.setConfig("serverParams", params); - } + let transactionType = this.groupProperties.transactionType; + let sourceType = this.entries[i].source_account.type ?? "unknown"; + let destinationType = this.entries[i].destination_account.type ?? "unknown"; + + let newTypes = getExpectedAccountTypes(transactionType, sourceType, destinationType); + + const el = document.getElementById("dest_" + i); + const inst = Autocomplete.getInstance(el); + if (null !== inst) { + let params = inst.getConfig("serverParams"); + params.types = newTypes; + inst.setConfig("serverParams", params); } if (i > 0) {