- 로또 서비스 페이지: 토스 정책으로 숨겼던 페이지를 PortOne 전환에 맞춰 복원 - 사주 상세 해석 가격: 4,900원 → 1,000원 (lib/products.ts, UI, schema.sql) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
149 lines
6.4 KiB
PL/PgSQL
149 lines
6.4 KiB
PL/PgSQL
-- ============================================================
|
|
-- 쟁승메이드 Supabase 스키마
|
|
-- Supabase SQL Editor에서 순서대로 실행하세요
|
|
-- ============================================================
|
|
|
|
-- ① profiles (유저 프로필 - auth.users와 연결)
|
|
create table public.profiles (
|
|
id uuid references auth.users(id) on delete cascade primary key,
|
|
email text,
|
|
full_name text,
|
|
avatar_url text,
|
|
created_at timestamptz default now(),
|
|
updated_at timestamptz default now()
|
|
);
|
|
|
|
-- 신규 가입 시 profiles 자동 생성 트리거
|
|
create or replace function public.handle_new_user()
|
|
returns trigger as $$
|
|
begin
|
|
insert into public.profiles (id, email, full_name, avatar_url)
|
|
values (
|
|
new.id,
|
|
new.email,
|
|
new.raw_user_meta_data->>'full_name',
|
|
new.raw_user_meta_data->>'avatar_url'
|
|
);
|
|
return new;
|
|
end;
|
|
$$ language plpgsql security definer;
|
|
|
|
create or replace trigger on_auth_user_created
|
|
after insert on auth.users
|
|
for each row execute procedure public.handle_new_user();
|
|
|
|
-- RLS
|
|
alter table public.profiles enable row level security;
|
|
create policy "본인 프로필 조회" on public.profiles for select using (auth.uid() = id);
|
|
create policy "본인 프로필 수정" on public.profiles for update using (auth.uid() = id);
|
|
|
|
|
|
-- ② saju_records (사주 분석 결과 저장)
|
|
create table public.saju_records (
|
|
id bigint generated by default as identity primary key,
|
|
user_id uuid references public.profiles(id) on delete cascade,
|
|
saju_data jsonb not null, -- SajuData JSON
|
|
interpretation text, -- AI 해석 Markdown
|
|
is_paid boolean default false, -- 유료 결제 여부
|
|
created_at timestamptz default now()
|
|
);
|
|
|
|
alter table public.saju_records enable row level security;
|
|
create policy "본인 사주 기록 조회" on public.saju_records for select using (auth.uid() = user_id);
|
|
create policy "본인 사주 기록 생성" on public.saju_records for insert with check (auth.uid() = user_id);
|
|
|
|
|
|
-- ③ products (판매 상품 정의)
|
|
create table public.products (
|
|
id text primary key, -- 예: 'saju_basic', 'saju_detail'
|
|
name text not null, -- 상품명
|
|
description text,
|
|
price integer not null, -- 원 단위
|
|
category text not null, -- 'saju' | 'lotto' | 'subscription'
|
|
is_active boolean default true,
|
|
created_at timestamptz default now()
|
|
);
|
|
|
|
-- 초기 상품 데이터
|
|
insert into public.products (id, name, description, price, category) values
|
|
('saju_detail', 'AI 사주 상세 리포트', '신강/신약, 용신, 대운, AI 12가지 항목 해석', 1000, 'saju'),
|
|
('lotto_gold', '로또 골드 플랜', '매주 1회 번호 추천 · 이메일 발송', 900, 'lotto'),
|
|
('lotto_platinum', '로또 플래티넘 플랜', '매주 3회 번호 + 상세 분석 + 텔레그램 알림', 2900, 'lotto'),
|
|
('lotto_diamond', '로또 다이아 플랜', '횟수 무제한 + 전체 기능 + 연간 패턴 리포트', 9900, 'lotto');
|
|
|
|
|
|
-- ④ orders (주문 - 결제 전 생성)
|
|
create table public.orders (
|
|
id uuid default gen_random_uuid() primary key,
|
|
user_id uuid references public.profiles(id) on delete set null,
|
|
product_id text references public.products(id),
|
|
amount integer not null,
|
|
status text default 'pending', -- 'pending' | 'paid' | 'failed' | 'cancelled'
|
|
metadata jsonb, -- 추가 정보 (saju_record_id 등)
|
|
created_at timestamptz default now(),
|
|
updated_at timestamptz default now()
|
|
);
|
|
|
|
alter table public.orders enable row level security;
|
|
create policy "본인 주문 조회" on public.orders for select using (auth.uid() = user_id);
|
|
create policy "본인 주문 생성" on public.orders for insert with check (auth.uid() = user_id);
|
|
|
|
|
|
-- ⑤ payments (결제 완료 내역 - 서버에서 검증 후 저장)
|
|
create table public.payments (
|
|
id uuid default gen_random_uuid() primary key,
|
|
user_id uuid references public.profiles(id) on delete set null,
|
|
order_id uuid references public.orders(id),
|
|
product_name text not null,
|
|
amount integer not null,
|
|
status text default 'paid', -- 'paid' | 'refunded' | 'partial_refund'
|
|
pg_provider text, -- 'toss' | 'portone'
|
|
pg_payment_key text unique, -- PG사 결제 키
|
|
created_at timestamptz default now()
|
|
);
|
|
|
|
alter table public.payments enable row level security;
|
|
create policy "본인 결제 내역 조회" on public.payments for select using (auth.uid() = user_id);
|
|
|
|
|
|
-- ⑥ contact_requests (외주/서비스 문의 내역)
|
|
create table public.contact_requests (
|
|
id uuid default gen_random_uuid() primary key,
|
|
user_id uuid references public.profiles(id) on delete set null,
|
|
email text not null,
|
|
name text,
|
|
service text not null, -- 문의 서비스 종류
|
|
message text not null,
|
|
status text default 'pending', -- 'pending' | 'in_progress' | 'completed'
|
|
created_at timestamptz default now()
|
|
);
|
|
|
|
alter table public.contact_requests enable row level security;
|
|
create policy "본인 의뢰 내역 조회" on public.contact_requests for select using (auth.uid() = user_id);
|
|
create policy "누구나 의뢰 생성" on public.contact_requests for insert with check (true);
|
|
|
|
|
|
-- ⑦ service_settings (서비스 노출 on/off 관리자 설정)
|
|
create table public.service_settings (
|
|
id text primary key, -- 서비스 ID: 'saju', 'lotto', 'stock', ...
|
|
name text not null,
|
|
description text,
|
|
is_active boolean default true,
|
|
order_index integer default 0,
|
|
updated_at timestamptz default now()
|
|
);
|
|
|
|
-- 초기 서비스 데이터
|
|
insert into public.service_settings (id, name, description, is_active, order_index) values
|
|
('saju', 'AI 사주 분석', '사주 입력 및 AI 해석 서비스', true, 1),
|
|
('lotto', '로또 번호 추천', '빅데이터 기반 로또 번호 분석', true, 2),
|
|
('stock', '주식 자동매매', '텔레그램 연동 자동매매 프로그램', true, 3),
|
|
('automation', '업무 자동화 RPA', '반복 업무 자동화 개발', true, 4),
|
|
('prompt', '프롬프트 엔지니어링', 'AI 프롬프트 설계 서비스', true, 5),
|
|
('freelance', '외주 개발', '맞춤형 소프트웨어 개발', true, 6);
|
|
|
|
-- service_settings는 누구나 읽기 가능 (공개 서비스 목록 조회용)
|
|
alter table public.service_settings enable row level security;
|
|
create policy "누구나 서비스 설정 조회" on public.service_settings for select using (true);
|
|
-- 쓰기는 service_role(관리자)만 가능 (별도 정책 없음 = anon 불가)
|