mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 15:07:33 +08:00
batch create nonexistent transaction tags when import transaction
This commit is contained in:
@@ -80,6 +80,7 @@ import type {
|
||||
} from '@/models/transaction_picture_info.ts';
|
||||
import type {
|
||||
TransactionTagCreateRequest,
|
||||
TransactionTagCreateBatchRequest,
|
||||
TransactionTagModifyRequest,
|
||||
TransactionTagHideRequest,
|
||||
TransactionTagMoveRequest,
|
||||
@@ -523,6 +524,9 @@ export default {
|
||||
addTransactionTag: (req: TransactionTagCreateRequest): ApiResponsePromise<TransactionTagInfoResponse> => {
|
||||
return axios.post<ApiResponse<TransactionTagInfoResponse>>('v1/transaction/tags/add.json', req);
|
||||
},
|
||||
addTransactionTagBatch: (req: TransactionTagCreateBatchRequest): ApiResponsePromise<TransactionTagInfoResponse[]> => {
|
||||
return axios.post<ApiResponse<TransactionTagInfoResponse[]>>('v1/transaction/tags/add_batch.json', req);
|
||||
},
|
||||
modifyTransactionTag: (req: TransactionTagModifyRequest): ApiResponsePromise<TransactionTagInfoResponse> => {
|
||||
return axios.post<ApiResponse<TransactionTagInfoResponse>>('v1/transaction/tags/modify.json', req);
|
||||
},
|
||||
|
||||
@@ -47,6 +47,11 @@ export interface TransactionTagCreateRequest {
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
export interface TransactionTagCreateBatchRequest {
|
||||
readonly tags: TransactionTagCreateRequest[];
|
||||
readonly skipExists: boolean;
|
||||
}
|
||||
|
||||
export interface TransactionTagModifyRequest {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { defineStore } from 'pinia';
|
||||
import type { BeforeResolveFunction } from '@/core/base.ts';
|
||||
|
||||
import {
|
||||
type TransactionTagCreateBatchRequest,
|
||||
type TransactionTagInfoResponse,
|
||||
type TransactionTagNewDisplayOrderRequest,
|
||||
TransactionTag
|
||||
@@ -189,6 +190,37 @@ export const useTransactionTagsStore = defineStore('transactionTags', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function addTags(req: TransactionTagCreateBatchRequest): Promise<TransactionTag[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
services.addTransactionTagBatch(req).then(response => {
|
||||
const data = response.data;
|
||||
|
||||
if (!data || !data.success || !data.result) {
|
||||
reject({ message: 'Unable to add tag' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!transactionTagListStateInvalid.value) {
|
||||
updateTransactionTagListInvalidState(true);
|
||||
}
|
||||
|
||||
const transactionTags = TransactionTag.ofMulti(data.result);
|
||||
|
||||
resolve(transactionTags);
|
||||
}).catch(error => {
|
||||
logger.error('failed to add tags', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
reject({ error: error.response.data });
|
||||
} else if (!error.processed) {
|
||||
reject({ message: 'Unable to add tag' });
|
||||
} else {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function changeTagDisplayOrder({ tagId, from, to }: { tagId: string, from: number, to: number }): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let tag: TransactionTag | null = null;
|
||||
@@ -342,6 +374,7 @@ export const useTransactionTagsStore = defineStore('transactionTags', () => {
|
||||
resetTransactionTags,
|
||||
loadAllTags,
|
||||
saveTag,
|
||||
addTags,
|
||||
changeTagDisplayOrder,
|
||||
updateTagDisplayOrders,
|
||||
hideTag,
|
||||
|
||||
@@ -155,10 +155,10 @@
|
||||
:disabled="!!editingTransaction || !allInvalidTransferCategoryNames || allInvalidTransferCategoryNames.length < 1"
|
||||
:title="tt('Create Nonexistent Transfer Categories')"
|
||||
@click="showBatchCreateInvalidItemDialog('transferCategory', allInvalidTransferCategoryNames)"></v-list-item>
|
||||
<!-- <v-list-item :prepend-icon="mdiShapePlusOutline"-->
|
||||
<!-- :disabled="!!editingTransaction || !allInvalidTransactionTagNames || allInvalidTransactionTagNames.length < 1"-->
|
||||
<!-- :title="tt('Create Nonexistent Transaction Tags')"-->
|
||||
<!-- @click="showBatchCreateInvalidItemDialog('tag', allInvalidTransactionTagNames)"></v-list-item>-->
|
||||
<v-list-item :prepend-icon="mdiShapePlusOutline"
|
||||
:disabled="!!editingTransaction || !allInvalidTransactionTagNames || allInvalidTransactionTagNames.length < 1"
|
||||
:title="tt('Create Nonexistent Transaction Tags')"
|
||||
@click="showBatchCreateInvalidItemDialog('tag', allInvalidTransactionTagNames)"></v-list-item>
|
||||
<v-divider class="my-2"/>
|
||||
<v-list-item :prepend-icon="mdiTransfer"
|
||||
:disabled="!!editingTransaction || selectedExpenseTransactionCount < 1"
|
||||
|
||||
@@ -72,6 +72,7 @@ import { ref, useTemplateRef } from 'vue';
|
||||
import { useI18n } from '@/locales/helpers.ts';
|
||||
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
|
||||
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||
|
||||
import type { NameValue } from '@/core/base.ts';
|
||||
import { CategoryType } from '@/core/category.ts';
|
||||
@@ -79,6 +80,7 @@ import { AUTOMATICALLY_CREATED_CATEGORY_ICON_ID } from '@/consts/icon.ts';
|
||||
import { DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
|
||||
|
||||
import { type TransactionCategoryCreateRequest, type TransactionCategoryCreateWithSubCategories, TransactionCategory } from '@/models/transaction_category.ts';
|
||||
import { type TransactionTagCreateRequest, TransactionTag } from '@/models/transaction_tag.ts';
|
||||
|
||||
import { isDefined, arrayItemToObjectField } from '@/lib/common.ts';
|
||||
|
||||
@@ -104,6 +106,7 @@ defineProps<{
|
||||
const { tt } = useI18n();
|
||||
|
||||
const transactionCategoriesStore = useTransactionCategoriesStore();
|
||||
const transactionTagsStore = useTransactionTagsStore();
|
||||
|
||||
const snackbar = useTemplateRef<SnackBarType>('snackbar');
|
||||
|
||||
@@ -151,6 +154,31 @@ function buildBatchCreateCategoryResponse(createdCategories: Record<number, Tran
|
||||
return response;
|
||||
}
|
||||
|
||||
function buildBatchCreateTagResponse(createdTags: TransactionTag[]): BatchCreateDialogResponse {
|
||||
const displayNameSourceItemMap: Record<string, string> = {};
|
||||
const sourceTargetMap: Record<string, string> = {};
|
||||
|
||||
for (const item of (invalidItems.value || [])) {
|
||||
displayNameSourceItemMap[item.name] = item.value;
|
||||
}
|
||||
|
||||
for (const tag of createdTags) {
|
||||
const sourceItem = displayNameSourceItemMap[tag.name];
|
||||
|
||||
if (!isDefined(sourceItem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sourceTargetMap[sourceItem] = tag.id;
|
||||
}
|
||||
|
||||
const response: BatchCreateDialogResponse = {
|
||||
sourceTargetMap: sourceTargetMap
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
function open(options: { type: BatchCreateDialogDataType, invalidItems?: NameValue[] }): Promise<BatchCreateDialogResponse> {
|
||||
type.value = options.type;
|
||||
invalidItems.value = options.invalidItems;
|
||||
@@ -241,7 +269,38 @@ function confirm(): void {
|
||||
}
|
||||
});
|
||||
} else if (type.value === 'tag') {
|
||||
submitting.value = true;
|
||||
|
||||
const submitTags: TransactionTagCreateRequest[] = [];
|
||||
|
||||
for (const item of selectedNames.value) {
|
||||
const tag: TransactionTag = TransactionTag.createNewTag(item);
|
||||
submitTags.push(tag.toCreateRequest());
|
||||
}
|
||||
|
||||
transactionTagsStore.addTags({
|
||||
tags: submitTags,
|
||||
skipExists: true
|
||||
}).then(response => {
|
||||
transactionTagsStore.loadAllTags({ force: false }).then(() => {
|
||||
submitting.value = false;
|
||||
showState.value = false;
|
||||
|
||||
resolveFunc?.(buildBatchCreateTagResponse(response));
|
||||
}).catch(error => {
|
||||
submitting.value = false;
|
||||
|
||||
if (!error.processed) {
|
||||
snackbar.value?.showError(error);
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
submitting.value = false;
|
||||
|
||||
if (!error.processed) {
|
||||
snackbar.value?.showError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user