fix: 투자 소수점 매수 금액 입력 모드 추가
CI / build (push) Failing after 15m19s

- 매매 모달에 '입력 방식: 단가/금액' 선택 추가
- 금액 모드: 수량+총금액 입력 → 단가=round(금액/수량) 자동계산 (소수점 매수)
- 예) 0.6주를 10,000원에 매수 시 6,000원이 아니라 10,000원으로 정확히 기록
- 단가/금액 상호 미리보기 표시

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ByungCheol
2026-06-03 17:44:01 +09:00
parent 68dd926cce
commit 41d6f11531
+39 -6
View File
@@ -1,5 +1,5 @@
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { computed, onMounted, reactive, ref } from 'vue'
import { accountApi } from '@/api/accountApi'
import IconBtn from '@/components/ui/IconBtn.vue'
@@ -19,10 +19,25 @@ const hError = ref(null)
// 매매 모달
const tradeModal = ref(false)
const tradeHolding = ref(null)
const tForm = reactive({ tradeType: 'BUY', tradeDate: '', quantity: null, price: null, fee: null })
// inputMode: 'PRICE'(수량×단가) | 'AMOUNT'(수량+총금액 → 단가 자동계산, 소수점 매수용)
const tForm = reactive({ tradeType: 'BUY', tradeDate: '', quantity: null, price: null, amount: null, fee: null, inputMode: 'PRICE' })
const tSubmitting = ref(false)
const tError = ref(null)
const tradeQty = computed(() => Number(tForm.quantity) || 0)
// 실제 저장에 쓰는 단가(원/주). 금액 모드면 총금액÷수량을 반올림.
const tradePrice = computed(() => {
if (tForm.inputMode === 'AMOUNT') {
return tradeQty.value > 0 ? Math.round((Number(tForm.amount) || 0) / tradeQty.value) : 0
}
return Number(tForm.price) || 0
})
// 표시용 총 거래금액
const tradeAmount = computed(() => {
if (tForm.inputMode === 'AMOUNT') return Number(tForm.amount) || 0
return Math.round(tradeQty.value * (Number(tForm.price) || 0))
})
// 매매이력 드롭다운
const openTradesId = ref(null)
const tradesByHolding = reactive({})
@@ -107,7 +122,7 @@ async function removeHolding(h) {
/* ===== 매매 ===== */
function openTrade(h, type) {
tradeHolding.value = h
Object.assign(tForm, { tradeType: type, tradeDate: todayStr(), quantity: null, price: h.currentPrice ?? null, fee: null })
Object.assign(tForm, { tradeType: type, tradeDate: todayStr(), quantity: null, price: h.currentPrice ?? null, amount: null, fee: null, inputMode: 'PRICE' })
tError.value = null
tradeModal.value = true
}
@@ -117,7 +132,12 @@ async function submitTrade() {
tError.value = '수량을 입력하세요.'
return
}
if (tForm.price == null || tForm.price < 0) {
if (tForm.inputMode === 'AMOUNT') {
if (!tForm.amount || tForm.amount <= 0) {
tError.value = '금액을 입력하세요.'
return
}
} else if (tForm.price == null || tForm.price < 0) {
tError.value = '단가를 입력하세요.'
return
}
@@ -126,7 +146,7 @@ async function submitTrade() {
tradeType: tForm.tradeType,
tradeDate: tForm.tradeDate,
quantity: Number(tForm.quantity),
price: Number(tForm.price),
price: tradePrice.value,
fee: tForm.fee ? Number(tForm.fee) : 0,
}
try {
@@ -266,7 +286,20 @@ onMounted(load)
</label>
<label>거래일<input v-model="tForm.tradeDate" type="date" :disabled="tSubmitting" /></label>
<label>수량()<input v-model.number="tForm.quantity" type="number" min="0" step="any" inputmode="decimal" placeholder="예: 0.5 / 1.25 (소수점 가능)" :disabled="tSubmitting" /></label>
<label>단가()<input v-model.number="tForm.price" type="number" min="0" :disabled="tSubmitting" /></label>
<label>입력 방식
<select v-model="tForm.inputMode" :disabled="tSubmitting">
<option value="PRICE">단가로 입력</option>
<option value="AMOUNT">금액으로 입력 (소수점 매수)</option>
</select>
</label>
<label v-if="tForm.inputMode === 'PRICE'">단가()
<input v-model.number="tForm.price" type="number" min="0" :disabled="tSubmitting" />
<small v-if="tradeQty > 0 && tForm.price" class="pf-hint"> {{ won(tradeAmount) }}</small>
</label>
<label v-else>금액(, )
<input v-model.number="tForm.amount" type="number" min="0" placeholder="이 금액어치 매매" :disabled="tSubmitting" />
<small v-if="tradeQty > 0 && tForm.amount" class="pf-hint">단가 {{ won(tradePrice) }}</small>
</label>
<label>수수료/세금<input v-model.number="tForm.fee" type="number" min="0" placeholder="(선택)" :disabled="tSubmitting" /></label>
<p v-if="tForm.tradeType === 'SELL'" class="pf-hint">보유 {{ shares(tradeHolding?.quantity) }} · 평단 {{ won(tradeHolding?.avgPrice) }}</p>
<p v-if="tError" class="pf-msg err">{{ tError }}</p>