fix(account): 영수증 AI 힌트를 단일 필드로 전송(멀티파트 파트수 제한 회피)
Deploy / deploy (push) Failing after 13m37s

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
sb
2026-07-05 14:46:44 +09:00
parent 7e13a42848
commit e23a694675
2 changed files with 10 additions and 4 deletions
+8 -3
View File
@@ -217,23 +217,28 @@ const realApi = {
}, },
// 영수증 OCR (백엔드가 Google Vision 호출 → 전체 텍스트 반환) — AI 폴백용 // 영수증 OCR (백엔드가 Google Vision 호출 → 전체 텍스트 반환) — AI 폴백용
// suppressNetError: runOcr 이 자체 formError 로 안내하므로 전역 배너 억제
ocrReceipt(blob) { ocrReceipt(blob) {
const fd = new FormData() const fd = new FormData()
fd.append('image', blob, 'receipt.jpg') fd.append('image', blob, 'receipt.jpg')
return http.post('/account/ocr/receipt', fd, { return http.post('/account/ocr/receipt', fd, {
headers: { 'Content-Type': 'multipart/form-data' }, headers: { 'Content-Type': 'multipart/form-data' },
timeout: 30000, timeout: 30000,
suppressNetError: true,
}) })
}, },
// 영수증 AI 구조화 (Claude Vision) — 금액·상호·날짜·분류·계좌를 한 번에. 사용자 후보 목록을 함께 전달 // 영수증 AI 구조화 (Claude Vision) — 금액·상호·날짜·분류·계좌를 한 번에. 사용자 후보 목록을 함께 전달
// 비전 처리가 느릴 수 있어 타임아웃 상향, 실패 시 OCR 폴백이 있으므로 전역 배너 억제
parseReceiptAi(blob, { categoryHints = [], walletHints = [] } = {}) { parseReceiptAi(blob, { categoryHints = [], walletHints = [] } = {}) {
const fd = new FormData() const fd = new FormData()
fd.append('image', blob, 'receipt.jpg') fd.append('image', blob, 'receipt.jpg')
categoryHints.forEach((c) => fd.append('categoryHints', c)) // 멀티파트 파트 수 제한(Tomcat 기본 10) 회피: 후보를 각각 한 파트에 줄바꿈으로 합쳐 전송
walletHints.forEach((w) => fd.append('walletHints', w)) if (categoryHints.length) fd.append('categoryHints', categoryHints.join('\n'))
if (walletHints.length) fd.append('walletHints', walletHints.join('\n'))
return http.post('/account/ocr/receipt-ai', fd, { return http.post('/account/ocr/receipt-ai', fd, {
headers: { 'Content-Type': 'multipart/form-data' }, headers: { 'Content-Type': 'multipart/form-data' },
timeout: 30000, timeout: 60000,
suppressNetError: true,
}) })
}, },
} }
+2 -1
View File
@@ -34,8 +34,9 @@ http.interceptors.response.use(
} else if (status === 403 && error.response?.data?.code === 'PREMIUM_REQUIRED') { } else if (status === 403 && error.response?.data?.code === 'PREMIUM_REQUIRED') {
// 유료 전용 API 를 무료 회원이 호출(우회/직접 접근) — 업그레이드 안내 // 유료 전용 API 를 무료 회원이 호출(우회/직접 접근) — 업그레이드 안내
window.dispatchEvent(new CustomEvent('premium:required')) window.dispatchEvent(new CustomEvent('premium:required'))
} else if (!error.response && error.code !== 'ERR_CANCELED') { } else if (!error.response && error.code !== 'ERR_CANCELED' && !error.config?.suppressNetError) {
// 응답 자체가 없음 = 네트워크 오류(오프라인/타임아웃/서버 연결 불가). 취소 요청은 제외. // 응답 자체가 없음 = 네트워크 오류(오프라인/타임아웃/서버 연결 불가). 취소 요청은 제외.
// suppressNetError: 자체 폴백/에러표시가 있는 호출(예: 영수증 AI)은 전역 배너를 띄우지 않음.
window.dispatchEvent(new CustomEvent('net:error')) window.dispatchEvent(new CustomEvent('net:error'))
} }
return Promise.reject(error) return Promise.reject(error)