Rebuild frontend, do not use store in components.

This commit is contained in:
James Cole
2021-02-22 18:43:26 +01:00
parent 6d9acd1dc2
commit 5b5c988aa3
87 changed files with 2887 additions and 2835 deletions

View File

@@ -24,6 +24,7 @@ const lodashClonedeep = require('lodash.clonedeep');
const state = () => ({
transactionType: 'any',
date: new Date,
time: new Date,
groupTitle: '',
transactions: [],
allowedOpposingTypes: {},
@@ -63,6 +64,22 @@ const state = () => ({
description: '',
transaction_journal_id: 0,
// accounts:
source_account_id: null,
source_account_name: null,
source_account_type: null,
source_account_currency_id: null,
source_account_currency_code: null,
source_account_currency_symbol: null,
destination_account_id: null,
destination_account_name: null,
destination_account_type: null,
destination_account_currency_id: null,
destination_account_currency_code: null,
destination_account_currency_symbol: null,
source_account: {
id: 0,
name: "",
@@ -133,12 +150,20 @@ const getters = {
date: state => {
return state.date;
},
time: state => {
return state.time;
},
groupTitle: state => {
return state.groupTitle;
},
transactionType: state => {
return state.transactionType;
},
accountToTransaction: state => {
// TODO better architecture here, does not need the store.
// possible API point!!
return state.accountToTransaction;
},
defaultTransaction: state => {
return state.defaultTransaction;
},
@@ -166,45 +191,7 @@ const getters = {
// actions
const actions = {
calcTransactionType(context) {
let source = context.state.transactions[0].source_account;
let dest = context.state.transactions[0].destination_account;
if (null === source || null === dest) {
// console.log('transactionType any');
context.commit('setTransactionType', 'any');
return;
}
if ('' === source.type || '' === dest.type) {
// console.log('transactionType any');
context.commit('setTransactionType', 'any');
return;
}
// ok so type is set on both:
let expectedDestinationTypes = context.state.accountToTransaction[source.type];
if ('undefined' !== typeof expectedDestinationTypes) {
let transactionType = expectedDestinationTypes[dest.type];
if ('undefined' !== typeof expectedDestinationTypes[dest.type]) {
// console.log('Found a type: ' + transactionType);
context.commit('setTransactionType', transactionType);
return;
}
}
// console.log('Found no type for ' + source.type + ' --> ' + dest.type);
if ('Asset account' !== source.type) {
console.log('Drop ID from source. TODO');
// source.id =null
// context.commit('updateField', {field: 'source_account',index: })
// context.state.transactions[0].source_account.id = null;
}
if ('Asset account' !== dest.type) {
console.log('Drop ID from destination. TODO');
//context.state.transactions[0].destination_account.id = null;
}
context.commit('setTransactionType', 'any');
}
}
// mutations
@@ -224,6 +211,9 @@ const mutations = {
setDate(state, payload) {
state.date = payload.date;
},
setTime(state, payload) {
state.time = payload.time;
},
setGroupTitle(state, payload) {
state.groupTitle = payload.groupTitle;
},

View File

@@ -33,7 +33,36 @@
:custom-fields="customFields"
:submitted-transaction="submittedTransaction"
v-on:uploaded-attachments="uploadedAttachment($event)"
v-on:set-description="storeDescription(index, $event)"
v-on:set-marker-location="storeLocation(index, $event)"
v-on:set-source-account-id="storeAccountValue(index, 'source', 'id', $event)"
v-on:set-source-account-name="storeAccountValue(index, 'source', 'name', $event)"
v-on:set-source-account-type="storeAccountValue(index, 'source', 'type', $event)"
v-on:set-source-account-currency-id="storeAccountValue(index, 'source', 'currency_id', $event)"
v-on:set-source-account-currency-code="storeAccountValue(index, 'source', 'currency_code', $event)"
v-on:set-source-account-currency-symbol="storeAccountValue(index, 'source', 'currency_symbol', $event)"
v-on:set-destination-account-id="storeAccountValue(index, 'destination', 'id', $event)"
v-on:set-destination-account-name="storeAccountValue(index, 'destination', 'name', $event)"
v-on:set-destination-account-type="storeAccountValue(index, 'destination', 'type', $event)"
v-on:set-destination-account-currency-id="storeAccountValue(index, 'destination', 'currency_id', $event)"
v-on:set-destination-account-currency-code="storeAccountValue(index, 'destination', 'currency_code', $event)"
v-on:set-destination-account-currency-symbol="storeAccountValue(index, 'destination', 'currency_symbol', $event)"
v-on:switch-accounts="switchAccounts($event)"
v-on:set-amount="storeAmount(index, $event)"
v-on:set-foreign-currency-id="storeForeignCurrencyId(index, $event)"
v-on:set-foreign-amount="storeForeignAmount(index, $event)"
v-on:set-date="storeDate($event)"
v-on:set-time="storeTime($event)"
v-on:set-custom-date="storeCustomDate(index, $event)"
v-on:set-budget="storeBudget(index, $event)"
v-on:set-category="storeCategory(index, $event)"
v-on:set-bill="storeBill(index, $event)"
v-on:set-tags="storeTags(index, $event)"
v-on:set-piggy-bank="storePiggyBank(index, $event)"
v-on:set-internal-reference="storeInternalReference(index, $event)"
v-on:set-external-url="storeExternalUrl(index, $event)"
v-on:set-notes="storeNotes(index, $event)"
v-on:set-links="storeLinks(index, $event)"
/>
</div>
@@ -154,6 +183,9 @@ export default {
// group ID + title once submitted:
returnedGroupId: 0,
returnedGroupTitle: '',
// meta data:
accountToTransaction: {}
}
},
computed: {
@@ -161,6 +193,7 @@ export default {
'transactionType',
'transactions',
'date',
'time',
'groupTitle'
])
},
@@ -187,11 +220,13 @@ export default {
'addTransaction',
'deleteTransaction',
'setAllowedOpposingTypes',
'setAccountToTransaction',
'setTransactionError',
'setTransactionType',
'resetErrors',
'updateField',
'resetTransactions'
'resetTransactions',
'setDate',
'setTime'
],
),
/**
@@ -279,6 +314,9 @@ export default {
const url = './api/v1/transactions';
const data = this.convertData();
console.log('Will submit:');
console.log(data);
// POST the transaction.
axios.post(url, data)
.then(response => {
@@ -347,7 +385,10 @@ export default {
this.submittedAttachments = true;
}
},
storeLocation: function(index, event) {
/**
* Responds to changed location.
*/
storeLocation: function (index, event) {
let zoomLevel = event.hasMarker ? event.zoomLevel : null;
let lat = event.hasMarker ? event.lat : null;
let lng = event.hasMarker ? event.lng : null;
@@ -355,8 +396,127 @@ export default {
this.updateField({index: index, field: 'latitude', value: lat});
this.updateField({index: index, field: 'longitude', value: lng});
},
/**
* Responds to changed account.
*/
storeAccountValue: function (index, direction, field, value) {
// depending on these account values
let key = direction + '_account_' + field;
//console.log('storeAccountValue(' + index + ', "' + direction + '", "' + field + '", "' + key + '") = "' + value + '"');
this.updateField({index: index, field: key, value: value});
if ('type' === field) {
this.calculateTransactionType(index);
}
},
storeDescription: function (index, value) {
this.updateField({field: 'description', index: index, value: value});
},
storeForeignCurrencyId: function (index, value) {
console.log('storeForeignCurrencyId(' + index + ',' + value + ')');
this.updateField({field: 'foreign_currency_id', index: index, value: value});
},
storeAmount: function (index, value) {
this.updateField({field: 'amount', index: index, value: value});
},
storeForeignAmount: function (index, value) {
this.updateField({field: 'foreign_amount', index: index, value: value});
},
storeDate: function (value) {
this.setDate(value.date)
},
storeTime: function (value) {
this.setTime(value.time)
},
storeCustomDate: function (index, payload) {
this.updateField({field: payload.field, index: index, value: payload.date});
},
storeBudget: function (index, value) {
this.updateField({field: 'budget_id', index: index, value: value});
},
storeCategory: function (index, value) {
this.updateField({field: 'category', index: index, value: value});
},
storeBill: function (index, value) {
this.updateField({field: 'bill_id', index: index, value: value});
},
storeTags: function (index, value) {
this.updateField({field: 'tags', index: index, value: value});
},
storePiggyBank: function (index, value) {
this.updateField({field: 'piggy_bank_id', index: index, value: value});
},
storeInternalReference: function (index, value) {
this.updateField({field: 'internal_reference', index: index, value: value});
},
storeExternalUrl: function (index, value) {
this.updateField({field: 'external_url', index: index, value: value});
},
storeNotes: function (index, value) {
this.updateField({field: 'notes', index: index, value: value});
},
storeLinks: function (index, value) {
this.updateField({field: 'links', index: index, value: value});
},
/**
* Calculate the transaction type based on what's currently in the store.
*/
calculateTransactionType: function (index) {
//console.log('calculateTransactionType(' + index + ')');
if (0 === index) {
let source = this.transactions[0].source_account_type;
let dest = this.transactions[0].destination_account_type;
if (null === source || null === dest) {
//console.log('transactionType any');
this.setTransactionType('any');
//this.$store.commit('setTransactionType', 'any');
//console.log('calculateTransactionType: either type is NULL so no dice.');
return;
}
if ('' === source || '' === dest) {
//console.log('transactionType any');
this.setTransactionType('any');
//this.$store.commit('setTransactionType', 'any');
//console.log('calculateTransactionType: either type is empty so no dice.');
return;
}
// ok so type is set on both:
let expectedDestinationTypes = this.accountToTransaction[source];
if ('undefined' !== typeof expectedDestinationTypes) {
let transactionType = expectedDestinationTypes[dest];
if ('undefined' !== typeof expectedDestinationTypes[dest]) {
//console.log('Found a type: ' + transactionType);
this.setTransactionType(transactionType);
//this.$store.commit('setTransactionType', transactionType);
//console.log('calculateTransactionType: ' + source + ' --> ' + dest + ' = ' + transactionType);
return;
}
}
//console.log('Found no type for ' + source + ' --> ' + dest);
if ('Asset account' !== source) {
//console.log('Drop ID from destination.');
this.updateField({index: 0, field: 'destination_account_id', value: null});
//console.log('calculateTransactionType: drop ID from destination.');
// source.id =null
// context.commit('updateField', {field: 'source_account',index: })
// context.state.transactions[0].source_account.id = null;
}
if ('Asset account' !== dest) {
//console.log('Drop ID from source.');
this.updateField({index: 0, field: 'source_account_id', value: null});
//console.log('calculateTransactionType: drop ID from source.');
//context.state.transactions[0].destination_account.id = null;
}
//console.log('calculateTransactionType: fallback, type to any.');
this.setTransactionType('any');
//this.$store.commit('setTransactionType', 'any');
}
},
/**
* Submit transaction links.
*/
submitTransactionLinks(data, response) {
console.log('submitTransactionLinks()');
//console.log('submitTransactionLinks()');
let promises = [];
let result = response.data.data.attributes.transactions;
let total = 0;
@@ -552,6 +712,26 @@ export default {
},
switchAccounts: function (index) {
console.log('user wants to switch Accounts');
let origSourceId = this.transactions[index].source_account_id;
let origSourceName = this.transactions[index].source_account_name;
let origSourceType = this.transactions[index].source_account_type;
let origDestId = this.transactions[index].destination_account_id;
let origDestName = this.transactions[index].destination_account_name;
let origDestType = this.transactions[index].destination_account_type;
this.updateField({index: 0, field: 'source_account_id', value: origDestId});
this.updateField({index: 0, field: 'source_account_name', value: origDestName});
this.updateField({index: 0, field: 'source_account_type', value: origDestType});
this.updateField({index: 0, field: 'destination_account_id', value: origSourceId});
this.updateField({index: 0, field: 'destination_account_name', value: origSourceName});
this.updateField({index: 0, field: 'destination_account_type', value: origSourceType});
this.calculateTransactionType(0);
},
/**
*
@@ -560,9 +740,18 @@ export default {
*/
convertSplit: function (key, array) {
let dateStr = 'invalid';
if (this.date instanceof Date && !isNaN(this.date)) {
if (
this.time instanceof Date && !isNaN(this.time) &&
this.date instanceof Date && !isNaN(this.date)
) {
let theDate = new Date(this.date);
// update time in date object.
theDate.setHours(this.time.getHours());
theDate.setMinutes(this.time.getMinutes());
theDate.setSeconds(this.time.getSeconds());
dateStr = this.toW3CString(this.date);
}
let currentSplit = {
// basic
description: array.description,
@@ -570,10 +759,10 @@ export default {
type: this.transactionType,
// account
source_id: array.source_account.id ?? null,
source_name: array.source_account.name ?? null,
destination_id: array.destination_account.id ?? null,
destination_name: array.destination_account.name ?? null,
source_id: array.source_account_id ?? null,
source_name: array.source_account_name ?? null,
destination_id: array.destination_account_id ?? null,
destination_name: array.destination_account_name ?? null,
// amount:
currency_id: array.currency_id,
@@ -616,7 +805,7 @@ export default {
}
// foreign amount:
if (0 !== array.foreign_currency_id) {
if (0 !== array.foreign_currency_id && '' !== array.foreign_amount) {
currentSplit.foreign_currency_id = array.foreign_currency_id;
}
if ('' !== array.foreign_amount) {
@@ -633,19 +822,22 @@ export default {
//console.log('Transaction type is now ' + transactionType);
// if the transaction type is invalid, might just be that we can deduce it from
// the presence of a source or destination account
firstSource = this.transactions[0].source_account.type;
firstDestination = this.transactions[0].destination_account.type;
firstSource = this.transactions[0].source_account_type;
firstDestination = this.transactions[0].destination_account_type;
//console.log(this.transactions[0].source_account);
//console.log(this.transactions[0].destination_account);
//console.log('Type of first source is ' + firstSource);
//console.log('Type of first destination is ' + firstDestination);
// default to source:
currentSplit.currency_id = array.source_account_currency_id;
if ('any' === transactionType && ['asset', 'Asset account', 'Loan', 'Debt', 'Mortgage'].includes(firstSource)) {
transactionType = 'withdrawal';
}
if ('any' === transactionType && ['asset', 'Asset account', 'Loan', 'Debt', 'Mortgage'].includes(firstDestination)) {
transactionType = 'deposit';
currentSplit.currency_id = array.destination_account_currency_id;
}
currentSplit.type = transactionType;
//console.log('Final type is ' + transactionType);
@@ -712,10 +904,14 @@ export default {
offsetSign + offsetHours + ':' + offsetMinutes;
},
storeAllowedOpposingTypes: function () {
// take this from API:
this.setAllowedOpposingTypes(window.allowedOpposingTypes);
},
storeAccountToTransaction: function () {
this.setAccountToTransaction(window.accountToTransaction);
axios.get('./api/v1/configuration/static/firefly.account_to_transaction')
.then(response => {
this.accountToTransaction = response.data['firefly.account_to_transaction'];
});
},
},

View File

@@ -34,6 +34,7 @@
<div class="row">
<div class="col">
<TransactionDescription
v-on="$listeners"
v-model="transaction.description"
:index="index"
:errors="transaction.errors.description"
@@ -45,7 +46,8 @@
<div class="col-xl-5 col-lg-5 col-md-10 col-sm-12 col-xs-12">
<!-- SOURCE -->
<TransactionAccount
v-model="transaction.source_account"
v-on="$listeners"
v-model="sourceAccount"
direction="source"
:index="index"
:errors="transaction.errors.source"
@@ -53,8 +55,10 @@
</div>
<!-- switcharoo! -->
<div class="col-xl-2 col-lg-2 col-md-2 col-sm-12 text-center d-none d-sm-block">
<SwitchAccount v-if="0 === index"
:index="index"
<SwitchAccount
v-if="0 === index"
v-on="$listeners"
:index="index"
/>
</div>
@@ -62,7 +66,8 @@
<div class="col-xl-5 col-lg-5 col-md-12 col-sm-12 col-xs-12">
<!-- DESTINATION -->
<TransactionAccount
v-model="transaction.destination_account"
v-on="$listeners"
v-model="destinationAccount"
direction="destination"
:index="index"
:errors="transaction.errors.destination"
@@ -75,16 +80,42 @@
<div class="row">
<div class="col-xl-5 col-lg-5 col-md-10 col-sm-12 col-xs-12">
<!-- AMOUNT -->
<TransactionAmount :index="index" :errors="transaction.errors.amount"/>
<!--
-->
<TransactionAmount
:index="index"
:errors="transaction.errors.amount"
:amount="transaction.amount"
:transaction-type="this.transactionType"
:source-currency-symbol="this.transaction.source_account_currency_symbol"
:destination-currency-symbol="this.transaction.destination_account_currency_symbol"
v-on="$listeners"
/>
</div>
<div class="col-xl-2 col-lg-2 col-md-2 col-sm-12 text-center d-none d-sm-block">
<TransactionForeignCurrency :index="index"/>
<TransactionForeignCurrency
v-on="$listeners"
:transaction-type="this.transactionType"
:source-currency-id="this.transaction.source_account_currency_id"
:destination-currency-id="this.transaction.destination_account_currency_id"
:selected-currency-id="this.transaction.foreign_currency_id"
:index="index"
/>
</div>
<div class="col-xl-5 col-lg-5 col-md-12 col-sm-12 col-xs-12">
<TransactionForeignAmount :index="index" :errors="transaction.errors.foreign_amount"/>
<!--
The reason that TransactionAmount gets the symbols and
TransactionForeignAmount gets the ID's of the currencies is
because ultimately TransactionAmount doesn't decide which
currency id is submitted to Firefly III.
-->
<TransactionForeignAmount
:index="index"
v-on="$listeners"
:errors="transaction.errors.foreign_amount"
:transaction-type="this.transactionType"
:source-currency-id="this.transaction.source_account_currency_id"
:destination-currency-id="this.transaction.destination_account_currency_id"
:selected-currency-id="this.transaction.foreign_currency_id"
/>
</div>
</div>
@@ -93,6 +124,9 @@
<div class="col-xl-5 col-lg-5 col-md-12 col-sm-12 col-xs-12">
<TransactionDate
:index="index"
v-on="$listeners"
:date="splitDate"
:time="splitTime"
:errors="transaction.errors.date"
/>
</div>
@@ -100,8 +134,15 @@
<div class="col-xl-5 col-lg-5 col-md-12 col-sm-12 col-xs-12 offset-xl-2 offset-lg-2">
<TransactionCustomDates
:index="index"
v-on="$listeners"
:custom-fields.sync="customFields"
:errors="transaction.errors.custom_dates"
:interest-date="transaction.interest_date"
:book-date="transaction.book_date"
:process-date="transaction.process_date"
:due-date="transaction.due_date"
:payment-date="transaction.payment_date"
:invoice-date="transaction.invoice_date"
/>
</div>
</div>
@@ -128,12 +169,14 @@
<div class="row">
<div class="col-xl-6 col-lg-6 col-md-12 col-sm-12 col-xs-12">
<TransactionBudget
v-on="$listeners"
v-model="transaction.budget_id"
:index="index"
:errors="transaction.errors.budget"
v-if="!('Transfer' === transactionType || 'Deposit' === transactionType)"
/>
<TransactionCategory
v-on="$listeners"
v-model="transaction.category"
:index="index"
:errors="transaction.errors.category"
@@ -141,17 +184,20 @@
</div>
<div class="col-xl-6 col-lg-6 col-md-12 col-sm-12 col-xs-12">
<TransactionBill
v-on="$listeners"
v-model="transaction.bill_id"
:index="index"
:errors="transaction.errors.bill"
v-if="!('Transfer' === transactionType || 'Deposit' === transactionType)"
/>
<TransactionTags
v-on="$listeners"
:index="index"
v-model="transaction.tags"
:errors="transaction.errors.tags"
/>
<TransactionPiggyBank
v-on="$listeners"
:index="index"
v-model="transaction.piggy_bank_id"
:errors="transaction.errors.piggy_bank"
@@ -180,6 +226,7 @@
<div class="col-xl-6 col-lg-6 col-md-12 col-sm-12 col-xs-12">
<TransactionInternalReference
v-on="$listeners"
:index="index"
v-model="transaction.internal_reference"
:errors="transaction.errors.internal_reference"
@@ -187,12 +234,14 @@
/>
<TransactionExternalUrl
v-on="$listeners"
:index="index"
v-model="transaction.external_url"
:errors="transaction.errors.external_url"
:custom-fields.sync="customFields"
/>
<TransactionNotes
v-on="$listeners"
:index="index"
v-model="transaction.notes"
:errors="transaction.errors.notes"
@@ -219,6 +268,7 @@
/>
<TransactionLinks
v-on="$listeners"
:index="index"
v-model="transaction.links"
:custom-fields.sync="customFields"
@@ -272,8 +322,29 @@ export default {
'index',
'submittedTransaction' // need to know if transaction is submitted.
],
// TODO get rid of mapped getters.
computed: {
...mapGetters(['transactionType',]),
...mapGetters(['transactionType', 'date', 'time']),
splitDate: function () {
return this.date;
},
splitTime: function () {
return this.time;
},
sourceAccount: function () {
return {
id: this.transaction.source_account_id,
name: this.transaction.source_account_name,
type: this.transaction.source_account_type,
};
},
destinationAccount: function () {
return {
id: this.transaction.destination_account_id,
name: this.transaction.destination_account_name,
type: this.transaction.destination_account_type,
};
},
hasMetaFields: function () {
let requiredFields = [
'internal_reference',

View File

@@ -49,18 +49,11 @@ export default {
),
switchAccounts() {
let source = this.transactions[this.index].source_account;
let dest = this.transactions[this.index].destination_account;
this.updateField({field: 'source_account', index: this.index, value: dest});
this.updateField({field: 'destination_account', index: this.index, value: source});
// trigger other components.
this.$emit('switch-accounts', this.index);
}
},
computed: {
...mapGetters(['transactions', 'transactionType']),
...mapGetters(['transactionType']),
}
}
</script>

View File

@@ -40,6 +40,12 @@
@input="lookupAccount"
@hit="selectedAccount = $event"
>
<template slot="suggestion" slot-scope="{ data, htmlText }">
<div class="d-flex" :title="data.type">
<span v-html="htmlText"></span><br>
</div>
</template>
<template slot="append">
<div class="input-group-append">
<button tabindex="-1" class="btn btn-outline-secondary" v-on:click="clearAccount" type="button"><i class="far fa-trash-alt"></i></button>
@@ -75,7 +81,8 @@ export default {
initialSet: [],
selectedAccount: {},
account: this.value,
accountName: ''
accountName: '',
selectedAccountTrigger: false,
}
},
created() {
@@ -89,20 +96,12 @@ export default {
'setSourceAllowedTypes'
],
),
...mapActions(
[
'calcTransactionType'
]
),
getACURL: function (types, query) {
let URL = './api/v1/autocomplete/accounts?types=' + types.join(',') + '&query=' + query;
//console.log('AC URL is ' + URL);
return URL;
return './api/v1/autocomplete/accounts?types=' + types.join(',') + '&query=' + query;
},
clearAccount: function () {
this.accounts = this.initialSet;
this.account = {name: ''};
this.account = {name: '', type: 'no_type', id: null, currency_id: null, currency_code: null, currency_symbol: null};
this.accountName = '';
},
lookupAccount: debounce(function () {
@@ -136,13 +135,41 @@ export default {
},
watch: {
selectedAccount: function (value) {
//console.log('Now in selectedAccount');
//console.log(value);
//console.log('Emit on selected account');
this.selectedAccountTrigger = true;
this.account = value;
this.$emit(this.emitAccountId, value.id);
this.$emit(this.emitAccountType, value.type);
this.$emit(this.emitAccountName, value.name);
this.$emit(this.emitAccountCurrencyId, value.currency_id);
this.$emit(this.emitAccountCurrencyCode, value.currency_code);
this.$emit(this.emitAccountCurrencySymbol, value.currency_symbol);
//this.$emit(this.emitAccount, value);
this.accountName = this.account.name_with_balance;
// call method to set what the opposing accounts should be.
// and what the
},
accountName: function (value) {
if (false === this.selectedAccountTrigger) {
console.log('Save to change name!');
this.$emit(this.emitAccountId, null);
this.$emit(this.emitAccountType, null);
this.$emit(this.emitAccountName, value);
this.$emit(this.emitAccountCurrencyId, null);
this.$emit(this.emitAccountCurrencyCode, null);
this.$emit(this.emitAccountCurrencySymbol, null);
//this.$emit(this.emitAccount, {name: value, type: null, id: null, currency_id: null, currency_code: null, currency_symbol: null});
// also reset local account thing, but dont be weird about it
this.accountTrigger = false;
this.account = {name: value, type: null, id: null, currency_id: null, currency_code: null, currency_symbol: null};
}
this.selectedAccountTrigger = false;
},
account: function (value) {
this.updateField({field: this.accountKey, index: this.index, value: value});
//this.updateField({field: this.accountKey, index: this.index, value: value});
// set the opposing account allowed set.
let opposingAccounts = [];
let type = value.type ? value.type : 'no_type';
@@ -158,9 +185,13 @@ export default {
if ('destination' === this.direction) {
this.setSourceAllowedTypes(opposingAccounts);
}
this.calcTransactionType();
},
value: function (value) {
console.log(this.direction + ' account overruled by external forces.');
this.account = value;
this.selectedAccountTrigger = true;
this.accountName = value.name;
}
},
computed: {
...mapGetters([
@@ -174,6 +205,42 @@ export default {
return 'source' === this.direction ? 'source_account' : 'destination_account';
}
},
emitAccountId: {
get() {
return 'set-' + this.direction + '-account-id';
}
},
emitAccount: {
get() {
return 'set-' + this.direction + '-account';
}
},
emitAccountName: {
get() {
return 'set-' + this.direction + '-account-name';
}
},
emitAccountType: {
get() {
return 'set-' + this.direction + '-account-type';
}
},
emitAccountCurrencyId: {
get() {
return 'set-' + this.direction + '-account-currency-id';
}
},
emitAccountCurrencyCode: {
get() {
return 'set-' + this.direction + '-account-currency-code';
}
},
emitAccountCurrencySymbol: {
get() {
return 'set-' + this.direction + '-account-currency-symbol';
}
},
visible: {
get() {
// index 0 is always visible:

View File

@@ -22,137 +22,67 @@
<div class="form-group">
<div class="text-xs">{{ $t('firefly.amount') }}</div>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-prepend" v-if="currencySymbol">
<div class="input-group-text">{{ currencySymbol }}</div>
</div>
<input type="hidden" name="currency_id[]" :value="currencyId"/>
<input
:title="$t('firefly.amount')"
autocomplete="off"
:class="errors.length > 0 ? 'form-control is-invalid' : 'form-control'"
name="amount[]"
type="number"
v-model="amount"
v-model="transactionAmount"
:placeholder="$t('firefly.amount')"
>
</div>
<span v-if="errors.length > 0">
<span v-for="error in errors" class="text-danger small">{{ error }}<br/></span>
</span>
</div>
</div>
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
//const {mapRootState, mapRootGetters, mapRootActions, mapRootMutations} = createHelpers('');
export default {
name: "TransactionAmount",
props: ['index', 'errors'],
props: [
'index', 'errors', 'amount', 'transactionType',
'sourceCurrencySymbol',
'destinationCurrencySymbol',
],
data() {
return {
currencySymbol: ''
transactionAmount: this.amount,
currencySymbol: null,
srcCurrencySymbol: this.sourceCurrencySymbol,
dstCurrencySymbol: this.destinationCurrencySymbol,
}
},
watch: {
transactionType: function (value) {
switch (value) {
case 'Transfer':
case 'Withdrawal':
// take currency from source:
this.currencyId = this.transactions[this.index].source_account.currency_id;
this.currencySymbol = this.transactions[this.index].source_account.currency_symbol;
return;
case 'Deposit':
// take currency from destination:
this.currencyId = this.transactions[this.index].destination_account.currency_id;
this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
return;
}
transactionAmount: function (value) {
this.$emit('set-amount', value);
},
destinationAllowedTypes: function (value) {
// aka source was updated. if source is asset/loan/debt/mortgage use it to set the currency:
if ('undefined' !== typeof this.transactions[this.index].source_account.type) {
if (['Asset account', 'Loan', 'Debt', 'Mortgage'].indexOf(this.transactions[this.index].source_account.type) !== -1) {
// get currency pref from source account
this.currencyId = this.transactions[this.index].source_account.currency_id;
this.currencySymbol = this.transactions[this.index].source_account.currency_symbol;
}
}
amount: function(value) {
this.transactionAmount = value;
},
sourceAllowedTypes: function (value) {
// aka destination was updated. if destination is asset/loan/debt/mortgage use it to set the currency:
// unless its already known to be a transfer
if ('undefined' !== typeof this.transactions[this.index].destination_account.type && 'Transfer' !== this.transactionType) {
if (['Asset account', 'Loan', 'Debt', 'Mortgage'].indexOf(this.transactions[this.index].destination_account.type) !== -1) {
// get currency pref from destination account
this.currencyId = this.transactions[this.index].destination_account.currency_id;
this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
}
}
sourceCurrencySymbol: function (value) {
this.srcCurrencySymbol = value;
},
destinationCurrencySymbol: function (value) {
this.dstCurrencySymbol = value;
},
},
created: function () {
this.updateCurrency();
},
methods: {
...mapMutations(
[
'updateField',
],
),
updateCurrency: function () {
if (0 === this.currencyId) {
// use default currency from store.
this.currencySymbol = this.currencyPreference.symbol;
this.currencyId = this.currencyPreference.id;
}
}
},
computed: {
currencyPreference: {
get() {
return this.$store.state.currencyPreference;
}
transactionType: function(value) {
switch (value) {
case 'Transfer':
case 'Withdrawal':
this.currencySymbol =this.srcCurrencySymbol;
break;
case 'Deposit':
this.currencySymbol =this.dstCurrencySymbol;
}
},
...mapGetters([
'transactionType',
'transactions',
'destinationAllowedTypes',
'sourceAllowedTypes',
]),
amount: {
get() {
return this.transactions[this.index].amount;
},
set(value) {
this.updateField({field: 'amount', index: this.index, value: value});
}
},
currencyId: {
get() {
return this.transactions[this.index].currency_id;
},
set(value) {
this.updateField({field: 'currency_id', index: this.index, value: value});
}
},
selectedTransactionType: {
get() {
return this.transactionType;
},
set(value) {
// console.log('set selectedAccount for ' + this.direction);
// console.log(value);
// this.updateField({field: this.accountKey, index: this.index, value: value});
}
}
}
},
}
</script>

View File

@@ -50,6 +50,8 @@ export default {
},
transaction_journal_id: function (value) {
if (!this.showField) {
console.log('Field is hidden. Emit event!');
this.$emit('uploaded-attachments', value);
return;
}
// console.log('transaction_journal_id changed to ' + value);

View File

@@ -44,11 +44,6 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['value', 'index', 'errors'],
name: "TransactionBill",
@@ -62,11 +57,6 @@ export default {
this.collectData();
},
methods: {
...mapMutations(
[
'updateField',
],
),
collectData() {
this.billList.push(
{
@@ -99,17 +89,9 @@ export default {
},
watch: {
bill: function (value) {
this.updateField({field: 'bill_id', index: this.index, value: value});
this.$emit('set-bill', value);
}
},
computed: {
...mapGetters(
[
'transactionType',
'transactions',
]
)
}
}
</script>

View File

@@ -43,11 +43,6 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'value', 'errors'],
name: "TransactionBudget",
@@ -61,11 +56,6 @@ export default {
this.collectData();
},
methods: {
...mapMutations(
[
'updateField',
],
),
collectData() {
this.budgetList.push(
{
@@ -98,16 +88,8 @@ export default {
},
watch: {
budget: function (value) {
this.updateField({field: 'budget_id', index: this.index, value: value});
this.$emit('set-budget', value);
}
},
computed: {
...mapGetters(
[
'transactionType',
'transactions',
]
)
}
}
</script>

View File

@@ -50,12 +50,9 @@
<script>
import {createNamespacedHelpers} from "vuex";
import VueTypeaheadBootstrap from 'vue-typeahead-bootstrap';
import {debounce} from "lodash";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['value', 'index', 'errors'],
components: {VueTypeaheadBootstrap},
@@ -79,11 +76,6 @@ export default {
},
methods: {
...mapMutations(
[
'updateField',
],
),
clearCategory: function () {
this.category = null;
},
@@ -101,16 +93,10 @@ export default {
},
watch: {
category: function (value) {
this.updateField({field: 'category', index: this.index, value: value});
this.$emit('set-category', value);
}
},
computed: {
...mapGetters(
[
'transactionType',
'transactions',
]
),
selectedCategory: {
get() {
return this.categories[this.index].name;

View File

@@ -43,37 +43,48 @@
</template>
<script>
// TODO: error handling
// TODO dont use store?
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
name: "TransactionCustomDates",
props: ['index', 'errors', 'customFields'],
props: [
'index',
'errors',
'customFields',
'interestDate',
'bookDate',
'processDate',
'dueDate',
'paymentDate',
'invoiceDate'
],
data() {
return {
dateFields: ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'],
availableFields: this.customFields
availableFields: this.customFields,
dates: {
interest_date: this.interestDate,
book_date: this.bookDate,
process_date: this.processDate,
due_date: this.dueDate,
payment_date: this.paymentDate,
invoice_date: this.invoiceDate,
}
,
}
},
watch: {
customFields: function(value) {
customFields: function (value) {
this.availableFields = value;
}
},
methods: {
...mapGetters(['transactions']),
...mapMutations(['updateField',],
),
isDateField: function (name) {
return this.dateFields.includes(name)
},
getFieldValue(field) {
return this.transactions()[parseInt(this.index)][field] ?? '';
return this.dates[field] ?? '';
},
setFieldValue(event, field) {
this.updateField({index: this.index, field: field, value: event.target.value});
this.$emit('set-custom-date', { field: field, date: event.target.value});
},
}
}

View File

@@ -29,22 +29,22 @@
type="date"
ref="date"
:title="$t('firefly.date')"
v-model="localDate"
v-model="dateStr"
:disabled="index > 0"
autocomplete="off"
name="date[]"
:placeholder="localDate"
:placeholder="dateStr"
>
<input
:class="errors.length > 0 ? 'form-control is-invalid' : 'form-control'"
type="time"
ref="time"
:title="$t('firefly.time')"
v-model="localTime"
v-model="timeStr"
:disabled="index > 0"
autocomplete="off"
name="time[]"
:placeholder="localTime"
:placeholder="timeStr"
>
</div>
<span v-if="errors.length > 0">
@@ -55,71 +55,59 @@
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'errors'],
props: ['index', 'errors', 'date', 'time'],
name: "TransactionDate",
methods: {
...mapMutations(
[
'updateField',
'setDate'
],
),
data() {
return {
localDate: this.date,
localTime: this.time
}
},
methods: {},
computed: {
...mapGetters(
[
'transactionType',
'date',
'transactions'
]
),
localDate: {
dateStr: {
get() {
if (this.date instanceof Date && !isNaN(this.date)) {
return this.date.toISOString().split('T')[0];
if (this.localDate instanceof Date && !isNaN(this.localDate)) {
return this.localDate.toISOString().split('T')[0];
}
return '';
},
set(value) {
// bit of a hack but meh.
if('' === value) {
if ('' === value) {
// reset to today
this.localDate = new Date();
this.$emit('set-date', {date: this.localDate});
return;
}
let newDate = new Date(value);
let current = new Date(this.date.getTime());
current.setFullYear(newDate.getFullYear());
current.setMonth(newDate.getMonth());
current.setDate(newDate.getDate());
this.setDate({date: current});
this.localDate = new Date(value);
this.$emit('set-date', {date: this.localDate});
}
},
localTime: {
timeStr: {
get() {
if (this.date instanceof Date && !isNaN(this.date)) {
return ('0' + this.date.getHours()).slice(-2) + ':' + ('0' + this.date.getMinutes()).slice(-2) + ':' + ('0' + this.date.getSeconds()).slice(-2);
if (this.localTime instanceof Date && !isNaN(this.localTime)) {
return ('0' + this.localTime.getHours()).slice(-2) + ':' + ('0' + this.localTime.getMinutes()).slice(-2) + ':' + ('0' + this.localTime.getSeconds()).slice(-2);
}
return '';
},
set(value) {
if('' === value) {
this.date.setHours(0);
this.date.setMinutes(0);
this.date.setSeconds(0);
this.setDate({date: this.date});
if ('' === value) {
this.localTime.setHours(0);
this.localTime.setMinutes(0);
this.localTime.setSeconds(0);
this.$emit('set-time', {time: this.localTime});
return;
}
// bit of a hack but meh.
let current = new Date(this.date.getTime());
let current = new Date(this.localTime.getTime());
let parts = value.split(':');
current.setHours(parseInt(parts[0]));
current.setMinutes(parseInt(parts[1]));
current.setSeconds(parseInt(parts[2]));
this.setDate({date: current});
this.localTime = current;
this.$emit('set-time', {time: this.localTime});
}
}
}

View File

@@ -46,12 +46,9 @@
<script>
import {createNamespacedHelpers} from "vuex";
import VueTypeaheadBootstrap from 'vue-typeahead-bootstrap';
import {debounce} from "lodash";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'value', 'errors'],
components: {VueTypeaheadBootstrap},
@@ -72,11 +69,6 @@ export default {
},
methods: {
...mapMutations(
[
'updateField',
],
),
clearDescription: function () {
this.description = '';
},
@@ -94,16 +86,9 @@ export default {
},
watch: {
description: function (value) {
this.updateField({field: 'description', index: this.index, value: value});
this.$emit('set-description', value);
//
}
},
computed: {
...mapGetters(
[
'transactionType',
'transactions',
]
)
}
}
</script>

View File

@@ -39,10 +39,6 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'value', 'errors', 'customFields'],
name: "TransactionExternalUrl",
@@ -61,18 +57,13 @@ export default {
}
},
methods: {
...mapMutations(
[
'updateField',
],
),
},
watch: {
customFields: function (value) {
this.availableFields = value;
},
url: function (value) {
this.updateField({field: 'external_url', index: this.index, value: value});
this.$emit('set-external-url', value);
}
}
}

View File

@@ -20,15 +20,13 @@
<template>
<!-- FOREIGN AMOUNT -->
<div class="form-group">
<input type="hidden" name="foreign_currency_id[]" :value="currencyId"/>
<div class="form-group" v-if="isVisible">
<div class="text-xs">{{ $t('form.foreign_amount') }}</div>
<div class="input-group">
<input
:title="$t('form.foreign_amount')"
autocomplete="off"
:class="errors.length > 0 ? 'form-control is-invalid' : 'form-control'"
:disabled="0===currencyId"
name="foreign_amount[]"
type="number"
v-model="amount"
@@ -42,117 +40,34 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
//const {mapRootState, mapRootGetters, mapRootActions, mapRootMutations} = createHelpers('');
export default {
name: "TransactionForeignAmount",
props: ['index','errors'],
props: [
'index',
'errors',
'transactionType',
'sourceCurrencyId',
'destinationCurrencyId'
],
data() {
return {
currencySymbol: '',
allCurrencies: [],
selectableCurrencies: [],
amount: ''
// currencySymbol: '',
// allCurrencies: [],
// selectableCurrencies: [],
}
},
watch: {
transactionType: function (value) {
// switch (value) {
// case 'Transfer':
// case 'Withdrawal':
// // take currency from source:
// //this.currencyId = this.transactions[this.index].source_account.currency_id;
// this.currencySymbol = this.transactions[this.index].source_account.currency_symbol;
// return;
// case 'Deposit':
// // take currency from destination:
// this.currencyId = this.transactions[this.index].destination_account.currency_id;
// this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
// return;
// }
},
destinationAllowedTypes: function (value) {
// // aka source was updated. if source is asset/loan/debt/mortgage use it to set the currency:
// if ('undefined' !== typeof this.transactions[this.index].source_account.type) {
// if (['Asset account', 'Loan', 'Debt', 'Mortgage'].indexOf(this.transactions[this.index].source_account.type) !== -1) {
// // get currency pref from source account
// this.currencyId = this.transactions[this.index].source_account.currency_id;
// this.currencySymbol = this.transactions[this.index].source_account.currency_symbol;
// }
// }
},
sourceAllowedTypes: function (value) {
// // aka destination was updated. if destination is asset/loan/debt/mortgage use it to set the currency:
// // unless its already known to be a transfer
// if ('undefined' !== typeof this.transactions[this.index].destination_account.type && 'Transfer' !== this.transactionType) {
// if (['Asset account', 'Loan', 'Debt', 'Mortgage'].indexOf(this.transactions[this.index].destination_account.type) !== -1) {
// // get currency pref from destination account
// this.currencyId = this.transactions[this.index].destination_account.currency_id;
// this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
// }
// }
},
},
created: function () {
},
methods: {
...mapMutations(
[
'updateField',
],
),
// updateCurrency: function () {
// if (0 === this.currencyId) {
// // use default currency from store.
// this.currencySymbol = this.currencyPreference.symbol;
// this.currencyId = this.currencyPreference.id;
// }
// }
amount: function(value) {
this.$emit('set-foreign-amount', value);
}
},
computed: {
currencyPreference: {
isVisible: {
get() {
return this.$store.state.currencyPreference;
return !('Transfer' === this.transactionType && this.sourceCurrencyId === this.destinationCurrencyId);
}
},
...mapGetters([
'transactionType',
'transactions',
'destinationAllowedTypes',
'sourceAllowedTypes',
]),
amount: {
get() {
return this.transactions[this.index].foreign_amount;
},
set(value) {
this.updateField({field: 'foreign_amount', index: this.index, value: value});
}
},
currencyId: {
get() {
return this.transactions[this.index].foreign_currency_id;
},
set(value) {
this.updateField({field: 'foreign_currency_id', index: this.index, value: value});
}
},
selectedTransactionType: {
get() {
return this.transactionType;
},
set(value) {
// console.log('set selectedAccount for ' + this.direction);
// console.log(value);
// this.updateField({field: this.accountKey, index: this.index, value: value});
}
}
}
}
</script>

View File

@@ -20,10 +20,10 @@
<template>
<!-- FOREIGN Currency -->
<div class="form-group" v-if="selectIsVisible">
<div class="form-group" v-if="isVisible">
<div class="text-xs">&nbsp;</div>
<div class="input-group">
<select name="foreign_currency_id[]" v-model="currencyId" class="form-control">
<select name="foreign_currency_id[]" v-model="selectedCurrency" class="form-control">
<option v-for="currency in selectableCurrencies" :label="currency.name" :value="currency.id">{{ currency.name }}</option>
</select>
</div>
@@ -31,77 +31,48 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
name: "TransactionForeignCurrency",
props: ['index'],
props: [
'index',
'transactionType',
'sourceCurrencyId',
'destinationCurrencyId',
'selectedCurrencyId'
],
data() {
return {
selectedCurrency: 0,
allCurrencies: [],
selectableCurrencies: [],
dstCurrencyId: this.destinationCurrencyId,
srcCurrencyId: this.sourceCurrencyId,
lockedCurrency: 0,
selectIsVisible: true
}
},
watch: {
sourceCurrencyId: function (value) {
this.srcCurrencyId = value;
},
destinationCurrencyId: function (value) {
this.dstCurrencyId = value;
},
selectedCurrency: function(value) {
this.$emit('set-foreign-currency-id', value);
},
transactionType: function (value) {
this.lockedCurrency = 0;
if ('Transfer' === value) {
// take currency from destination:
this.currencyId = this.transactions[this.index].destination_account.currency_id;
this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
this.lockedCurrency = this.currencyId;
this.lockedCurrency = this.dstCurrencyId;
this.selectedCurrency = this.dstCurrencyId;
}
this.filterCurrencies();
this.checkVisibility();
},
destinationAllowedTypes: function (value) {
this.lockedCurrency = 0;
if ('Transfer' === this.transactionType) {
// take currency from destination:
this.currencyId = this.transactions[this.index].destination_account.currency_id;
this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
this.lockedCurrency = this.currencyId;
}
this.filterCurrencies();
this.checkVisibility();
},
sourceAllowedTypes: function (value) {
this.lockedCurrency = 0;
if ('Transfer' === this.transactionType) {
// take currency from destination:
this.currencyId = this.transactions[this.index].destination_account.currency_id;
this.currencySymbol = this.transactions[this.index].destination_account.currency_symbol;
this.lockedCurrency = this.currencyId;
}
this.filterCurrencies();
this.checkVisibility();
},
},
created: function () {
this.getAllCurrencies();
},
methods: {
...mapMutations(
[
'updateField',
],
),
checkVisibility: function () {
// have the same currency ID, but not zero, and is a transfer
let sourceId = this.transactions[this.index].source_account.currency_id;
let destId = this.transactions[this.index].destination_account.currency_id;
this.selectIsVisible = true;
if (sourceId === destId && 0 !== sourceId && 'Transfer' === this.transactionType) {
this.selectIsVisible = false;
this.currencyId = 0;
}
},
getAllCurrencies: function () {
axios.get('./api/v1/autocomplete/currencies')
.then(response => {
@@ -119,14 +90,13 @@ export default {
let current = this.allCurrencies[key];
if (current.id === this.lockedCurrency) {
this.selectableCurrencies = [current];
this.currencyId = current.id;
this.selectedCurrency = current.id;
}
}
}
return;
}
this.selectableCurrencies = [
{
"id": 0,
@@ -136,62 +106,15 @@ export default {
for (let key in this.allCurrencies) {
if (this.allCurrencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
let current = this.allCurrencies[key];
// add to array if not "locked" in place:
if (this.transactions[this.index].currency_id !== current.id) {
this.selectableCurrencies.push(current);
}
// deselect impossible currency.
if (this.transactions[this.index].currency_id === current.id && this.currencyId === current.id) {
this.currencyId = 0;
}
this.selectableCurrencies.push(current);
}
}
//currency_id
// always add empty currency:
// this.selectableCurrencies = this.allCurrencies;
// this.selectableCurrencies.reverse();
// this.selectableCurrencies.push(
// ;
// this.selectableCurrencies.reverse();
// remove
}
// updateCurrency: function () {
// if (0 === this.currencyId) {
// // use default currency from store.
// this.currencySymbol = this.currencyPreference.symbol;
// this.currencyId = this.currencyPreference.id;
// }
// }
},
computed: {
currencyPreference: {
get() {
return this.$store.state.currencyPreference;
}
},
...mapGetters([
'transactionType',
'transactions',
'destinationAllowedTypes',
'sourceAllowedTypes',
]),
currencyId: {
get() {
return this.transactions[this.index].foreign_currency_id;
},
set(value) {
this.updateField({field: 'foreign_currency_id', index: this.index, value: value});
}
},
normalCurrencyId: {
get() {
return this.transactions[this.index].currency_id;
},
},
isVisible: function () {
return !('Transfer' === this.transactionType && this.srcCurrencyId === this.dstCurrencyId);
}
}
}
</script>

View File

@@ -39,10 +39,6 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'value', 'errors', 'customFields'],
name: "TransactionInternalReference",
@@ -61,18 +57,13 @@ export default {
}
},
methods: {
...mapMutations(
[
'updateField',
],
),
},
watch: {
customFields: function (value) {
this.availableFields = value;
},
reference: function (value) {
this.updateField({field: 'internal_reference', index: this.index, value: value});
this.$emit('set-internal-reference', value);
}
}
}

View File

@@ -184,10 +184,6 @@
</template>
<script>
import {createNamespacedHelpers} from 'vuex'
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
const lodashClonedeep = require('lodash.clonedeep');
// TODO error handling
export default {
@@ -220,18 +216,15 @@ export default {
},
watch: {
links: function (value) {
this.updateField({index: this.index, field: 'links', value: lodashClonedeep(value)});
// TODO
this.$emit('set-links', lodashClonedeep(value));
//this.updateField({index: this.index, field: 'links', value: lodashClonedeep(value)});
},
customFields: function (value) {
this.availableFields = value;
}
},
methods: {
...mapMutations(
[
'updateField',
],
),
getTextForLinkType: function (linkTypeId) {
let parts = linkTypeId.split('-');
for (let i in this.linkTypes) {

View File

@@ -40,6 +40,7 @@
<button class="btn btn-default btn-xs" @click="clearLocation">{{ $t('firefly.clear_location') }}</button>
</span>
</div>
<p>&nbsp;</p>
</div>
</template>

View File

@@ -36,10 +36,6 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'value', 'errors', 'customFields'],
name: "TransactionNotes",
@@ -57,19 +53,12 @@ export default {
return false;
}
},
methods: {
...mapMutations(
[
'updateField',
],
),
},
watch: {
customFields: function (value) {
this.availableFields = value;
},
notes: function (value) {
this.updateField({field: 'notes', index: this.index, value: value});
this.$emit('set-notes', value);
}
}
}

View File

@@ -45,10 +45,6 @@
<script>
import {createNamespacedHelpers} from "vuex";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
props: ['index', 'value', 'errors'],
name: "TransactionPiggyBank",
@@ -62,11 +58,6 @@ export default {
this.collectData();
},
methods: {
...mapMutations(
[
'updateField',
],
),
collectData() {
this.piggyList.push(
{
@@ -99,14 +90,8 @@ export default {
},
watch: {
piggy_bank_id: function (value) {
this.updateField({field: 'piggy_bank_id', index: this.index, value: value});
this.$emit('set-piggy-bank', value);
}
},
computed: {
...mapGetters([
'transactionType',
'transactions',
])
}
}
</script>

View File

@@ -41,12 +41,9 @@
</template>
<script>
import {createNamespacedHelpers} from "vuex";
import VueTagsInput from "@johmun/vue-tags-input";
import axios from "axios";
const {mapState, mapGetters, mapActions, mapMutations} = createNamespacedHelpers('transactions/create')
export default {
name: "TransactionTags",
components: {
@@ -66,14 +63,12 @@ export default {
watch: {
'currentTag': 'initItems',
tagList: function (value) {
this.updateField({field: 'tags', index: this.index, value: value});
this.$emit('set-tags', value);
this.updateTags = false;
this.tags = value;
},
tags: function (value) {
if (this.updateTags) {
//console.log('watch: tags');
let shortList = [];
for (let key in value) {
if (value.hasOwnProperty(key)) {
@@ -86,11 +81,6 @@ export default {
}
},
methods: {
...mapMutations(
[
'updateField',
],
),
initItems() {
if (this.currentTag.length < 2) {
return;

View File

@@ -73,9 +73,9 @@
"create_another": "Nach dem Speichern hierher zur\u00fcckkehren, um ein weiteres zu erstellen.",
"reset_after": "Formular nach der \u00dcbermittlung zur\u00fccksetzen",
"bill_paid_on": "Bezahlt am {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "Die erste Aufteilung bestimmt den Wert dieses Feldes",
"first_split_overrules_source": "Die erste Aufteilung k\u00f6nnte das Quellkonto \u00fcberschreiben",
"first_split_overrules_destination": "Die erste Aufteilung k\u00f6nnte das Zielkonto \u00fcberschreiben",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Buchung #{ID} (\"{title}\")<\/a> wurde gespeichert.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",

View File

@@ -73,9 +73,9 @@
"create_another": "Apr\u00e8s enregistrement, revenir ici pour en cr\u00e9er un nouveau.",
"reset_after": "R\u00e9initialiser le formulaire apr\u00e8s soumission",
"bill_paid_on": "Pay\u00e9 le {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "La premi\u00e8re ventilation d\u00e9termine la valeur de ce champ",
"first_split_overrules_source": "La premi\u00e8re ventilation peut remplacer le compte source",
"first_split_overrules_destination": "La premi\u00e8re ventilation peut remplacer le compte de destination",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">L'op\u00e9ration n\u00b0{ID} (\"{title}\")<\/a> a \u00e9t\u00e9 enregistr\u00e9e.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",

View File

@@ -73,9 +73,9 @@
"create_another": "Dopo il salvataggio, torna qui per crearne un'altra.",
"reset_after": "Resetta il modulo dopo l'invio",
"bill_paid_on": "Pagata il {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "La prima suddivisione determina il valore di questo campo",
"first_split_overrules_source": "La prima suddivisione potrebbe sovrascrivere l'account di origine",
"first_split_overrules_destination": "La prima suddivisione potrebbe sovrascrivere l'account di destinazione",
"transaction_stored_link": "La <a href=\"transactions\/show\/{ID}\">transazione #{ID} (\"{title}\")<\/a> \u00e8 stata salvata.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",

View File

@@ -73,13 +73,13 @@
"create_another": "Terug naar deze pagina voor een nieuwe transactie.",
"reset_after": "Reset formulier na opslaan",
"bill_paid_on": "Betaald op {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "De eerste split bepaalt wat hier staat",
"first_split_overrules_source": "De eerste split kan de bronrekening overschrijven",
"first_split_overrules_destination": "De eerste split kan de doelrekening overschrijven",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transactie #{ID} (\"{title}\")<\/a> is opgeslagen.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",
"select_period": "Select a period",
"custom_period": "Aangepaste periode",
"reset_to_current": "Reset naar huidige periode",
"select_period": "Selecteer een periode",
"location": "Plaats",
"other_budgets": "Aangepaste budgetten",
"journal_links": "Transactiekoppelingen",

View File

@@ -73,9 +73,9 @@
"create_another": "Po zapisaniu wr\u00f3\u0107 tutaj, aby utworzy\u0107 kolejny.",
"reset_after": "Wyczy\u015b\u0107 formularz po zapisaniu",
"bill_paid_on": "Zap\u0142acone {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "Pierwszy podzia\u0142 okre\u015bla warto\u015b\u0107 tego pola",
"first_split_overrules_source": "Pierwszy podzia\u0142 mo\u017ce nadpisa\u0107 konto \u017ar\u00f3d\u0142owe",
"first_split_overrules_destination": "Pierwszy podzia\u0142 mo\u017ce nadpisa\u0107 konto docelowe",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transakcja #{ID} (\"{title}\")<\/a> zosta\u0142a zapisana.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",

View File

@@ -16,12 +16,12 @@
"transaction_journal_extra": "Informa\u00e7\u00e3o extra",
"transaction_journal_meta": "Meta-informa\u00e7\u00e3o",
"basic_journal_information": "Informa\u00e7\u00f5es b\u00e1sicas de transa\u00e7\u00e3o",
"bills_to_pay": "Faturas a pagar",
"bills_to_pay": "Contas a pagar",
"left_to_spend": "Restante para gastar",
"attachments": "Anexos",
"net_worth": "Valor L\u00edquido",
"bill": "Fatura",
"no_bill": "(sem fatura)",
"no_bill": "(sem conta)",
"tags": "Tags",
"internal_reference": "Refer\u00eancia interna",
"external_url": "URL externa",
@@ -41,11 +41,11 @@
"categories": "Categorias",
"go_to_budgets": "V\u00e1 para seus or\u00e7amentos",
"income": "Receita \/ Renda",
"go_to_deposits": "Ir para os dep\u00f3sitos",
"go_to_deposits": "Ir para as entradas",
"go_to_categories": "V\u00e1 para suas categorias",
"expense_accounts": "Contas de despesas",
"go_to_expenses": "Ir para despesas",
"go_to_bills": "V\u00e1 para suas faturas",
"go_to_bills": "V\u00e1 para suas contas",
"bills": "Faturas",
"go_to_piggies": "V\u00e1 para sua poupan\u00e7a",
"saved": "Salvo",
@@ -73,15 +73,15 @@
"create_another": "Depois de armazenar, retorne aqui para criar outro.",
"reset_after": "Resetar o formul\u00e1rio ap\u00f3s o envio",
"bill_paid_on": "Pago em {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "A primeira divis\u00e3o determina o valor deste campo",
"first_split_overrules_source": "A primeira divis\u00e3o pode anular a conta de origem",
"first_split_overrules_destination": "A primeira divis\u00e3o pode anular a conta de destino",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transa\u00e7\u00e3o #{ID} (\"{title}\")<\/a> foi salva.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",
"select_period": "Select a period",
"location": "Localiza\u00e7\u00e3o",
"other_budgets": "Custom timed budgets",
"other_budgets": "Or\u00e7amentos de per\u00edodos personalizados",
"journal_links": "Transa\u00e7\u00f5es ligadas",
"go_to_withdrawals": "V\u00e1 para seus saques",
"revenue_accounts": "Contas de receitas",

View File

@@ -73,9 +73,9 @@
"create_another": "Depois de guardar, voltar aqui para criar outra.",
"reset_after": "Repor o formul\u00e1rio ap\u00f3s o envio",
"bill_paid_on": "Pago a {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "A primeira divis\u00e3o determina o valor deste campo",
"first_split_overrules_source": "A primeira divis\u00e3o pode anular a conta de origem",
"first_split_overrules_destination": "A primeira divis\u00e3o pode anular a conta de destino",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transa\u00e7\u00e3o #{ID} (\"{title}\")<\/a> foi guardada.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",

View File

@@ -73,9 +73,9 @@
"create_another": "\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0441\u044e\u0434\u0430 \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c.",
"reset_after": "\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0443 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438",
"bill_paid_on": "\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u043e {date}",
"first_split_decides": "The first split determines the value of this field",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"first_split_decides": "\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u043b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438",
"first_split_overrules_source": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0447\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430",
"first_split_overrules_destination": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0447\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f #{ID} (\"{title}\")<\/a> \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0430.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",

View File

@@ -3,88 +3,88 @@
"Transfer": "\u8f6c\u5e10",
"Withdrawal": "\u63d0\u6b3e",
"Deposit": "\u5b58\u6b3e",
"date_and_time": "Date and time",
"date_and_time": "\u65e5\u671f\u548c\u65f6\u95f4",
"no_currency": "(\u6ca1\u6709\u8d27\u5e01)",
"date": "\u65e5\u671f",
"time": "Time",
"time": "\u65f6\u95f4",
"no_budget": "(\u65e0\u9884\u7b97)",
"destination_account": "\u76ee\u6807\u5e10\u6237",
"source_account": "\u6765\u6e90\u5e10\u6237",
"single_split": "Split",
"create_new_transaction": "\u65b0\u5efa\u4ea4\u6613",
"destination_account": "\u76ee\u6807\u8d26\u6237",
"source_account": "\u6765\u6e90\u8d26\u6237",
"single_split": "\u62c6\u5206",
"create_new_transaction": "\u521b\u5efa\u65b0\u4ea4\u6613",
"balance": "\u4f59\u989d",
"transaction_journal_extra": "Extra information",
"transaction_journal_meta": "\u540e\u8bbe\u8d44\u8baf",
"basic_journal_information": "Basic transaction information",
"bills_to_pay": "\u5f85\u4ed8\u5e10\u5355",
"transaction_journal_extra": "\u989d\u5916\u4fe1\u606f",
"transaction_journal_meta": "\u5143\u4fe1\u606f",
"basic_journal_information": "\u57fa\u7840\u4ea4\u6613\u4fe1\u606f",
"bills_to_pay": "\u5f85\u4ed8\u8d26\u5355",
"left_to_spend": "\u5269\u4f59\u53ef\u82b1\u8d39",
"attachments": "\u9644\u52a0\u6863\u6848",
"net_worth": "\u51c0\u503c",
"bill": "\u5e10\u5355",
"no_bill": "(no bill)",
"attachments": "\u9644\u4ef6",
"net_worth": "\u51c0\u8d44\u4ea7",
"bill": "\u8d26\u5355",
"no_bill": "(\u65e0\u8d26\u5355)",
"tags": "\u6807\u7b7e",
"internal_reference": "\u5185\u90e8\u53c2\u8003",
"internal_reference": "\u5185\u90e8\u5f15\u7528",
"external_url": "\u5916\u90e8\u94fe\u63a5",
"no_piggy_bank": "\uff08\u65e0\u5b58\u94b1\u7f50\uff09",
"no_piggy_bank": "(\u65e0\u5b58\u94b1\u7f50)",
"paid": "\u5df2\u4ed8\u6b3e",
"notes": "\u6ce8\u91ca",
"yourAccounts": "\u60a8\u7684\u5e10\u6237",
"go_to_asset_accounts": "\u68c0\u89c6\u60a8\u7684\u8d44\u4ea7\u5e10\u6237",
"transaction_table_description": "A table containing your transactions",
"account": "\u5e10\u6237",
"notes": "\u5907\u6ce8",
"yourAccounts": "\u60a8\u7684\u8d26\u6237",
"go_to_asset_accounts": "\u67e5\u770b\u60a8\u7684\u8d44\u4ea7\u8d26\u6237",
"transaction_table_description": "\u5305\u542b\u60a8\u4ea4\u6613\u7684\u8868\u683c",
"account": "\u8d26\u6237",
"description": "\u63cf\u8ff0",
"amount": "\u91d1\u989d",
"budget": "\u9884\u7b97",
"category": "\u5206\u7c7b",
"opposing_account": "Opposing account",
"opposing_account": "\u5bf9\u65b9\u8d26\u6237",
"budgets": "\u9884\u7b97",
"categories": "\u5206\u7c7b",
"go_to_budgets": "\u524d\u5f80\u60a8\u7684\u9884\u7b97",
"income": "\u6536\u5165 \/ \u6240\u5f97",
"go_to_deposits": "Go to deposits",
"income": "\u6536\u76ca \/ \u6536\u5165",
"go_to_deposits": "\u524d\u5f80\u5b58\u6b3e",
"go_to_categories": "\u524d\u5f80\u60a8\u7684\u5206\u7c7b",
"expense_accounts": "\u652f\u51fa\u5e10\u6237",
"go_to_expenses": "Go to expenses",
"go_to_bills": "\u524d\u5f80\u60a8\u7684\u5e10\u5355",
"bills": "\u5e10\u5355",
"expense_accounts": "\u652f\u51fa\u8d26\u6237",
"go_to_expenses": "\u524d\u5f80\u652f\u51fa",
"go_to_bills": "\u524d\u5f80\u8d26\u5355",
"bills": "\u8d26\u5355",
"go_to_piggies": "\u524d\u5f80\u60a8\u7684\u5b58\u94b1\u7f50",
"saved": "\u5df2\u4fdd\u5b58",
"piggy_banks": "\u5b58\u94b1\u7f50",
"piggy_bank": "\u5b58\u94b1\u7f50",
"amounts": "Amounts",
"Default asset account": "\u9884\u8bbe\u8d44\u4ea7\u5e10\u6237",
"account_role_defaultAsset": "\u9884\u8bbe\u8d44\u4ea7\u5e10\u6237",
"account_role_savingAsset": "\u50a8\u84c4\u5e10\u6237",
"account_role_sharedAsset": "\u5171\u7528\u8d44\u4ea7\u5e10\u6237",
"amounts": "\u91d1\u989d",
"Default asset account": "\u9ed8\u8ba4\u8d44\u4ea7\u8d26\u6237",
"account_role_defaultAsset": "\u9ed8\u8ba4\u8d44\u4ea7\u8d26\u6237",
"account_role_savingAsset": "\u50a8\u84c4\u8d26\u6237",
"account_role_sharedAsset": "\u5171\u7528\u8d44\u4ea7\u8d26\u6237",
"clear_location": "\u6e05\u9664\u4f4d\u7f6e",
"account_role_ccAsset": "\u4fe1\u7528\u5361",
"account_role_cashWalletAsset": "\u73b0\u91d1\u94b1\u5305",
"daily_budgets": "Daily budgets",
"weekly_budgets": "Weekly budgets",
"monthly_budgets": "Monthly budgets",
"quarterly_budgets": "Quarterly budgets",
"half_year_budgets": "Half-yearly budgets",
"yearly_budgets": "Yearly budgets",
"daily_budgets": "\u6bcf\u65e5\u9884\u7b97",
"weekly_budgets": "\u6bcf\u5468\u9884\u7b97",
"monthly_budgets": "\u6bcf\u6708\u9884\u7b97",
"quarterly_budgets": "\u6bcf\u5b63\u5ea6\u9884\u7b97",
"half_year_budgets": "\u6bcf\u534a\u5e74\u9884\u7b97",
"yearly_budgets": "\u6bcf\u5e74\u9884\u7b97",
"split_transaction_title": "\u62c6\u5206\u4ea4\u6613\u7684\u63cf\u8ff0",
"errors_submission": "There was something wrong with your submission. Please check out the errors.",
"errors_submission": "\u60a8\u63d0\u4ea4\u7684\u5185\u5bb9\u6709\u8bef\uff0c\u8bf7\u68c0\u67e5\u9519\u8bef\u4fe1\u606f\u3002",
"flash_error": "\u9519\u8bef\uff01",
"store_transaction": "Store transaction",
"store_transaction": "\u4fdd\u5b58\u4ea4\u6613",
"flash_success": "\u6210\u529f\uff01",
"create_another": "\u4fdd\u5b58\u540e\uff0c\u8fd4\u56de\u6b64\u9875\u9762\u521b\u5efa\u53e6\u4e00\u7b14\u8bb0\u5f55\u3002",
"create_another": "\u4fdd\u5b58\u540e\uff0c\u8fd4\u56de\u6b64\u9875\u9762\u4ee5\u521b\u5efa\u65b0\u8bb0\u5f55",
"reset_after": "\u63d0\u4ea4\u540e\u91cd\u7f6e\u8868\u5355",
"bill_paid_on": "Paid on {date}",
"first_split_decides": "The first split determines the value of this field",
"bill_paid_on": "\u652f\u4ed8\u4e8e {date}",
"first_split_decides": "\u9996\u6b21\u62c6\u5206\u51b3\u5b9a\u6b64\u5b57\u6bb5\u7684\u503c",
"first_split_overrules_source": "The first split may overrule the source account",
"first_split_overrules_destination": "The first split may overrule the destination account",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID} (\"{title}\")<\/a> has been stored.",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">\u4ea4\u6613 #{ID} (\u201c{title}\u201d)<\/a> \u5df2\u4fdd\u5b58\u3002",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",
"select_period": "Select a period",
"location": "\u4f4d\u7f6e",
"other_budgets": "Custom timed budgets",
"journal_links": "\u4ea4\u6613\u8fde\u7ed3",
"go_to_withdrawals": "Go to your withdrawals",
"revenue_accounts": "\u6536\u5165\u5e10\u6237",
"other_budgets": "\u81ea\u5b9a\u4e49\u533a\u95f4\u9884\u7b97",
"journal_links": "\u4ea4\u6613\u5173\u8054",
"go_to_withdrawals": "\u524d\u5f80\u53d6\u6b3e",
"revenue_accounts": "\u6536\u5165\u8d26\u6237",
"add_another_split": "\u589e\u52a0\u62c6\u5206"
},
"list": {
@@ -93,18 +93,18 @@
"amount": "\u91d1\u989d",
"name": "\u540d\u79f0",
"role": "\u89d2\u8272",
"iban": "\u56fd\u9645\u94f6\u884c\u5e10\u6237\u53f7\u7801 (IBAN)",
"iban": "\u56fd\u9645\u94f6\u884c\u8d26\u6237\u53f7\u7801\uff08IBAN\uff09",
"lastActivity": "\u4e0a\u6b21\u6d3b\u52a8",
"currentBalance": "\u76ee\u524d\u9980\u989d",
"balanceDiff": "\u9980\u989d\u5dee",
"next_expected_match": "\u4e0b\u4e00\u4e2a\u9884\u671f\u7684\u914d\u5bf9"
"currentBalance": "\u76ee\u524d\u4f59\u989d",
"balanceDiff": "\u4f59\u989d\u5dee",
"next_expected_match": "\u4e0b\u4e00\u6b21\u9884\u671f\u5339\u914d"
},
"config": {
"html_language": "zh-cn"
},
"form": {
"foreign_amount": "\u5916\u5e01\u91d1\u989d",
"interest_date": "\u5229\u7387\u65e5\u671f",
"interest_date": "\u5229\u606f\u65e5\u671f",
"book_date": "\u767b\u8bb0\u65e5\u671f",
"process_date": "\u5904\u7406\u65e5\u671f",
"due_date": "\u5230\u671f\u65e5",