SearchTrademark/test/database_schema.sql

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();