From 9aa5f5d6907c64d139e42c2a892ab9ad8ce28395 Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Fri, 12 Jun 2026 22:52:34 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=83=81=ED=99=98/=EB=82=A9=EB=B6=80?= =?UTF-8?q?=20=EC=97=B0=ED=9A=8C=EB=B9=84=20=EC=9E=85=EB=A0=A5(=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EB=8C=80=EC=83=81=20=EC=8B=9C)=20+=20=EC=9B=90?= =?UTF-8?q?=EA=B8=88/=EC=9D=B4=EC=9E=90=20=EC=95=88=EB=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 대상이 카드일 때만 연회비 입력란 노출(repayTargetIsCard) - 원금=이체·이자/연회비=지출 안내 placeholder, 검증 '원금·이자·연회비 중 하나' Co-Authored-By: Claude Opus 4.8 --- src/views/account/AccountView.vue | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/views/account/AccountView.vue b/src/views/account/AccountView.vue index 3289710..3714551 100644 --- a/src/views/account/AccountView.vue +++ b/src/views/account/AccountView.vue @@ -76,8 +76,13 @@ function resetFilters() { // 추가/수정 모달 const formOpen = ref(false) const editId = ref(null) -const form = reactive({ entryDate: '', type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: '', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' }) +const form = reactive({ entryDate: '', type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: '', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, annualFee: null, installmentMonths: '' }) const isRepayment = computed(() => form.type === 'REPAYMENT') +// 상환 대상이 카드면 연회비 입력 노출(대출은 연회비 없음) +const repayTargetIsCard = computed(() => { + const w = wallets.value.find((x) => x.id === form.toWalletId) + return !!w && w.type === 'CARD' +}) // 카드 지출일 때만 할부 입력 노출 (2~24개월, 일시불은 빈값) const showInstallment = computed(() => form.type === 'EXPENSE' && form.walletKind === 'CARD') const installmentMonthly = computed(() => { @@ -365,7 +370,7 @@ function todayStr() { function openCreate() { editId.value = null editingPending.value = false - Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: 'BANK', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' }) + Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: 'BANK', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, annualFee: null, installmentMonths: '' }) selectedTagIds.value = [] cancelAddCategory() formError.value = null @@ -389,6 +394,7 @@ function openEdit(e) { toWalletId: e.toWalletId || '', principal: null, interest: null, + annualFee: null, installmentMonths: e.installmentMonths || '', }) // 태그 이름 → id 매핑 (현재 태그 목록 기준) @@ -406,7 +412,7 @@ async function submit() { formError.value = '거래일을 입력하세요.' return } - // 상환/납부: 원금=이체, 이자=지출 자동 분리 + // 상환/납부: 원금=이체, 이자·연회비=지출 자동 분리 if (isRepayment.value) { if (!form.walletId || !form.toWalletId) { formError.value = '출금 계좌와 대상(대출/카드)을 선택하세요.' @@ -418,20 +424,22 @@ async function submit() { } const principal = Number(form.principal) || 0 const interest = Number(form.interest) || 0 - if (principal <= 0 && interest <= 0) { - formError.value = '원금 또는 이자를 입력하세요.' + const annualFee = repayTargetIsCard.value ? (Number(form.annualFee) || 0) : 0 + if (principal <= 0 && interest <= 0 && annualFee <= 0) { + formError.value = '원금·이자·연회비 중 하나는 입력하세요.' return } submitting.value = true try { - // 상환은 원금=이체 / 이자=지출 2건으로 저장된다. 수정 시에는 기존 1건을 - // 상환 2건으로 다시 만든다(상환 생성 성공 후 원본 삭제 — 중간 실패 시 원본 보존). + // 상환은 원금=이체 / 이자·연회비=지출로 나눠 저장된다. 수정 시에는 기존 1건을 + // 상환 N건으로 다시 만든다(상환 생성 성공 후 원본 삭제 — 중간 실패 시 원본 보존). await accountApi.repayment({ entryDate: form.entryDate, fromWalletId: form.walletId, targetWalletId: form.toWalletId, principal, interest, + annualFee, memo: form.memo || null, }) if (editId.value) { @@ -714,7 +722,7 @@ onMounted(async () => { - +