add / view transaction in reconciliation statement dialog

This commit is contained in:
MaysWind
2025-07-23 00:41:32 +08:00
parent 5d07d1a70d
commit 6050f5deab
12 changed files with 107 additions and 4 deletions
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Verbergen", "Hide": "Verbergen",
"Version": "Version", "Version": "Version",
"Edit": "Bearbeiten", "Edit": "Bearbeiten",
"View": "View",
"Remove": "Entfernen", "Remove": "Entfernen",
"Delete": "Löschen", "Delete": "Löschen",
"Duplicate": "Duplizieren", "Duplicate": "Duplizieren",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Hide", "Hide": "Hide",
"Version": "Version", "Version": "Version",
"Edit": "Edit", "Edit": "Edit",
"View": "View",
"Remove": "Remove", "Remove": "Remove",
"Delete": "Delete", "Delete": "Delete",
"Duplicate": "Duplicate", "Duplicate": "Duplicate",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Ocultar", "Hide": "Ocultar",
"Version": "Versión", "Version": "Versión",
"Edit": "Editar", "Edit": "Editar",
"View": "View",
"Remove": "Eliminar", "Remove": "Eliminar",
"Delete": "Borrar", "Delete": "Borrar",
"Duplicate": "Duplicar", "Duplicate": "Duplicar",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Nascondi", "Hide": "Nascondi",
"Version": "Versione", "Version": "Versione",
"Edit": "Modifica", "Edit": "Modifica",
"View": "View",
"Remove": "Rimuovi", "Remove": "Rimuovi",
"Delete": "Elimina", "Delete": "Elimina",
"Duplicate": "Duplica", "Duplicate": "Duplica",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "非表示", "Hide": "非表示",
"Version": "バージョン", "Version": "バージョン",
"Edit": "編集", "Edit": "編集",
"View": "View",
"Remove": "削除", "Remove": "削除",
"Delete": "削除", "Delete": "削除",
"Duplicate": "複製", "Duplicate": "複製",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Ocultar", "Hide": "Ocultar",
"Version": "Versão", "Version": "Versão",
"Edit": "Editar", "Edit": "Editar",
"View": "View",
"Remove": "Remover", "Remove": "Remover",
"Delete": "Excluir", "Delete": "Excluir",
"Duplicate": "Duplicar", "Duplicate": "Duplicar",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Скрыть", "Hide": "Скрыть",
"Version": "Версия", "Version": "Версия",
"Edit": "Редактировать", "Edit": "Редактировать",
"View": "View",
"Remove": "Удалить", "Remove": "Удалить",
"Delete": "Удалить", "Delete": "Удалить",
"Duplicate": "Дублировать", "Duplicate": "Дублировать",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Сховати", "Hide": "Сховати",
"Version": "Версія", "Version": "Версія",
"Edit": "Редагувати", "Edit": "Редагувати",
"View": "View",
"Remove": "Видалити", "Remove": "Видалити",
"Delete": "Видалити", "Delete": "Видалити",
"Duplicate": "Дублювати", "Duplicate": "Дублювати",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "Ẩn", "Hide": "Ẩn",
"Version": "Phiên bản", "Version": "Phiên bản",
"Edit": "Sửa", "Edit": "Sửa",
"View": "View",
"Remove": "Xóa", "Remove": "Xóa",
"Delete": "Xóa", "Delete": "Xóa",
"Duplicate": "Nhân đôi", "Duplicate": "Nhân đôi",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "隐藏", "Hide": "隐藏",
"Version": "版本", "Version": "版本",
"Edit": "编辑", "Edit": "编辑",
"View": "查看",
"Remove": "移除", "Remove": "移除",
"Delete": "删除", "Delete": "删除",
"Duplicate": "复制", "Duplicate": "复制",
+1
View File
@@ -1360,6 +1360,7 @@
"Hide": "隱藏", "Hide": "隱藏",
"Version": "版本", "Version": "版本",
"Edit": "編輯", "Edit": "編輯",
"View": "檢視",
"Remove": "移除", "Remove": "移除",
"Delete": "刪除", "Delete": "刪除",
"Duplicate": "複製", "Duplicate": "複製",
@@ -1,5 +1,5 @@
<template> <template>
<v-dialog :min-height="loading ? 600 : 400" :persistent="loading" v-model="showState"> <v-dialog :min-height="400" :persistent="loading" v-model="showState">
<v-card class="pa-6 pa-sm-10 pa-md-12"> <v-card class="pa-6 pa-sm-10 pa-md-12">
<template #title> <template #title>
<div class="d-flex align-center justify-center"> <div class="d-flex align-center justify-center">
@@ -7,6 +7,17 @@
<h4 class="text-h4">{{ tt('Reconciliation Statement') }}</h4> <h4 class="text-h4">{{ tt('Reconciliation Statement') }}</h4>
<v-progress-circular indeterminate size="22" class="ml-2" v-if="loading"></v-progress-circular> <v-progress-circular indeterminate size="22" class="ml-2" v-if="loading"></v-progress-circular>
</div> </div>
<v-btn density="comfortable" color="default" variant="text" class="ml-2"
:icon="true" :disabled="loading">
<v-icon :icon="mdiDotsVertical" />
<v-menu activator="parent">
<v-list>
<v-list-item :prepend-icon="mdiReceiptTextPlusOutline"
:title="tt('Add Transaction')"
@click="addTransaction()"></v-list-item>
</v-list>
</v-menu>
</v-btn>
</div> </div>
</template> </template>
@@ -118,6 +129,12 @@
<template #item.accountBalance="{ item }"> <template #item.accountBalance="{ item }">
<span>{{ getDisplayAccountBalance(item) }}</span> <span>{{ getDisplayAccountBalance(item) }}</span>
</template> </template>
<template #item.operation="{ item }">
<v-btn density="compact" variant="text" color="default" :disabled="loading"
@click="showTransaction(item)">
{{ tt('View') }}
</v-btn>
</template>
<template #bottom> <template #bottom>
<div class="title-and-toolbar d-flex align-center text-no-wrap mt-2" v-if="loading || reconciliationStatements.length"> <div class="title-and-toolbar d-flex align-center text-no-wrap mt-2" v-if="loading || reconciliationStatements.length">
<span class="ml-2">{{ tt('Total Transactions') }}</span> <span class="ml-2">{{ tt('Total Transactions') }}</span>
@@ -157,12 +174,19 @@
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-dialog> </v-dialog>
<edit-dialog ref="editDialog" :type="TransactionEditPageType.Transaction" />
<snack-bar ref="snackbar" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import PaginationButtons from '@/components/desktop/PaginationButtons.vue'; import PaginationButtons from '@/components/desktop/PaginationButtons.vue';
import SnackBar from '@/components/desktop/SnackBar.vue';
import EditDialog from '@/views/desktop/transactions/list/dialogs/EditDialog.vue';
import { TransactionEditPageType } from '@/views/base/transactions/TransactionEditPageBase.ts';
import { ref, computed } from 'vue'; import { ref, computed, useTemplateRef } from 'vue';
import { useI18n } from '@/locales/helpers.ts'; import { useI18n } from '@/locales/helpers.ts';
import { useReconciliationStatementPageBase } from '@/views/base/transactions/ReconciliationStatementPageBase.ts'; import { useReconciliationStatementPageBase } from '@/views/base/transactions/ReconciliationStatementPageBase.ts';
@@ -172,11 +196,17 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionsStore } from '@/stores/transaction.ts'; import { useTransactionsStore } from '@/stores/transaction.ts';
import { TransactionType } from '@/core/transaction.ts'; import { TransactionType } from '@/core/transaction.ts';
import { Transaction, type TransactionReconciliationStatementResponseItem } from '@/models/transaction.ts';
import { import {
mdiArrowRight mdiArrowRight,
mdiDotsVertical,
mdiReceiptTextPlusOutline
} from '@mdi/js'; } from '@mdi/js';
type SnackBarType = InstanceType<typeof SnackBar>;
type EditDialogType = InstanceType<typeof EditDialog>;
interface ReconciliationStatementDialogTablePageOption { interface ReconciliationStatementDialogTablePageOption {
value: number; value: number;
title: string; title: string;
@@ -216,6 +246,9 @@ const accountsStore = useAccountsStore();
const transactionCategoriesStore = useTransactionCategoriesStore(); const transactionCategoriesStore = useTransactionCategoriesStore();
const transactionsStore = useTransactionsStore(); const transactionsStore = useTransactionsStore();
const snackbar = useTemplateRef<SnackBarType>('snackbar');
const editDialog = useTemplateRef<EditDialogType>('editDialog');
const showState = ref<boolean>(false); const showState = ref<boolean>(false);
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const currentPage = ref<number>(1); const currentPage = ref<number>(1);
@@ -251,6 +284,7 @@ const dataTableHeaders = computed<object[]>(() => {
headers.push({ key: 'sourceAccountId', value: 'sourceAccountId', title: tt('Account'), sortable: true, nowrap: true }); headers.push({ key: 'sourceAccountId', value: 'sourceAccountId', title: tt('Account'), sortable: true, nowrap: true });
headers.push({ key: 'accountBalance', value: 'accountBalance', title: tt(accountBalanceName), sortable: true, nowrap: true }); headers.push({ key: 'accountBalance', value: 'accountBalance', title: tt(accountBalanceName), sortable: true, nowrap: true });
headers.push({ key: 'comment', value: 'comment', title: tt('Description'), sortable: true, nowrap: true }); headers.push({ key: 'comment', value: 'comment', title: tt('Description'), sortable: true, nowrap: true });
headers.push({ key: 'operation', title: tt('Operation'), sortable: false, nowrap: true, align: 'end' });
return headers; return headers;
}); });
@@ -310,13 +344,71 @@ function open(options: { accountId: string, startTime: number, endTime: number }
emit('error', error); emit('error', error);
showState.value = false; showState.value = false;
} }
}) });
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
rejectFunc = reject; rejectFunc = reject;
}); });
} }
function reload(): void {
loading.value = true;
transactionsStore.getReconciliationStatements({
accountId: accountId.value,
startTime: startTime.value,
endTime: endTime.value
}).then(result => {
reconciliationStatements.value = result.transactions;
openingBalance.value = result.openingBalance;
closingBalance.value = result.closingBalance;
loading.value = false;
}).catch(error => {
loading.value = false;
if (!error.processed) {
snackbar.value?.showError(error);
}
})
}
function addTransaction(): void {
editDialog.value?.open({
accountId: accountId.value
}).then(result => {
if (result && result.message) {
snackbar.value?.showMessage(result.message);
}
reload();
}).catch(error => {
if (error) {
snackbar.value?.showError(error);
}
});
}
function showTransaction(transaction: TransactionReconciliationStatementResponseItem): void {
if (transaction.type === TransactionType.ModifyBalance) {
return;
}
editDialog.value?.open({
id: transaction.id,
currentTransaction: Transaction.of(transaction)
}).then(result => {
if (result && result.message) {
snackbar.value?.showMessage(result.message);
}
reload();
}).catch(error => {
if (error) {
snackbar.value?.showError(error);
}
});
}
function close(): void { function close(): void {
rejectFunc?.(); rejectFunc?.();
showState.value = false; showState.value = false;