diff --git a/src/api/accountApi.js b/src/api/accountApi.js index 69da852..8e0dd63 100644 --- a/src/api/accountApi.js +++ b/src/api/accountApi.js @@ -153,6 +153,14 @@ export const accountApi = { return http.delete(`/account/tags/${id}`) }, + // 카드 결제 알림 자동인식 (미확인 내역) + pendingCount() { + return http.get('/account/entries/pending/count') + }, + confirmEntry(id, payload) { + return http.post(`/account/entries/${id}/confirm`, payload || {}) + }, + // 영수증 OCR (백엔드가 Google Vision 호출 → 전체 텍스트 반환) ocrReceipt(blob) { const fd = new FormData() diff --git a/src/views/account/AccountView.vue b/src/views/account/AccountView.vue index d2ae2a6..7fa2399 100644 --- a/src/views/account/AccountView.vue +++ b/src/views/account/AccountView.vue @@ -14,6 +14,26 @@ const entries = ref([]) const summary = ref({ totalIncome: 0, totalExpense: 0, balance: 0 }) const loading = ref(false) const error = ref(null) +const pendingCount = ref(0) // 확인 필요(카드 알림 자동인식) 건수 +const editingPending = ref(false) // 수정 중인 항목이 미확인 건인지 + +async function loadPendingCount() { + try { + pendingCount.value = (await accountApi.pendingCount()).count || 0 + } catch { + pendingCount.value = 0 + } +} +// 미확인 내역 즉시 확정(분류 미지정으로 수락) +async function confirmRow(e) { + try { + await accountApi.confirmEntry(e.id, {}) + await load() + await loadPendingCount() + } catch (err) { + alert(err.response?.data?.message || '확인 처리에 실패했습니다.') + } +} // 검색·필터 const filterOpen = ref(false) @@ -331,6 +351,7 @@ function todayStr() { function openCreate() { editId.value = null + editingPending.value = false Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: '', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' }) selectedTagIds.value = [] cancelAddCategory() @@ -339,6 +360,7 @@ function openCreate() { } function openEdit(e) { editId.value = e.id + editingPending.value = !!e.pending Object.assign(form, { entryDate: e.entryDate, type: e.type, @@ -428,10 +450,18 @@ async function submit() { tagIds: selectedTagIds.value, } try { - if (editId.value) await accountApi.update(editId.value, payload) - else await accountApi.create(payload) + if (editId.value) { + await accountApi.update(editId.value, payload) + // 미확인(카드 알림) 건이면 수정 저장 후 확정 처리 + if (editingPending.value) { + await accountApi.confirmEntry(editId.value, {}) + } + } else { + await accountApi.create(payload) + } formOpen.value = false await load() + await loadPendingCount() } catch (e) { formError.value = e.response?.data?.message || '저장에 실패했습니다.' } finally { @@ -460,13 +490,14 @@ onMounted(async () => { loadTagOptions() loadWallets() loadCategories() + loadPendingCount() })