195 lines
7.9 KiB
PL/PgSQL
195 lines
7.9 KiB
PL/PgSQL
-- 찜관리 기능을 위한 데이터베이스 스키마
|
|
|
|
-- 1. 찜 기록 테이블 (public.jjim)
|
|
CREATE TABLE IF NOT EXISTS public.jjim (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id UUID NOT NULL,
|
|
market_url TEXT NOT NULL,
|
|
market_name TEXT,
|
|
market_nickname TEXT,
|
|
zzim_count INTEGER DEFAULT 0,
|
|
zzim_type VARCHAR(20) NOT NULL CHECK (zzim_type IN ('my_market', 'mutual')),
|
|
mileage_earned INTEGER DEFAULT 0,
|
|
target_user_id UUID,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT fk_jjim_user_id FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
CONSTRAINT fk_jjim_target_user_id FOREIGN KEY (target_user_id) REFERENCES auth.users(id) ON DELETE SET NULL
|
|
);
|
|
|
|
-- 2. 사용자 마켓 통합 테이블 (public.user_markets) - 찜 관련 필드 추가
|
|
CREATE TABLE IF NOT EXISTS public.user_markets (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id UUID NOT NULL,
|
|
|
|
-- 마켓 목록 (JSONB 배열)
|
|
my_markets JSONB DEFAULT '[]'::jsonb,
|
|
|
|
-- 찜 통계 필드들 (users 테이블에서 이관)
|
|
my_zzim INTEGER DEFAULT 0, -- 받은 찜 총 개수
|
|
zzim_mile INTEGER DEFAULT 0, -- 총 마일리지
|
|
available_zzim_mile INTEGER DEFAULT 0, -- 사용 가능한 마일리지
|
|
today_zzim_count INTEGER DEFAULT 0, -- 오늘 찜한 개수
|
|
today_zzim_date DATE DEFAULT CURRENT_DATE, -- 마지막 찜한 날짜
|
|
|
|
-- 회원등급 (users 테이블과 동기화)
|
|
membership_level VARCHAR(20) DEFAULT 'basic',
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT fk_user_markets_user_id FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
CONSTRAINT unique_user_markets_user_id UNIQUE (user_id)
|
|
);
|
|
|
|
-- 3. 회원등급별 찜 제한 테이블 (public.membership_zzim_limits) - 개선
|
|
CREATE TABLE IF NOT EXISTS public.membership_zzim_limits (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
membership_level VARCHAR(20) NOT NULL UNIQUE,
|
|
|
|
-- 찜 제한 설정
|
|
daily_zzim_limit INTEGER DEFAULT 50, -- 일일 찜 제한
|
|
max_zzim_mileage INTEGER DEFAULT 500, -- 최대 마일리지 보유량
|
|
mileage_per_zzim INTEGER DEFAULT 1, -- 찜당 마일리지
|
|
|
|
-- 추가 제한 설정
|
|
max_markets INTEGER DEFAULT 5, -- 최대 등록 가능한 마켓 수
|
|
mutual_zzim_enabled BOOLEAN DEFAULT TRUE, -- 품앗이 기능 사용 가능 여부
|
|
background_zzim_enabled BOOLEAN DEFAULT FALSE, -- 백그라운드 찜 기능 사용 가능 여부
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- 4. 기본 회원등급 데이터 삽입
|
|
INSERT INTO public.membership_zzim_limits (membership_level, daily_zzim_limit, max_zzim_mileage, mileage_per_zzim, max_markets, mutual_zzim_enabled, background_zzim_enabled)
|
|
VALUES
|
|
('basic', 50, 500, 1, 3, TRUE, FALSE),
|
|
('premium', 100, 1000, 1, 10, TRUE, TRUE),
|
|
('vip', 200, 2000, 1, 20, TRUE, TRUE)
|
|
ON CONFLICT (membership_level) DO UPDATE SET
|
|
daily_zzim_limit = EXCLUDED.daily_zzim_limit,
|
|
max_zzim_mileage = EXCLUDED.max_zzim_mileage,
|
|
mileage_per_zzim = EXCLUDED.mileage_per_zzim,
|
|
max_markets = EXCLUDED.max_markets,
|
|
mutual_zzim_enabled = EXCLUDED.mutual_zzim_enabled,
|
|
background_zzim_enabled = EXCLUDED.background_zzim_enabled,
|
|
updated_at = NOW();
|
|
|
|
-- 5. 마켓 데이터 구조 예시 (my_markets JSONB 필드 내용)
|
|
/*
|
|
my_markets JSONB 예시:
|
|
[
|
|
{
|
|
"market_url": "https://smartstore.naver.com/example",
|
|
"market_name": "예시 마켓",
|
|
"market_nickname": "내 마켓",
|
|
"is_visible": true, -- 다른 사람에게 노출 여부
|
|
"for_zzim": true, -- 내 마켓 찜하기 대상 여부
|
|
"for_mutual_zzim": true, -- 품앗이 대상 여부 (새로 추가)
|
|
"zzim_received_count": 0, -- 받은 찜 개수
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"updated_at": "2024-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
*/
|
|
|
|
-- 6. 인덱스 생성
|
|
CREATE INDEX IF NOT EXISTS idx_jjim_user_id ON public.jjim(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_jjim_target_user_id ON public.jjim(target_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_jjim_created_at ON public.jjim(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_jjim_zzim_type ON public.jjim(zzim_type);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_markets_user_id ON public.user_markets(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_user_markets_membership_level ON public.user_markets(membership_level);
|
|
CREATE INDEX IF NOT EXISTS idx_user_markets_today_zzim_date ON public.user_markets(today_zzim_date);
|
|
|
|
-- 7. RLS (Row Level Security) 정책 설정
|
|
-- user_markets 테이블: 품앗이를 위해 읽기는 모든 사용자에게 허용, 쓰기는 본인만
|
|
ALTER TABLE public.user_markets ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- 본인 데이터 읽기/쓰기 허용
|
|
CREATE POLICY "Users can view and edit their own user_markets data" ON public.user_markets
|
|
FOR ALL USING (auth.uid() = user_id);
|
|
|
|
-- 품앗이를 위한 다른 사용자 데이터 읽기 허용 (민감하지 않은 정보만)
|
|
CREATE POLICY "Users can view others user_markets for mutual zzim" ON public.user_markets
|
|
FOR SELECT USING (true);
|
|
|
|
-- jjim 테이블: 본인이 한 찜 기록만 조회/수정 가능
|
|
ALTER TABLE public.jjim ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Users can view and edit their own jjim records" ON public.jjim
|
|
FOR ALL USING (auth.uid() = user_id);
|
|
|
|
-- membership_zzim_limits 테이블: 모든 사용자가 읽기 가능
|
|
ALTER TABLE public.membership_zzim_limits ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "All users can view membership limits" ON public.membership_zzim_limits
|
|
FOR SELECT USING (true);
|
|
|
|
-- 8. 데이터 마이그레이션 함수 (users 테이블에서 user_markets로 찜 데이터 이관)
|
|
CREATE OR REPLACE FUNCTION migrate_zzim_data_to_user_markets()
|
|
RETURNS void AS $$
|
|
BEGIN
|
|
-- users 테이블의 찜 관련 데이터를 user_markets로 이관
|
|
INSERT INTO public.user_markets (
|
|
user_id,
|
|
my_zzim,
|
|
zzim_mile,
|
|
available_zzim_mile,
|
|
today_zzim_count,
|
|
today_zzim_date,
|
|
membership_level
|
|
)
|
|
SELECT
|
|
id,
|
|
COALESCE(my_zzim, 0),
|
|
COALESCE(zzim_mile, 0),
|
|
COALESCE(available_zzim_mile, COALESCE(zzim_mile, 0)),
|
|
COALESCE(today_zzim_count, 0),
|
|
COALESCE(today_zzim_date, CURRENT_DATE),
|
|
COALESCE(membership_level, 'basic')
|
|
FROM auth.users
|
|
WHERE id NOT IN (SELECT user_id FROM public.user_markets)
|
|
ON CONFLICT (user_id) DO UPDATE SET
|
|
my_zzim = EXCLUDED.my_zzim,
|
|
zzim_mile = EXCLUDED.zzim_mile,
|
|
available_zzim_mile = EXCLUDED.available_zzim_mile,
|
|
today_zzim_count = EXCLUDED.today_zzim_count,
|
|
today_zzim_date = EXCLUDED.today_zzim_date,
|
|
membership_level = EXCLUDED.membership_level,
|
|
updated_at = NOW();
|
|
|
|
RAISE NOTICE 'Zzim data migration completed';
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- 9. 트리거 함수: user_markets와 users 테이블 동기화
|
|
CREATE OR REPLACE FUNCTION sync_user_markets_to_users()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
-- user_markets 테이블의 변경사항을 users 테이블에 반영
|
|
UPDATE auth.users
|
|
SET
|
|
my_zzim = NEW.my_zzim,
|
|
zzim_mile = NEW.zzim_mile,
|
|
available_zzim_mile = NEW.available_zzim_mile,
|
|
today_zzim_count = NEW.today_zzim_count,
|
|
today_zzim_date = NEW.today_zzim_date,
|
|
membership_level = NEW.membership_level
|
|
WHERE id = NEW.user_id;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- 트리거 생성
|
|
CREATE TRIGGER sync_user_markets_to_users_trigger
|
|
AFTER INSERT OR UPDATE ON public.user_markets
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION sync_user_markets_to_users();
|
|
|
|
-- 10. 마이그레이션 실행 (주석 해제하여 실행)
|
|
-- SELECT migrate_zzim_data_to_user_markets(); |