Skip to content

FE handoff — 상품 선택·결제·워크스페이스 활성화

기준 흐름

  • 계정 생성 확인 → /onboarding/products
  • 업무 프리셋 선택 → 상품별 추가/제거 → 사용 규모 입력
  • 월 공급가액·VAT·합계 및 결제 방법 확인
  • 활성화 성공 → /workspace/home
  • 워크스페이스 사이드바는 entitlement가 있는 모듈만 렌더링
  • 사이드바 상품 관리에서 같은 구성 화면으로 재진입
  • 기존 고객 진입은 /onboarding/products?mode=manage이며 현재 Organization 유효 계약 상품을 편집 초깃값으로 사용
  • 이 경로는 administration/app-view의 자식으로 등록되어 계정·계약 헤더와 aside를 유지한다.
  • 상품 추가는 즉시, 제거는 다음 결제일 예약 변경으로 구분해 표시
  • 신규 Organization의 기본 결제 방법은 invoice이며 저장된 결제수단 조회가 연결되기 전에는 임의의 카드를 표시하지 않는다.
  • 화면의 Organization 명칭은 useAccountContext().organization에서 읽고 Goldnus 문자열을 고정하지 않는다.
  • 레거시 결제수단·결제내역·계약현황 라우트는 가짜 카드와 계약을 렌더하지 않고 /onboarding/products?mode=manage로 redirect한다. administration aside에는 단일 상품·계약 관리 항목만 노출한다.
  • 정상 승인·결제 실패·활성화 지연 제어는 ?qa=1에서만 노출하고 일반 고객 화면에서는 숨긴다.

계정별 출시 검수 노출

src/composables/productCatalog.jsimplementationStage가 기술 준비도 SSOT다. src/composables/prototypeOrganizationAccess.js가 principal의 Organization slug/email을 full-preview | implemented-only | entitlement 프로필로 해석하고, useModuleSubscription()이 아래 소비 표면을 제공한다.

표시명과 한·영 용어는 src/composables/productVocabulary.js가 SSOT다. PRODUCT_VOCABULARY의 21개 포트폴리오와 PRODUCT_MODULES의 실행 상품을 합치지 않는다. candidate 어휘를 메뉴·주문·route guard에 자동 노출하면 안 된다.

상품 카드는 한국어 product.name을 제목으로, product.englishName을 바로 아래 subtitle-sm text-neutral-moderate 보조 텍스트로 표시한다. 별도 로컬 CSS나 색상값을 만들지 않는다. 분류는 5개 도메인을 기본으로 하고, 프로퍼티는 PRODUCT_GROUPS의 거래·분양과 운영 제품군을 한 단계 더 사용한다.

  • availableProducts, availableBundles: 상품 선택·Workspace 생성에 사용할 노출 허용 목록
  • enabledModules: 워크스페이스 메뉴와 상품 route guard가 사용할 활성 목록
  • hasFullPreviewAccess: CRM 등 catalog 밖 preview 앱 판정
  • isProductExposed(key): hidden product mutation 방지

Goldnus Organization Owner는 Owner 이메일 로그인에서 server-core 상품 전체를 활성화해 검수한다. Goldnus 직원은 노출 필터 뒤 기존 Workspace module 배정을 계속 적용한다. Leysys는 catalog 전체와 preview 앱을 검수한다. 일반 계정은 기존 entitlement 흐름을 유지한다.

적용 위치는 워크스페이스 홈 HomePag.vue, aside AppAsideOrg.vue, 상품 선택 ProductOnboardingPag.vue, Workspace 생성 SheetCreateWorkspaceArt.vue, AI 비서 링크 AssistantMainOrg.vue, authSession.js route guard다. /crm, /notice, /complaint, /access-control, /calendar, /buildingrequiresFullPreviewForPath()를 통과한 Leysys 프로필에서만 직접 열 수 있다.

상품 변경 시 화면에 보이지 않는 기존 module key를 제거 목록으로 해석하면 안 된다. useProductOnboarding()currentVisibleModules만 사용자 draft와 비교하고 preservedHiddenModules + draftModules를 서버 checkout의 desired set으로 보낸다. 숨은 상품 토글 입력도 무시한다.

prototype 구현 표면

  • 카탈로그/프리셋/권한: src/composables/useModuleSubscription.js
  • 구성/가격/결제 상태: src/composables/useProductOnboarding.js
  • Supabase seam: src/composables/productSubscriptionRepo.js
  • 화면: src/components/onboarding/products/ProductOnboardingPag.vue
  • 라우트 셸: src/router/index.js의 administration 자식 /onboarding/products; 화면 루트는 중첩된 <main>을 피하기 위해 일반 <div>를 사용한다.
  • 메뉴 게이트: src/components/workspace/AppAsideOrg.vue
  • 단계 표시: src/registry/vue/stepper/* (leysys-design EDS 정본 소비)
  • 추천 구성은 radio radio-card radio-md radio-primary, 개별 상품은 checkbox checkbox-card checkbox-md checkbox-primary 정본을 사용한다. 두 표면 모두 bg-neutral-minimal을 명시하고, 선택 상태를 별도 ring-2로 중첩하지 않는다.
  • 상품 구성 단계의 우측 요약은 card card-md card-filled card-inset-edged 한 개로 구성한다. 모바일에서는 상품 목록 아래로 이동하고 데스크톱에서는 lg:sticky 사이드 카드로 유지한다.
  • quantities.unitsquantities.usersinput-group의 짧은 숫자 입력과 inline-end 단위(, )로 표시한다. inputmode="numeric", min="1", step="1"을 유지한다.
  • 같은 카드에서 선택 상품 수와 combinedEstimatedTotal의 VAT 포함 월 예상 이용료를 표시한다. 단계 2의 결제 확인하기이전도 card footer가 소유하며, 페이지 공용 footer는 단계 2에서 렌더하지 않는다.
  • contract-management는 독립 상품이다. contract-billingPRODUCT_MODULES, Workspace, route entitlement guard에 등록하지 않는다. Billing Core에는 별도 entitlement가 없다.
  • 과거 /contract-billing/* URL은 호환 route 하나에서 /sales/console/transaction으로 redirect한다. 이 route에는 moduleKey: contract-billing이나 전용 component를 다시 추가하지 않는다.
  • 화면에는 임대차관리, 회계증빙관리, 전자문서 발행, 판매·매출채권, 구매·매입채무, 고정자산관리, 고객관계관리를 정식명으로 사용한다.
  • 영문 UI는 Facility Management, Sales & Accounts Receivable, Procurement & Accounts Payable, Source Document Management, Workflow & Approvals를 사용한다.
  • 실행 제품 accounting-source-documents/accounting-source-documents/, accountingSourceDocument*, accounting_source_documents를 같은 도메인 식별자로 사용하며 finance*taxEvidence* alias를 만들지 않는다.
  • supporting-documents는 별도 후보 제품이다. 실행 catalog·route·entitlement에 자동 추가하지 않는다.
  • contract-to-cashcontract-managementsales를 함께 선택하는 편의 preset이다. 화면 아이콘은 EDS/Material 공식 contract 심볼을 사용하며 별도 로컬 아이콘을 만들지 않는다.
  • 판매·매출채권, 관리비관리, 임대차관리는 Billing Core의 EDS 패턴과 순수 계산 capability를 재사용할 수 있지만 서로의 store·원장·RPC를 공유하지 않는다. 경계 정본은 docs/decisions/BILLING-FAMILY-BOUNDED-CONTEXTS-2026-07-19.md다.

Supabase 환경에서는 현재 Organization과 실제 Workspace UUID로 catalog·organization_product_contracts를 읽고 organization_effective_product_contract_items·workspace_effective_module_entitlements RPC를 호출한다. 첫 RPC의 Organization 계약 상품이 변경 화면의 current/desired set이며, 둘째 RPC의 현재 Workspace 배정은 메뉴·route capability를 hydrate하는 별도 정본이다. 두 RPC는 DB current_date로 계약·계약 항목·entitlement 유효기간을 교차 검증하므로 원본 organization_product_contract_itemsworkspace_module_entitlements를 프런트 read contract로 사용하지 않는다. Vitest 또는 Supabase env가 없는 환경만 mock repository를 사용한다. canonical entitlement hydrate 이후에도 isModuleEnabled(key) 소비 표면은 유지한다. 실제품에서는 라우트 자체에도 entitlement guard를 추가해 URL 직접 입력을 차단해야 한다.

Organization 상품 추가는 checkout 대상 Workspace에 자동 배정하지만 기존 계약 상품(keep)의 다른 Workspace 배정은 바꾸지 않는다. 다른 Workspace가 사용 중인 상품 제거가 module_in_use_by_other_workspace로 거부되면 해당 Workspace 배정을 먼저 해제하도록 안내한다. 예약 제거일은 exclusive 경계라 그 날짜부터 메뉴 접근이 닫힌다.

구현된 예외 상태

  • payment_failed: 결제 단계 유지, 오류 Alert와 재시도 제공
  • provisioning: 완료 단계에서 지연 상태 표시, 기존 entitlement 유지
  • active: 신규 구독 활성화 또는 계약 변경 접수 완료
  • 기존 고객 제거: pendingChange.effectiveAt까지 메뉴 접근 유지

UX 후속 검증

  • 모바일에서 노출 상품 탐색 밀도와 요약 카드까지의 스크롤 길이. 선택 카드는 흰 표면과 1px 상태 테두리를 유지해야 한다.
  • 프리셋 변경 시 사용자가 직접 조정한 상품을 덮어쓸지 확인하는 규칙
  • 실제 계약 API 기준의 일할 과금·크레딧 금액 표시
  • 관리자 승인 대기와 결제수단 변경 sheet
  • provisioning 상태 polling, timeout, 재시도 및 알림

셸 회귀 검증

  • src/router/__tests__/globalIaIntegrity.spec.js에서 /onboarding/products의 matched route chain에 administration layout이 포함되는지 검사한다.
  • 데스크톱·모바일에서 워크스페이스 상품·계약 관리 진입 후 계정·계약 메뉴와 Leyve 홈이 유지되어야 한다.
  • productCatalog.spec.js, prototypeOrganizationAccess.spec.js, workspaceNav.spec.js, moduleRouteAccess.spec.js, authSession.spec.js, useProductOnboarding.spec.js가 준비도 분류, 계정 프로필, 메뉴·직접 URL, 숨은 entitlement 보존을 고정한다.