- 대상이 카드일 때만 연회비 입력란 노출(repayTargetIsCard) - 원금=이체·이자/연회비=지출 안내 placeholder, 검증 '원금·이자·연회비 중 하나' Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -76,8 +76,13 @@ function resetFilters() {
|
|||||||
// 추가/수정 모달
|
// 추가/수정 모달
|
||||||
const formOpen = ref(false)
|
const formOpen = ref(false)
|
||||||
const editId = ref(null)
|
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 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개월, 일시불은 빈값)
|
// 카드 지출일 때만 할부 입력 노출 (2~24개월, 일시불은 빈값)
|
||||||
const showInstallment = computed(() => form.type === 'EXPENSE' && form.walletKind === 'CARD')
|
const showInstallment = computed(() => form.type === 'EXPENSE' && form.walletKind === 'CARD')
|
||||||
const installmentMonthly = computed(() => {
|
const installmentMonthly = computed(() => {
|
||||||
@@ -365,7 +370,7 @@ function todayStr() {
|
|||||||
function openCreate() {
|
function openCreate() {
|
||||||
editId.value = null
|
editId.value = null
|
||||||
editingPending.value = false
|
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 = []
|
selectedTagIds.value = []
|
||||||
cancelAddCategory()
|
cancelAddCategory()
|
||||||
formError.value = null
|
formError.value = null
|
||||||
@@ -389,6 +394,7 @@ function openEdit(e) {
|
|||||||
toWalletId: e.toWalletId || '',
|
toWalletId: e.toWalletId || '',
|
||||||
principal: null,
|
principal: null,
|
||||||
interest: null,
|
interest: null,
|
||||||
|
annualFee: null,
|
||||||
installmentMonths: e.installmentMonths || '',
|
installmentMonths: e.installmentMonths || '',
|
||||||
})
|
})
|
||||||
// 태그 이름 → id 매핑 (현재 태그 목록 기준)
|
// 태그 이름 → id 매핑 (현재 태그 목록 기준)
|
||||||
@@ -406,7 +412,7 @@ async function submit() {
|
|||||||
formError.value = '거래일을 입력하세요.'
|
formError.value = '거래일을 입력하세요.'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 상환/납부: 원금=이체, 이자=지출 자동 분리
|
// 상환/납부: 원금=이체, 이자·연회비=지출 자동 분리
|
||||||
if (isRepayment.value) {
|
if (isRepayment.value) {
|
||||||
if (!form.walletId || !form.toWalletId) {
|
if (!form.walletId || !form.toWalletId) {
|
||||||
formError.value = '출금 계좌와 대상(대출/카드)을 선택하세요.'
|
formError.value = '출금 계좌와 대상(대출/카드)을 선택하세요.'
|
||||||
@@ -418,20 +424,22 @@ async function submit() {
|
|||||||
}
|
}
|
||||||
const principal = Number(form.principal) || 0
|
const principal = Number(form.principal) || 0
|
||||||
const interest = Number(form.interest) || 0
|
const interest = Number(form.interest) || 0
|
||||||
if (principal <= 0 && interest <= 0) {
|
const annualFee = repayTargetIsCard.value ? (Number(form.annualFee) || 0) : 0
|
||||||
formError.value = '원금 또는 이자를 입력하세요.'
|
if (principal <= 0 && interest <= 0 && annualFee <= 0) {
|
||||||
|
formError.value = '원금·이자·연회비 중 하나는 입력하세요.'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
try {
|
try {
|
||||||
// 상환은 원금=이체 / 이자=지출 2건으로 저장된다. 수정 시에는 기존 1건을
|
// 상환은 원금=이체 / 이자·연회비=지출로 나눠 저장된다. 수정 시에는 기존 1건을
|
||||||
// 상환 2건으로 다시 만든다(상환 생성 성공 후 원본 삭제 — 중간 실패 시 원본 보존).
|
// 상환 N건으로 다시 만든다(상환 생성 성공 후 원본 삭제 — 중간 실패 시 원본 보존).
|
||||||
await accountApi.repayment({
|
await accountApi.repayment({
|
||||||
entryDate: form.entryDate,
|
entryDate: form.entryDate,
|
||||||
fromWalletId: form.walletId,
|
fromWalletId: form.walletId,
|
||||||
targetWalletId: form.toWalletId,
|
targetWalletId: form.toWalletId,
|
||||||
principal,
|
principal,
|
||||||
interest,
|
interest,
|
||||||
|
annualFee,
|
||||||
memo: form.memo || null,
|
memo: form.memo || null,
|
||||||
})
|
})
|
||||||
if (editId.value) {
|
if (editId.value) {
|
||||||
@@ -714,7 +722,7 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 상환/납부: 대상(대출/카드) + 원금 + 이자 -->
|
<!-- 상환/납부: 대상(대출/카드) + 원금 + 이자 (+카드면 연회비). 원금=이체·이자/연회비=지출 -->
|
||||||
<template v-if="isRepayment">
|
<template v-if="isRepayment">
|
||||||
<label>대상(대출/카드)
|
<label>대상(대출/카드)
|
||||||
<select v-model="form.toWalletId" :disabled="submitting">
|
<select v-model="form.toWalletId" :disabled="submitting">
|
||||||
@@ -724,8 +732,9 @@ onMounted(async () => {
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label>원금<input v-model.number="form.principal" type="number" min="0" placeholder="원" :disabled="submitting" /></label>
|
<label>원금<input v-model.number="form.principal" type="number" min="0" placeholder="원 (이체로 기록)" :disabled="submitting" /></label>
|
||||||
<label>이자<input v-model.number="form.interest" type="number" min="0" placeholder="원" :disabled="submitting" /></label>
|
<label>이자<input v-model.number="form.interest" type="number" min="0" placeholder="원 (지출·분류 이자)" :disabled="submitting" /></label>
|
||||||
|
<label v-if="repayTargetIsCard">연회비<input v-model.number="form.annualFee" type="number" min="0" placeholder="원 (지출·분류 연회비)" :disabled="submitting" /></label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<label v-if="form.type === 'INCOME' || form.type === 'EXPENSE'">분류
|
<label v-if="form.type === 'INCOME' || form.type === 'EXPENSE'">분류
|
||||||
|
|||||||
Reference in New Issue
Block a user