Billing 스키마
개요
Billing 관련 테이블은 두 계층으로 구분됩니다:
| 계층 | 소유 | RLS | 설명 |
|---|---|---|---|
| 플랫폼 빌링 | Lumie ↔ 학원 | 없음 (앱 계층 접근 제어) | plans, subscriptions, invoices, billing_keys 등 |
| 학원 수납 | 학원 ↔ 학부모/학생 | 있음 (tenant_id + RLS) | guardians, tuition_invoices, tuition_payments, cash_receipts 등 |
결제 게이트웨이는 Toss Payments입니다. 직접 수납(direct-Toss tuition payment) 기능은 제거(ff9db43)되었으나 merchant_profiles 테이블은 유지됩니다.
플랫폼 빌링 ERD
플랫폼 빌링 테이블 상세
plans
사전 정의된 구독 플랜 목록입니다. custom_domains 컬럼은 V49에서 제거되었습니다 (모든 플랜에서 커스텀 도메인 지원).
| 플랜 ID | 월 가격 | 학생 수 | OMR/월 |
|---|---|---|---|
| FREE | 0원 | 제한 있음 | 제한 있음 |
| BASIC | 49,000원 | 제한 있음 | 제 한 있음 |
| PRO | 149,000원 | 제한 있음 | 제한 있음 |
| MAX | 499,000원 | 제한 있음 | 제한 있음 |
실제 한도값은
plans테이블에서 확인하세요. V51에서 ENTERPRISE → MAX 리네임.
billing_keys
Toss 자동결제 토큰 (billingKey)을 저장합니다. 테넌트당 활성 키는 1개만 허용합니다 (partial unique index: status = 'ACTIVE'). pg_billing_key는 PG사 비밀 값이므로 절대 로깅하지 않습니다.
subscriptions
테넌트 구독 상태입니다. 테넌트당 1개(UNIQUE on tenant_id).
pending_plan_id+scheduled_change_at: 다운그레이드 예약 지원 (V37)status: ACTIVE / PAUSED / PAST_DUE / CANCELLED / EXPIRED
invoices
Lumie가 학원에 발행하는 구독 청구서입니다. invoice_number는 멱등성 키 역할을 합니다.
alimtalk_credits
카카오 알림톡 크레딧 잔액입니다. balance >= 0 CHECK 제약.
payment_transactions
PG 호출 감사 로그입니다. 불변 테이블로 UPDATE/DELETE를 수행하지 않습니다.
| 컬럼 | 설명 |
|---|---|
type | BILLING_CHARGE / TUITION_PAYMENT / REFUND / BILLING_KEY_ISSUE / MERCHANT_REGISTER |
direction | REQUEST / RESPONSE / WEBHOOK |
owner_entity | INVOICE / TUITION_INVOICE / BILLING_KEY |
pg_payload | 원본 PG 요청/응답 JSONB |
billing_operation_locks
진행 중인 빌링 작업의 테넌트별 뮤텍스입니다 (V38). PK (tenant_id, operation_type)으로 동시 요청을 직렬화합니다. 완료 시 행 삭제, 15분 경과 시 스케줄러가 정리합니다.
tax_invoices
세금계산서 발행 이력입니다. buyer_business_no = 학원 사업자번호.