From 1a85e448aa10a45241a43bf605ec180d26defe45 Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Fri, 10 Jul 2026 00:32:49 +0900 Subject: [PATCH] =?UTF-8?q?feat(shop):=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=94?= =?UTF-8?q?=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - accountApi: shopStatus(), buyShopItem(item) 추가; buyShopItem은 DEMO_WRITES에 등록 - router: /settings/shop → ShopView.vue 라우트 추가 - ShopView.vue: 포인트 잔액·상품 카드(계좌 슬롯/AI 통계) 구매 화면, PREMIUM 회원 안내 분기 - AccountInfoView: '기프트콘 교환' → '포인트 상점' 로 이름 변경 + 클릭 시 /settings/shop 이동 - AccountDashboardView: AI 코멘트 402 응답 시 크레딧 소진 안내 + 상점 이동 버튼 노출 - LAUNCH-PROGRESS: 포인트 상점 ✅ 완료 표시, 다음 재개 지점 현행화 Co-Authored-By: Claude Sonnet 4.6 --- brand/LAUNCH-PROGRESS.md | 29 +- src/api/accountApi.js | 10 +- src/router/index.js | 6 + src/views/account/AccountDashboardView.vue | 37 ++- src/views/settings/AccountInfoView.vue | 11 +- src/views/settings/ShopView.vue | 351 +++++++++++++++++++++ 6 files changed, 419 insertions(+), 25 deletions(-) create mode 100644 src/views/settings/ShopView.vue diff --git a/brand/LAUNCH-PROGRESS.md b/brand/LAUNCH-PROGRESS.md index 8b15736..3a85569 100644 --- a/brand/LAUNCH-PROGRESS.md +++ b/brand/LAUNCH-PROGRESS.md @@ -139,14 +139,12 @@ ## 📌 남은 백로그 (출시 후 업데이트) 1. **앱 업데이트 안내** — 새 버전 알림 + 구글플레이 바로가기 2. (선택) 첫 실행 온보딩 / Play 인앱 리뷰 / 생체 인증 -3. **조직 계정 전환 + 기프트콘 교환** — 사업자등록→DUNS→앱이전, B2B 기프트콘 매입 -4. **포인트 상점 (사용량·슬롯 판매)** — 견적 ~1~1.5일. 무료회원 대상, 유료회원은 무제한. - - **AI 텍스트 입력**(`/entries/parse`): 월 5회 무료 + **추가 10회 = 300P** - - **OCR 영수증 인식**(`/ocr/receipt-ai`): 월 3회 무료 + **추가 10회 = 500P** - - **계좌 슬롯**: 종류별 기본 2개(적용됨) + **500P당 +1, 최대 5개**, 구매분은 **영구** - - 설계: 월별 사용량 테이블(`ai_usage`) + 구매 크레딧(`ai_credit`) / 매 호출 전 `무료쿼터→구매크레딧→거부(충전유도)` / 구매는 PointService로 포인트 차감(+크레딧) - - 확정 필요: ①유료=무제한 ②구매팩 이월(기본은 매월 리셋) ③'1회'=AI API 호출 1건(비용 기준) ④월 1일 리셋 - - 참고: AI 호출 비용 상한 통제 효과. 지금은 `/entries/parse`가 무료·미게이트(영수증·재무코멘트는 이미 유료 게이트) → 상점 없이 단순 유료화하려면 WebConfig 1줄로도 가능 +3. **조직 계정 전환** — 사업자등록→DUNS→앱이전 +4. ✅ **포인트 상점** (2026-07-10 구현 완료) + - **계좌 슬롯**: 500P/개, 최대 3개, 영구. `extra_wallet_slots` (member 테이블) + - **AI 통계 분석**: 1000P → 10회 이용권. `ai_stat_credits` (member 테이블) + - FREE 회원이 크레딧 없이 AI 코멘트 호출 시 402 → 통계 화면에서 상점 안내 + - PREMIUM 회원은 AI 코멘트 무제한 (크레딧 불필요) ### 🤖 AI 기능 — ✅ 구현·배포 완료 (2026-07-05) - 백엔드: `AiEntryParser`(Claude Haiku 4.5, raw HTTP `/v1/messages`), 키는 서버 `/opt/sb-backend/.env`(`ANTHROPIC_API_KEY`), 실패/미설정 시 규칙기반·Google Vision OCR 폴백. @@ -169,12 +167,9 @@ ## 다음 세션 재개 지점 0. ✅ **[해결] 화면 가로 밀림/잘림** — 진짜 원인은 **iOS input 자동확대**였음(모달·CSS 아님). - viewport에 maximum-scale 없어 16px 미만 input 포커스 시 페이지 확대→우측 잘림. `maximum-scale=1.0, user-scalable=no` 추가로 해결(ec130e8). *교훈: "모든 화면 input 포커스 시 동일" = iOS 줌 의심.* -1. **테스터 12명 opt-in 진행상황 확인**(업체 의뢰) → 12명 + 14일 연속 충족되면 **프로덕션 액세스 신청**(`production-access-draft.md`) -2. **v4 AAB 비공개 트랙 업로드** — versionCode 4(1.0.3) 빌드 완료, Play Console 업로드 대기 - - ⚠️ 2026-07-07 추가분(정기결제·계좌개편·상환조회·월상환금 등)은 **웹·서버 배포 완료** — 다음 AAB에 포함해 빌드 -3. **포인트 상점** — 견적 ~1~1.5일. 착수 전 정책 4가지 확정 필요: - - ①유료 회원 = AI 무제한 여부 ②구매 크레딧 이월 vs 매월 리셋 ③1회=API 호출 1건 ④리셋 기준일=월 1일 -4. **DUNS 발급 대기** → 발급 시 Play Console 개인사업자 계정 전환 마저 진행 -5. (선택) **음성 전용 🎤 버튼** — `@capacitor-community/speech-recognition`(현재는 iOS 키보드 받아쓰기로 대체 가능) -6. **iOS(App Store) 트랙** — 실기기 빌드 확인 완료. 애플 개발자 승인·번들ID·App Store 심사는 Play와 독립 진행 +1. **테스터 12명 opt-in 진행상황 확인**(업체 의뢰) → 12명 + 14일 연속 충족되면 **프로덕션 액세스 신청** +2. **v5 AAB 비공개 트랙 업로드** — versionCode 5(1.0.4) 빌드 완료, Play Console 업로드 대기 + - 포인트 상점 포함 이번 작업분 서버 배포 확인 후 AAB 업로드 +3. **DUNS 발급 대기** → 발급 시 Play Console 개인사업자 계정 전환 +4. (선택) **음성 전용 🎤 버튼** — `@capacitor-community/speech-recognition` +5. **iOS(App Store) 트랙** — 실기기 빌드 확인 완료. 애플 개발자 승인·번들ID·App Store 심사는 Play와 독립 진행 diff --git a/src/api/accountApi.js b/src/api/accountApi.js index 8b2e2b3..536e322 100644 --- a/src/api/accountApi.js +++ b/src/api/accountApi.js @@ -225,6 +225,14 @@ const realApi = { return http.delete('/account/all') }, + // 포인트 상점 — 현황 조회 / 아이템 구매 + shopStatus() { + return http.get('/account/shop/status') + }, + buyShopItem(item) { + return http.post('/account/shop/buy', { item }) + }, + // 영수증 OCR (백엔드가 Google Vision 호출 → 전체 텍스트 반환) — AI 폴백용 // suppressNetError: runOcr 이 자체 formError 로 안내하므로 전역 배너 억제 ocrReceipt(blob) { @@ -271,7 +279,7 @@ const DEMO_WRITES = new Set([ 'createRecurring', 'updateRecurring', 'removeRecurring', 'runRecurrings', 'createWallet', 'updateWallet', 'removeWallet', 'reorderWallets', 'createCategory', 'updateCategory', 'removeCategory', 'reorderCategories', 'importCategories', - 'createTag', 'updateTag', 'removeTag', 'reorderTags', 'confirmEntry', 'ocrReceipt', 'parseReceiptAi', 'aiComment', 'restore', 'deleteAllData', + 'createTag', 'updateTag', 'removeTag', 'reorderTags', 'confirmEntry', 'ocrReceipt', 'parseReceiptAi', 'aiComment', 'restore', 'deleteAllData', 'buyShopItem', 'createBudget', 'updateBudget', 'removeBudget', 'setExpectedIncome', 'createHolding', 'updateHolding', 'removeHolding', 'addTrade', 'updateTrade', 'removeTrade', 'refreshPrices', 'refreshAllPrices', diff --git a/src/router/index.js b/src/router/index.js index 20b35f0..70d8c35 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -213,6 +213,12 @@ const router = createRouter({ component: () => import('../views/settings/ProfileEditView.vue'), meta: { requiresAuth: true }, }, + { + path: '/settings/shop', + name: 'settings-shop', + component: () => import('../views/settings/ShopView.vue'), + meta: { requiresAuth: true }, + }, ], }) diff --git a/src/views/account/AccountDashboardView.vue b/src/views/account/AccountDashboardView.vue index 4768cd2..0413196 100644 --- a/src/views/account/AccountDashboardView.vue +++ b/src/views/account/AccountDashboardView.vue @@ -1,8 +1,11 @@ + +