From 99aaf35e0bbef919b877e68a527013ee2adeaad3 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sun, 16 Jul 2023 23:35:37 +0800 Subject: [PATCH] add account list page for desktop --- src/lib/account.js | 76 +++++ src/lib/i18n.js | 11 + src/locales/en.js | 4 + src/locales/zh_Hans.js | 4 + src/stores/account.js | 97 ++++++ src/views/desktop/AccountsPage.vue | 457 ++++++++++++++++++++++++++++- 6 files changed, 646 insertions(+), 3 deletions(-) diff --git a/src/lib/account.js b/src/lib/account.js index 97d638c3..92016d9f 100644 --- a/src/lib/account.js +++ b/src/lib/account.js @@ -10,6 +10,82 @@ export function getAccountCategoryInfo(categoryId) { return null; } +export function getAccountOrSubAccountId(account, subAccountId) { + if (account.type === accountConstants.allAccountTypes.SingleAccount) { + return account.id; + } else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && !subAccountId) { + return account.id; + } else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && subAccountId) { + if (!account.subAccounts || !account.subAccounts.length) { + return null; + } + + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + + if (subAccountId && subAccountId === subAccount.id) { + return subAccount.id; + } + } + + return null; + } else { + return null; + } +} + +export function getAccountOrSubAccountComment(account, subAccountId) { + if (account.type === accountConstants.allAccountTypes.SingleAccount) { + return account.comment; + } else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && !subAccountId) { + return account.comment; + } else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && subAccountId) { + if (!account.subAccounts || !account.subAccounts.length) { + return null; + } + + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + + if (subAccountId && subAccountId === subAccount.id) { + return subAccount.comment; + } + } + + return null; + } else { + return null; + } +} + +export function getSubAccountCurrencies(account, showHidden, subAccountId) { + if (!account.subAccounts || !account.subAccounts.length) { + return []; + } + + const subAccountCurrenciesMap = {}; + const subAccountCurrencies = []; + + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + + if (!showHidden && subAccount.hidden) { + continue; + } + + if (subAccountId && subAccountId === subAccount.id) { + return [subAccount.currency]; + } else { + if (!subAccountCurrenciesMap[subAccount.currency]) { + subAccountCurrenciesMap[subAccount.currency] = true; + subAccountCurrencies.push(subAccount.currency); + } + } + } + + return subAccountCurrencies; +} + export function getCategorizedAccounts(allAccounts) { const ret = {}; diff --git a/src/lib/i18n.js b/src/lib/i18n.js index a685d0aa..3b0384cc 100644 --- a/src/lib/i18n.js +++ b/src/lib/i18n.js @@ -726,6 +726,16 @@ function getDisplayCurrency(value, currencyCode, options, translateFn) { } } +function joinMultiText(textArray, translateFn) { + if (!textArray || !textArray.length) { + return ''; + } + + const separator = translateFn('format.misc.multiTextJoinSeparator'); + + return textArray.join(separator); +} + function getLocalizedError(error) { if (error.errorCode === apiNotFoundErrorCode && specifiedApiNotFoundErrors[error.path]) { return { @@ -948,6 +958,7 @@ export function i18nFunctions(i18nGlobal) { getAllDisplayExchangeRates: (exchangeRatesData) => getAllDisplayExchangeRates(exchangeRatesData, i18nGlobal.t), getEnableDisableOptions: () => getEnableDisableOptions(i18nGlobal.t), getDisplayCurrency: (value, currencyCode, options) => getDisplayCurrency(value, currencyCode, options, i18nGlobal.t), + joinMultiText: (textArray) => joinMultiText(textArray, i18nGlobal.t), setLanguage: (locale, force) => setLanguage(i18nGlobal, locale, force), initLocale: (lastUserLanguage, timezone) => initLocale(i18nGlobal, lastUserLanguage, timezone) }; diff --git a/src/locales/en.js b/src/locales/en.js index ffa8d186..630cb300 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -67,6 +67,7 @@ export default { 'symbol': '{symbol} {amount}' }, 'misc': { + 'multiTextJoinSeparator': ', ', 'hoursBehindDefaultTimezone': '{hours} hour(s) behind default timezone', 'hoursAheadOfDefaultTimezone': '{hours} hour(s) ahead of default timezone', 'hoursMinutesBehindDefaultTimezone': '{hours} hour(s) and {minutes} minutes behind default timezone', @@ -855,6 +856,8 @@ export default { 'Debt Account': 'Debt Account', 'Receivables': 'Receivables', 'Investment Account': 'Investment Account', + 'Balance': 'Balance', + 'View Transactions': 'View Transactions', 'Unable to get account list': 'Unable to get account list', 'Account list is up to date': 'Account list is up to date', 'Account list has been updated': 'Account list has been updated', @@ -997,6 +1000,7 @@ export default { 'Currency Name': 'Currency Name', 'Currency Symbol': 'Currency Symbol', 'Show Account Balance': 'Show Account Balance', + 'Hide Account Balance': 'Hide Account Balance', 'Page Settings': 'Page Settings', 'Overview Page': 'Overview Page', 'Transaction List Page': 'Transaction List Page', diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js index c5f76334..c9f455ab 100644 --- a/src/locales/zh_Hans.js +++ b/src/locales/zh_Hans.js @@ -67,6 +67,7 @@ export default { 'symbol': '{symbol} {amount}' }, 'misc': { + 'multiTextJoinSeparator': '、', 'hoursBehindDefaultTimezone': '比默认时区晚{hours}小时', 'hoursAheadOfDefaultTimezone': '比默认时区早{hours}小时', 'hoursMinutesBehindDefaultTimezone': '比默认时区晚{hours}小时{minutes}分', @@ -855,6 +856,8 @@ export default { 'Debt Account': '负债账户', 'Receivables': '应收款项', 'Investment Account': '投资账户', + 'Balance': '余额', + 'View Transactions': '查看交易', 'Unable to get account list': '无法获取账户列表', 'Account list is up to date': '账户列表已是最新', 'Account list has been updated': '账户列表已更新', @@ -997,6 +1000,7 @@ export default { 'Currency Name': '货币名称', 'Currency Symbol': '货币符号', 'Show Account Balance': '显示账户余额', + 'Hide Account Balance': '隐藏账户余额', 'Page Settings': '页面设置', 'Overview Page': '总览页面', 'Transaction List Page': '交易列表页面', diff --git a/src/stores/account.js b/src/stores/account.js index ea361097..bc6e170d 100644 --- a/src/stores/account.js +++ b/src/stores/account.js @@ -485,6 +485,103 @@ export const useAccountsStore = defineStore('accounts', { return '***'; } }, + getAccountSubAccountBalance(showAccountBalance, showHidden, account, subAccountId) { + if (account.type !== accountConstants.allAccountTypes.MultiSubAccounts) { + return null; + } + + const userStore = useUserStore(); + const exchangeRatesStore = useExchangeRatesStore(); + let resultCurrency = userStore.currentUserDefaultCurrency; + + if (!account.subAccounts || !account.subAccounts.length) { + return { + balance: showAccountBalance ? 0 : '***', + currency: resultCurrency + }; + } + + const allSubAccountCurrenciesMap = {}; + const allSubAccountCurrencies = []; + let totalBalance = 0; + + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + + if (!showHidden && subAccount.hidden) { + continue; + } + + if (!allSubAccountCurrenciesMap[subAccount.currency]) { + allSubAccountCurrenciesMap[subAccount.currency] = true; + allSubAccountCurrencies.push(subAccount.currency); + } + } + + if (allSubAccountCurrencies.length === 0) { + return { + balance: showAccountBalance ? 0 : '***', + currency: resultCurrency + }; + } + + if (allSubAccountCurrencies.length === 1) { + resultCurrency = allSubAccountCurrencies[0]; + } + + let hasUnCalculatedAmount = false; + + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + + if (!showHidden && subAccount.hidden) { + continue; + } + + if (subAccountId) { + if (subAccountId === subAccount.id) { + return { + balance: showAccountBalance ? this.getAccountBalance(showAccountBalance, subAccount) : '***', + currency: subAccount.currency + }; + } + } + + if (subAccount === resultCurrency) { + if (subAccount.isAsset) { + totalBalance += subAccount.balance; + } else if (subAccount.isLiability) { + totalBalance -= subAccount.balance; + } else { + totalBalance += subAccount.balance; + } + } else { + const balance = exchangeRatesStore.getExchangedAmount(subAccount.balance, subAccount.currency, resultCurrency); + + if (!isNumber(balance)) { + hasUnCalculatedAmount = true; + continue; + } + + if (subAccount.isAsset) { + totalBalance += Math.floor(balance); + } else if (subAccount.isLiability) { + totalBalance -= Math.floor(balance); + } else { + totalBalance += Math.floor(balance); + } + } + } + + if (subAccountId) { // not found specified id in sub accounts + return null; + } + + return { + balance: showAccountBalance ? totalBalance : '***', + currency: resultCurrency + }; + }, hasAccount(accountCategory, visibleOnly) { if (!this.allCategorizedAccounts[accountCategory.id] || !this.allCategorizedAccounts[accountCategory.id].accounts || diff --git a/src/views/desktop/AccountsPage.vue b/src/views/desktop/AccountsPage.vue index 2e202c61..c8cc1afb 100644 --- a/src/views/desktop/AccountsPage.vue +++ b/src/views/desktop/AccountsPage.vue @@ -1,13 +1,464 @@ + +