support hiding/unhiding/deleting sub-account in account list page

This commit is contained in:
MaysWind
2025-04-13 20:46:06 +08:00
parent 68b08c1e8a
commit df31be61e8
15 changed files with 329 additions and 32 deletions
+3
View File
@@ -360,6 +360,9 @@ export default {
deleteAccount: (req: AccountDeleteRequest): ApiResponsePromise<boolean> => {
return axios.post<ApiResponse<boolean>>('v1/accounts/delete.json', req);
},
deleteSubAccount: (req: AccountDeleteRequest): ApiResponsePromise<boolean> => {
return axios.post<ApiResponse<boolean>>('v1/accounts/sub_account/delete.json', req);
},
getTransactions: (req: TransactionListByMaxTimeRequest): ApiResponsePromise<TransactionInfoPageWrapperResponse> => {
const amountFilter = encodeURIComponent(req.amountFilter);
const keyword = encodeURIComponent(req.keyword);
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "Kontosaldo-Zeit ist nicht festgelegt",
"cannot set statement date for non credit card account": "Abrechnungsdatum kann für kein Kreditkartenkonto festgelegt werden",
"cannot set statement date for sub account": "Abrechnungsdatum kann für Teilkonto nicht festgelegt werden",
"sub-account not found": "Sub-account is not found",
"sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted",
"transaction id is invalid": "Transaktions-ID ist ungültig",
"transaction not found": "Transaktion nicht gefunden",
"transaction type is invalid": "Transaktionstyp ist ungültig",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "Dieses Konto kann nicht eingeblendet werden",
"Unable to move account": "Konto kann nicht verschoben werden",
"Are you sure you want to delete this account?": "Sind Sie sicher, dass Sie dieses Konto löschen möchten?",
"Are you sure you want to delete this sub-account?": "Are you sure you want to delete this sub-account?",
"Unable to delete this account": "Konto kann nicht gelöscht werden",
"Unable to delete this sub-account": "Unable to delete this sub-account",
"Transaction": "Transaktion",
"Transactions": "Transaktionen",
"Transaction Pictures": "Transaktionsbilder",
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "Account balance time is not set",
"cannot set statement date for non credit card account": "Cannot set statement date for non credit card account",
"cannot set statement date for sub account": "Cannot set statement date for sub-account",
"sub-account not found": "Sub-account is not found",
"sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted",
"transaction id is invalid": "Transaction ID is invalid",
"transaction not found": "Transaction is not found",
"transaction type is invalid": "Transaction type is invalid",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "Unable to unhide this account",
"Unable to move account": "Unable to move account",
"Are you sure you want to delete this account?": "Are you sure you want to delete this account?",
"Are you sure you want to delete this sub-account?": "Are you sure you want to delete this sub-account?",
"Unable to delete this account": "Unable to delete this account",
"Unable to delete this sub-account": "Unable to delete this sub-account",
"Transaction": "Transaction",
"Transactions": "Transactions",
"Transaction Pictures": "Transaction Pictures",
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "La hora del saldo de la cuenta no está establecida",
"cannot set statement date for non credit card account": "No se puede establecer la fecha del extracto para una cuenta que no sea de tarjeta de crédito",
"cannot set statement date for sub account": "No se puede establecer la fecha del estado de cuenta para la subcuenta",
"sub-account not found": "Sub-account is not found",
"sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted",
"transaction id is invalid": "El ID de transacción no es válido",
"transaction not found": "La transacción no se encuentra",
"transaction type is invalid": "El tipo de transacción no es válido",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "No se puede mostrar esta cuenta",
"Unable to move account": "No se puede mover la cuenta",
"Are you sure you want to delete this account?": "¿Está seguro de que desea eliminar esta cuenta?",
"Are you sure you want to delete this sub-account?": "Are you sure you want to delete this sub-account?",
"Unable to delete this account": "No se puede eliminar esta cuenta",
"Unable to delete this sub-account": "Unable to delete this sub-account",
"Transaction": "Transacción",
"Transactions": "Transacciones",
"Transaction Pictures": "Imágenes de transacciones",
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "口座残高の時間が設定されていません",
"cannot set statement date for non credit card account": "クレジットカード以外の口座の明細書の日付を設定できません",
"cannot set statement date for sub account": "子口座の明細日を設定できません",
"sub-account not found": "Sub-account is not found",
"sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted",
"transaction id is invalid": "取引IDは無効です",
"transaction not found": "取引が見つかりません",
"transaction type is invalid": "取引タイプは無効です",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "この口座は非表示を解除できません",
"Unable to move account": "口座を移動できません",
"Are you sure you want to delete this account?": "この口座を削除しますか?",
"Are you sure you want to delete this sub-account?": "Are you sure you want to delete this sub-account?",
"Unable to delete this account": "この口座を削除できません",
"Unable to delete this sub-account": "Unable to delete this sub-account",
"Transaction": "取引",
"Transactions": "取引",
"Transaction Pictures": "取引の写真",
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "Время баланса счета не установлено",
"cannot set statement date for non credit card account": "Нельзя установить дату выписки для счета, не являющегося кредитной картой",
"cannot set statement date for sub account": "Нельзя установить дату выписки для субсчета",
"sub-account not found": "Sub-account is not found",
"sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted",
"transaction id is invalid": "ID транзакции недействителен",
"transaction not found": "Транзакция не найдена",
"transaction type is invalid": "Тип транзакции недействителен",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "Не удалось отобразить этот счет",
"Unable to move account": "Не удалось переместить счет",
"Are you sure you want to delete this account?": "Вы уверены, что хотите удалить этот счет?",
"Are you sure you want to delete this sub-account?": "Are you sure you want to delete this sub-account?",
"Unable to delete this account": "Не удалось удалить этот счет",
"Unable to delete this sub-account": "Unable to delete this sub-account",
"Transaction": "Транзакция",
"Transactions": "Транзакции",
"Transaction Pictures": "Изображения транзакций",
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "Thời gian số dư tài khoản chưa được đặt",
"cannot set statement date for non credit card account": "Cannot set statement date for non credit card account",
"cannot set statement date for sub account": "Cannot set statement date for sub-account",
"sub-account not found": "Sub-account is not found",
"sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted",
"transaction id is invalid": "ID giao dịch không hợp lệ",
"transaction not found": "Không tìm thấy giao dịch",
"transaction type is invalid": "Loại giao dịch không hợp lệ",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "Không thể hiển thị tài khoản này",
"Unable to move account": "Không thể di chuyển tài khoản",
"Are you sure you want to delete this account?": "Bạn có chắc chắn muốn xóa tài khoản này không?",
"Are you sure you want to delete this sub-account?": "Are you sure you want to delete this sub-account?",
"Unable to delete this account": "Không thể xóa tài khoản này",
"Unable to delete this sub-account": "Unable to delete this sub-account",
"Transaction": "Giao dịch",
"Transactions": "Giao dịch",
"Transaction Pictures": "Ảnh giao dịch",
+4
View File
@@ -1067,6 +1067,8 @@
"account balance time is not set": "账户余额时间没有设置",
"cannot set statement date for non credit card account": "非信用卡账户不能设置账单日期",
"cannot set statement date for sub account": "子账户不能设置账单日期",
"sub-account not found": "子账户不存在",
"sub-account is in use and cannot be deleted": "子账户正在被使用,无法删除",
"transaction id is invalid": "交易ID无效",
"transaction not found": "交易不存在",
"transaction type is invalid": "交易类型无效",
@@ -1576,7 +1578,9 @@
"Unable to unhide this account": "无法取消隐藏账户",
"Unable to move account": "无法移动账户",
"Are you sure you want to delete this account?": "您确定要删除该账户?",
"Are you sure you want to delete this sub-account?": "您确定要删除该子账户?",
"Unable to delete this account": "无法删除该账户",
"Unable to delete this sub-account": "无法删除该子账户",
"Transaction": "交易",
"Transactions": "交易",
"Transaction Pictures": "交易图片",
+64
View File
@@ -240,6 +240,30 @@ export class Account implements AccountInfoResponse {
}
}
public isAccountOrSubAccountHidden(subAccountId: string): boolean {
if (this.type === AccountType.SingleAccount.type) {
return this.hidden;
} else if (this.type === AccountType.MultiSubAccounts.type && !subAccountId) {
return this.hidden;
} else if (this.type === AccountType.MultiSubAccounts.type && subAccountId) {
if (!this.subAccounts || !this.subAccounts.length) {
return false;
}
for (let i = 0; i < this.subAccounts.length; i++) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) {
return subAccount.hidden;
}
}
return false;
} else {
return false;
}
}
public getAccountOrSubAccountComment(subAccountId: string): string | null {
if (this.type === AccountType.SingleAccount.type) {
return this.comment;
@@ -264,6 +288,46 @@ export class Account implements AccountInfoResponse {
}
}
public getAccountOrSubAccount(subAccountId: string): Account | null {
if (this.type === AccountType.SingleAccount.type) {
return this;
} else if (this.type === AccountType.MultiSubAccounts.type && !subAccountId) {
return this;
} else if (this.type === AccountType.MultiSubAccounts.type && subAccountId) {
if (!this.subAccounts || !this.subAccounts.length) {
return null;
}
for (let i = 0; i < this.subAccounts.length; i++) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) {
return subAccount;
}
}
return null;
} else {
return null;
}
}
public getSubAccount(subAccountId: string): Account | null {
if (!this.subAccounts || !this.subAccounts.length) {
return null;
}
for (let i = 0; i < this.subAccounts.length; i++) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) {
return subAccount;
}
}
return null;
}
public getSubAccountCurrencies(showHidden: boolean, subAccountId: string): string[] {
if (!this.subAccounts || !this.subAccounts.length) {
return [];
+77 -1
View File
@@ -295,6 +295,46 @@ export const useAccountsStore = defineStore('accounts', () => {
}
}
function removeSubAccountFromAccountList(subAccount: Account): void {
for (let i = 0; i < allAccounts.value.length; i++) {
if (allAccounts.value[i].type !== AccountType.MultiSubAccounts.type || !allAccounts.value[i].subAccounts) {
continue;
}
const subAccounts = allAccounts.value[i].subAccounts as Account[];
for (let j = 0; j < subAccounts.length; j++) {
if (subAccounts[j].id === subAccount.id) {
subAccounts.splice(j, 1);
break;
}
}
}
if (allAccountsMap.value[subAccount.id]) {
delete allAccountsMap.value[subAccount.id];
}
if (allCategorizedAccountsMap.value[subAccount.category]) {
const accountList = allCategorizedAccountsMap.value[subAccount.category].accounts;
for (let i = 0; i < accountList.length; i++) {
if (accountList[i].type !== AccountType.MultiSubAccounts.type || !accountList[i].subAccounts) {
continue;
}
const subAccounts = accountList[i].subAccounts as Account[];
for (let j = 0; j < subAccounts.length; j++) {
if (subAccounts[j].id === subAccount.id) {
subAccounts.splice(j, 1);
break;
}
}
}
}
}
function updateAccountListInvalidState(invalidState: boolean): void {
accountListStateInvalid.value = invalidState;
}
@@ -997,6 +1037,41 @@ export const useAccountsStore = defineStore('accounts', () => {
});
}
function deleteSubAccount({ subAccount, beforeResolve }: { subAccount: Account, beforeResolve?: BeforeResolveFunction }): Promise<boolean> {
return new Promise((resolve, reject) => {
services.deleteSubAccount({
id: subAccount.id
}).then(response => {
const data = response.data;
if (!data || !data.success || !data.result) {
reject({ message: 'Unable to delete this sub-account' });
return;
}
if (beforeResolve) {
beforeResolve(() => {
removeSubAccountFromAccountList(subAccount);
});
} else {
removeSubAccountFromAccountList(subAccount);
}
resolve(data.result);
}).catch(error => {
logger.error('failed to delete sub-account', error);
if (error.response && error.response.data && error.response.data.errorMessage) {
reject({ error: error.response.data });
} else if (!error.processed) {
reject({ message: 'Unable to delete this sub-account' });
} else {
reject(error);
}
});
});
}
return {
// states
allAccounts,
@@ -1029,6 +1104,7 @@ export const useAccountsStore = defineStore('accounts', () => {
changeAccountDisplayOrder,
updateAccountDisplayOrders,
hideAccount,
deleteAccount
deleteAccount,
deleteSubAccount
}
});
+51 -30
View File
@@ -196,24 +196,24 @@
<v-divider/>
<v-card-text v-if="accountComment(element)">
{{ accountComment(element) }}
<v-card-text v-if="element.getAccountOrSubAccountComment(activeSubAccount[element.id])">
{{ element.getAccountOrSubAccountComment(activeSubAccount[element.id]) }}
</v-card-text>
<v-card-text>
<div class="d-flex account-toolbar align-center">
<v-btn class="px-2" density="comfortable" color="default" variant="text"
:disabled="loading" :prepend-icon="mdiListBoxOutline"
:to="`/transaction/list?accountIds=${accountOrSubAccountId(element)}`">
:to="`/transaction/list?accountIds=${element.getAccountOrSubAccountId(activeSubAccount[element.id])}`">
{{ tt('Transaction List') }}
</v-btn>
<v-btn class="px-2 ml-1" density="comfortable" color="default" variant="text"
:class="{ 'd-none': loading, 'hover-display': !loading }"
:disabled="loading"
:prepend-icon="element.hidden ? mdiEyeOutline : mdiEyeOffOutline"
v-if="!activeSubAccount[element.id]"
@click="hide(element, !element.hidden)">
{{ element.hidden ? tt('Show') : tt('Hide') }}
:prepend-icon="element.isAccountOrSubAccountHidden(activeSubAccount[element.id]) ? mdiEyeOutline : mdiEyeOffOutline"
v-if="!activeSubAccount[element.id] || element.getSubAccount(activeSubAccount[element.id])"
@click="hide(element, element.getAccountOrSubAccount(activeSubAccount[element.id]), !element.isAccountOrSubAccountHidden(activeSubAccount[element.id]))">
{{ element.isAccountOrSubAccountHidden(activeSubAccount[element.id]) ? tt('Show') : tt('Hide') }}
</v-btn>
<v-btn class="px-2 ml-1" density="comfortable" color="default" variant="text"
:class="{ 'd-none': loading, 'hover-display': !loading }"
@@ -225,7 +225,7 @@
<v-btn class="px-2 ml-1" density="comfortable" color="default" variant="text"
:class="{ 'd-none': loading, 'hover-display': !loading }"
:disabled="loading" :prepend-icon="mdiDeleteOutline"
v-if="!activeSubAccount[element.id]"
v-if="!activeSubAccount[element.id] || element.getSubAccount(activeSubAccount[element.id])"
@click="remove(element)">
{{ tt('Delete') }}
</v-btn>
@@ -383,14 +383,6 @@ function hasAccount(accountCategory: AccountCategory): boolean {
return accountsStore.hasAccount(accountCategory, !showHidden.value);
}
function accountOrSubAccountId(account: Account): string | null {
return account.getAccountOrSubAccountId(activeSubAccount.value[account.id]);
}
function accountComment(account: Account): string | null {
return account.getAccountOrSubAccountComment(activeSubAccount.value[account.id]);
}
function accountCurrency(account: Account): string | null {
if (account.type === AccountType.SingleAccount.type) {
return getCurrencyName(account.currency);
@@ -458,13 +450,17 @@ function edit(account: Account): void {
});
}
function hide(account: Account, hidden: boolean): void {
function hide(account: Account, targetAccount: Account, hidden: boolean): void {
loading.value = true;
accountsStore.hideAccount({
account: account,
account: targetAccount,
hidden: hidden
}).then(() => {
if (hidden && !showHidden.value && activeSubAccount.value[account.id]) {
activeSubAccount.value[account.id] = '';
}
loading.value = false;
}).catch(error => {
loading.value = false;
@@ -476,21 +472,46 @@ function hide(account: Account, hidden: boolean): void {
}
function remove(account: Account): void {
confirmDialog.value?.open('Are you sure you want to delete this account?').then(() => {
loading.value = true;
if (activeSubAccount.value[account.id]) {
const subAccount: Account | null = account.getSubAccount(activeSubAccount.value[account.id]);
accountsStore.deleteAccount({
account: account
}).then(() => {
loading.value = false;
}).catch(error => {
loading.value = false;
if (!subAccount) {
snackbar.value?.showMessage('Unable to delete this sub-account');
return;
}
if (!error.processed) {
snackbar.value?.showError(error);
}
confirmDialog.value?.open('Are you sure you want to delete this sub-account?').then(() => {
loading.value = true;
accountsStore.deleteSubAccount({
subAccount: subAccount
}).then(() => {
loading.value = false;
}).catch(error => {
loading.value = false;
if (!error.processed) {
snackbar.value?.showError(error);
}
});
});
});
} else {
confirmDialog.value?.open('Are you sure you want to delete this account?').then(() => {
loading.value = true;
accountsStore.deleteAccount({
account: account
}).then(() => {
loading.value = false;
}).catch(error => {
loading.value = false;
if (!error.processed) {
snackbar.value?.showError(error);
}
});
});
}
}
function saveSortResult(): void {