Expand AC

This commit is contained in:
James Cole 2023-03-31 19:20:26 +02:00
parent c3b99c322d
commit 9939ed0aaf
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
5 changed files with 287 additions and 48 deletions

View File

@ -42,12 +42,19 @@
:has-submission-error="hasSubmissionErrors.description"
:disabled-input="disabledInput"
:description="transaction.description"
@update:description="updateDescription"/>
@update:description="updateDescription"
/>
</div>
</div>
<div class="row">
<div class="col-4 q-mb-xs q-pr-xs">
<SourceAccount name="Test" :disabled-input="false" submission-error="" :has-submission-error="false" />
<SourceAccount
:name="''"
@update:source="updateSource"
:disabled-input="false"
submission-error=""
:transaction-type="transactionType"
:has-submission-error="false"/>
</div>
<div class="col-4 q-px-xs">
<q-input
@ -60,14 +67,13 @@
outlined reverse-fill-mask/>
</div>
<div class="col-4 q-pl-xs">
<q-input dense
v-model="transaction.destination"
:disable="disabledInput"
:error="hasSubmissionErrors.destination"
:error-message="submissionErrors.destination" :label="$t('firefly.destination_account')"
bottom-slots
clearable
outlined/>
<DestinationAccount
:name="''"
@update:destination="updateDestination"
:disabled-input="false"
submission-error=""
:transaction-type="transactionType"
:has-submission-error="false"/>
</div>
</div>
<div class="row">
@ -268,15 +274,21 @@
<script>
import TransactionDescription from "components/transactions/form/TransactionDescription.vue";
import SourceAccount from "components/transactions/form/SourceAccount.vue";
import DestinationAccount from "components/transactions/form/DestinationAccount.vue";
export default {
name: "Split",
components: {SourceAccount, TransactionDescription},
components: {DestinationAccount, SourceAccount, TransactionDescription},
props: {
index: {
type: Number,
required: true
},
transactionType: {
type: String,
default: 'unknown',
required: true
},
disabledInput: {
type: Boolean,
required: true
@ -297,6 +309,17 @@ export default {
methods: {
updateDescription(newVal) {
this.transaction.description = newVal;
console.log('Description is now "' + newVal + '"');
},
updateSource(newVal) {
this.transaction.source = newVal;
console.log('Source is now:');
console.log(newVal);
},
updateDestination(newVal) {
this.transaction.destination = newVal;
console.log('Destination is now:');
console.log(newVal);
}
},
watch: {

View File

@ -0,0 +1,156 @@
<!--
- SourceAccount.vue
- Copyright (c) 2023 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/>.
-->
<template>
<q-select
v-model="model"
use-input
:options="options"
@filter="filterFn"
dense
:loading="loading"
outlined
new-value-mode="add-unique"
:disable="disabledInput"
:error="hasSubmissionError"
:label="$t('firefly.destination_account')"
:error-message="submissionError"
bottom-slots
clearable
>
<!--
input-debounce="0"
label="Lazy filter"
-->
<template v-slot:option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section>
<q-item-label>{{ scope.opt.label }}</q-item-label>
<q-item-label caption>{{ scope.opt.type }}</q-item-label>
</q-item-section>
</q-item>
</template>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
</template>
<!--
source account is basic dropdown from API
with optional filters on account type. This depends
on transaction type which is null or invalid or withdrawal or whatever
if the index is not null the field shall be disabled and empty.
-->
<script>
import Accounts from '../../../api/v2/autocomplete/accounts'
export default {
name: "DestinationAccount",
data() {
return {
model: null,
transactionTypeString: '',
options: [],
loading: true,
}
},
props: {
name: {
type: String,
required: true
},
transactionType: {
type: String,
required: false,
default: 'unknown'
},
disabledInput: {
type: Boolean,
default: false,
required: true
},
hasSubmissionError: {
type: Boolean,
default: false,
required: true
},
submissionError: {
type: String,
required: true
}
},
mounted() {
this.getAccounts('');
this.model = this.name;
},
methods: {
getAccounts: function (query) {
this.loading = true;
// default set of account types, will later be set by the transaction type.
let types = 'Expense account, Loan, Debt, Mortgage';
if('deposit' === this.transactionType) {
let types = 'Asset account, Loan, Debt, Mortgage';
}
(new Accounts).get(types, query).then(response => {
this.stringOptions = [];
for (let i in response.data) {
let entry = response.data[i];
let current = {
label: entry.name,
value: entry.id,
type: entry.type
}
this.stringOptions.push(current);
}
//this.stringOptions = response.data.data;
this.options = this.stringOptions;
this.loading = false;
});
},
filterFn(val, update, abort) {
update(() => {
this.getAccounts(val);
})
}
},
watch: {
model: {
handler: function (newVal) {
if(newVal !== undefined) {
this.$emit('update:destination', newVal);
}
},
deep: true
}
}
}
</script>

View File

@ -27,6 +27,7 @@
dense
:loading="loading"
outlined
new-value-mode="add-unique"
:disable="disabledInput"
:error="hasSubmissionError"
:label="$t('firefly.source_account')"
@ -44,7 +45,7 @@
<q-item v-bind="scope.itemProps">
<q-item-section>
<q-item-label>{{ scope.opt.label }}</q-item-label>
<q-item-label caption>{{ scope.opt.description }}</q-item-label>
<q-item-label caption>{{ scope.opt.type }}</q-item-label>
</q-item-section>
</q-item>
</template>
@ -87,7 +88,8 @@ export default {
},
transactionType: {
type: String,
required: false
required: false,
default: 'unknown'
},
disabledInput: {
type: Boolean,
@ -105,16 +107,18 @@ export default {
}
},
mounted() {
console.log('Mounted');
//this.options.value = this.stringOptions
this.getAccounts('');
this.model = this.name;
},
methods: {
getAccounts: function (query) {
this.loading = true;
console.log('getAccounts("'+query+'")');
// default set of account types, will later be set by the transaction type.
let types = 'Asset account,Revenue account,Loan,Debt,Mortgage';
if('deposit' === this.transactionType) {
console.log('NOW DEPOSIT');
}
(new Accounts).get(types, query).then(response => {
this.stringOptions = [];
for (let i in response.data) {
@ -122,46 +126,31 @@ export default {
let current = {
label: entry.name,
value: entry.id,
description: entry.type
type: entry.type
}
this.stringOptions.push(current);
}
//this.stringOptions = response.data.data;
this.options = this.stringOptions;
this.options = this.stringOptions;
this.loading = false;
console.log('getAccounts done!');
});
},
filterFn(val, update, abort) {
console.log('filterFn(' + val + ')');
if (val === '') {
update(() => {
this.getAccounts('');
//this.options = stringOptions
// here you have access to "ref" which
// is the Vue reference of the QSelect
})
return
}
update(() => {
this.getAccounts(val);
//const needle = val.toLowerCase()
//this.options = this.options.filter(v => v.label.toLowerCase().indexOf(needle) > -1)
})
// console.log('filterFn(' + val + ')');
// if (this.loading) {
// console.log('return');
// return
// }
// const needle = val.toLowerCase()
// this.options = this.stringOptions.filter(v => v.label.toLowerCase().indexOf(needle) > -1);
}
},
watch: {
model: {
handler: function (newVal) {
if(newVal !== undefined) {
this.$emit('update:source', newVal);
}
},
deep: true
}
}
}
</script>
<style scoped>
</style>

View File

@ -59,6 +59,7 @@
<Split
:transaction="transaction"
:index="index"
:transaction-type="transactionType"
:disabled-input="disabledInput"
:has-submission-errors="hasSubmissionErrors[index]"
:submission-errors="submissionErrors[index]"
@ -112,6 +113,7 @@ import format from 'date-fns/format';
import formatISO from 'date-fns/formatISO';
import Post from "../../api/transactions/post";
import Split from "components/transactions/Split.vue";
import CalculateType from "src/support/transactions/calculate-type";
export default {
name: 'Create',
@ -119,6 +121,7 @@ export default {
data() {
return {
tab: 'split-0',
transactionType: 'unknown',
transactions: [],
submissionErrors: [],
hasSubmissionErrors: [],
@ -165,7 +168,7 @@ export default {
this.tab = 'split-' + index;
},
getSplitLabel: function (index) {
console.log('Get split label (' + index + ')');
//console.log('Get split label (' + index + ')');
if (this.transactions.hasOwnProperty(index) &&
null !== this.transactions[index].description &&
this.transactions[index].description.length > 0) {
@ -196,10 +199,9 @@ export default {
},
updateTransaction: function (obj) {
const index = obj.index;
const transaction = obj.transaction;
console.log('Update transaction ' + index);
console.log(transaction);
this.transactions[index] = transaction;
this.transactions[index] = obj.transaction;
// TODO needs to update all splits if necessary and warn user about it.
this.transactionType = (new CalculateType()).calculateType(this.transactions[0].source, this.transactions[0].destination);
},
processSuccess: function (response) {
console.log('process success');

View File

@ -0,0 +1,69 @@
/*
* calculate-type.js
* Copyright (c) 2023 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/>.
*/
export default class CalculateType {
calculateType(source, destination) {
const srcEmpty = this.empty(source);
const dstEmpty = this.empty(destination);
// both are null or ''
if (srcEmpty && dstEmpty) {
return 'unknown';
}
// source has data, dest has not
if (typeof source === 'object' && null !== source && dstEmpty) {
if (source.type === 'Asset account' || source.type === 'Loan' || source.type === 'Debt' || source.type === 'Mortgage') {
return 'withdrawal';
}
if (source.type === 'Revenue account') {
return 'deposit';
}
}
// dst has data, source has not
if (typeof destination === 'object' && null !== destination && srcEmpty) {
if (destination.type === 'Asset account') {
return 'deposit';
}
}
// both have data:
if (!srcEmpty && !dstEmpty) {
if (source.type === 'Asset account' && destination.type === 'Expense account') {
return 'withdrawal';
}
if (source.type === destination.type) {
return 'transfer';
}
}
console.error('Cannot handle');
console.log(source);
console.log(destination);
}
empty(value) {
if (null === value || '' === value) {
return true;
}
if (null !== value && typeof value === 'object') {
return false;
}
return true;
}
}