feat: xavis ai_platform 기능 이전 및 ncue 환경 전환
xavis 소스·DB 스키마·활용사례/F-Scan/프롬프트 라이브러리 등 기능 반영. @xavis.co.kr → @ncue.net, 관리자 토큰 ncue-admin, 런타임 data/ Git 추적 제외. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
134
db/schema.sql
134
db/schema.sql
@@ -106,11 +106,11 @@ BEFORE UPDATE ON ax_assignments
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_ax_assignments_updated_at();
|
||||
|
||||
-- OPS 이메일(@xavis.co.kr) 매직 링크 인증 — 이벤트 감사 로그
|
||||
-- OPS 이메일(@ncue.net) 매직 링크 인증 — 이벤트 감사 로그
|
||||
CREATE TABLE IF NOT EXISTS ops_email_auth_events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(320) NOT NULL,
|
||||
event_type VARCHAR(40) NOT NULL CHECK (event_type IN ('magic_link_requested', 'login_success', 'logout')),
|
||||
event_type VARCHAR(40) NOT NULL CHECK (event_type IN ('magic_link_requested', 'login_success', 'logout', 'sessions_revoked')),
|
||||
ip_address VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
return_to TEXT,
|
||||
@@ -126,11 +126,18 @@ CREATE TABLE IF NOT EXISTS ops_email_users (
|
||||
email VARCHAR(320) PRIMARY KEY,
|
||||
first_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_login_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
login_count INTEGER NOT NULL DEFAULT 0
|
||||
login_count INTEGER NOT NULL DEFAULT 0,
|
||||
sessions_revoked_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ops_email_users_last_login ON ops_email_users (last_login_at DESC);
|
||||
|
||||
ALTER TABLE ops_email_users ADD COLUMN IF NOT EXISTS sessions_revoked_at TIMESTAMPTZ;
|
||||
|
||||
ALTER TABLE ops_email_auth_events DROP CONSTRAINT IF EXISTS ops_email_auth_events_event_type_check;
|
||||
ALTER TABLE ops_email_auth_events ADD CONSTRAINT ops_email_auth_events_event_type_check
|
||||
CHECK (event_type IN ('magic_link_requested', 'login_success', 'logout', 'sessions_revoked'));
|
||||
|
||||
-- 회의록 AI: 이메일(OPS 세션) 기반 사용자·프롬프트·회의 저장
|
||||
CREATE TABLE IF NOT EXISTS meeting_ai_users (
|
||||
email VARCHAR(320) PRIMARY KEY,
|
||||
@@ -295,3 +302,124 @@ CREATE TABLE IF NOT EXISTS mgmt_perf_snapshots (
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mgmt_perf_snapshots_upload ON mgmt_perf_snapshots (upload_id);
|
||||
|
||||
-- AI 활용 사례: 일반 사용자 제출(글쓰기) — 본문 4섹션·썸네일·첨부, 제출자 이메일·시각
|
||||
CREATE TABLE IF NOT EXISTS ai_use_case_submissions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
submitter_email VARCHAR(320) NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
situation TEXT NOT NULL DEFAULT '',
|
||||
task_goal TEXT NOT NULL DEFAULT '',
|
||||
action_taken TEXT NOT NULL DEFAULT '',
|
||||
result_outcome TEXT NOT NULL DEFAULT '',
|
||||
tags TEXT[] NOT NULL DEFAULT '{}',
|
||||
thumbnail_relative_path TEXT,
|
||||
thumbnail_files JSONB NOT NULL DEFAULT '[]',
|
||||
attachment_files JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_use_case_submissions_created ON ai_use_case_submissions (created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_use_case_submissions_submitter ON ai_use_case_submissions (submitter_email, created_at DESC);
|
||||
|
||||
CREATE OR REPLACE FUNCTION set_ai_use_case_submissions_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_ai_use_case_submissions_updated_at ON ai_use_case_submissions;
|
||||
CREATE TRIGGER trg_ai_use_case_submissions_updated_at
|
||||
BEFORE UPDATE ON ai_use_case_submissions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_ai_use_case_submissions_updated_at();
|
||||
|
||||
-- 썸네일 다중 업로드(최대 5): 기존 DB 마이그레이션
|
||||
ALTER TABLE ai_use_case_submissions
|
||||
ADD COLUMN IF NOT EXISTS thumbnail_files JSONB NOT NULL DEFAULT '[]';
|
||||
|
||||
UPDATE ai_use_case_submissions
|
||||
SET thumbnail_files = jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'originalName', COALESCE(NULLIF(regexp_replace(thumbnail_relative_path, '^.+/', ''), ''), 'thumbnail'),
|
||||
'relativePath', thumbnail_relative_path
|
||||
)
|
||||
)
|
||||
WHERE thumbnail_relative_path IS NOT NULL
|
||||
AND btrim(thumbnail_relative_path) <> ''
|
||||
AND (thumbnail_files IS NULL OR thumbnail_files = '[]'::jsonb);
|
||||
|
||||
-- AI 활용 사례 제출: 페이지뷰 조회수(제출자 본인 로그인 조회 제외) · 좋아요
|
||||
ALTER TABLE ai_use_case_submissions
|
||||
ADD COLUMN IF NOT EXISTS view_count INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
-- (legacy) 초기 unique 조회 추적용 — 현재 집계는 view_count 페이지뷰만 사용
|
||||
CREATE TABLE IF NOT EXISTS ai_use_case_views (
|
||||
submission_id UUID NOT NULL REFERENCES ai_use_case_submissions(id) ON DELETE CASCADE,
|
||||
viewer_email VARCHAR(320) NOT NULL,
|
||||
viewed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (submission_id, viewer_email)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_use_case_views_submission ON ai_use_case_views (submission_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_use_case_submission_likes (
|
||||
submission_id UUID NOT NULL REFERENCES ai_use_case_submissions(id) ON DELETE CASCADE,
|
||||
user_email VARCHAR(320) NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (submission_id, user_email)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_use_case_submission_likes_submission
|
||||
ON ai_use_case_submission_likes (submission_id);
|
||||
|
||||
-- 프롬프트 라이브러리: 공식 템플릿(company-prompts.json id) + 커뮤니티 공유 글에 대한 좋아요
|
||||
CREATE TABLE IF NOT EXISTS prompt_likes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_email VARCHAR(320) NOT NULL,
|
||||
target_kind VARCHAR(20) NOT NULL CHECK (target_kind IN ('official', 'community')),
|
||||
target_id VARCHAR(200) NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_prompt_likes_user_target UNIQUE (user_email, target_kind, target_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_prompt_likes_target ON prompt_likes (target_kind, target_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_prompt_likes_user ON prompt_likes (user_email, created_at DESC);
|
||||
|
||||
-- 임직원이 공유한 프롬프트(라이브러리 커뮤니티) — author_email: POST 시 세션(OPS) 이메일, UI는 @ 앞 로컬부로 표시
|
||||
CREATE TABLE IF NOT EXISTS prompt_community_entries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
author_email VARCHAR(320) NOT NULL,
|
||||
title VARCHAR(500) NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
body TEXT NOT NULL,
|
||||
tag VARCHAR(100) NOT NULL DEFAULT '기타',
|
||||
is_published BOOLEAN NOT NULL DEFAULT true,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_prompt_community_author ON prompt_community_entries (author_email, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_prompt_community_created ON prompt_community_entries (created_at DESC) WHERE is_deleted = false AND is_published = true;
|
||||
|
||||
CREATE OR REPLACE FUNCTION set_prompt_community_entries_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_prompt_community_entries_updated_at ON prompt_community_entries;
|
||||
CREATE TRIGGER trg_prompt_community_entries_updated_at
|
||||
BEFORE UPDATE ON prompt_community_entries
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_prompt_community_entries_updated_at();
|
||||
|
||||
-- 팀 공유 프롬프트: 프롬프트 관련·결과(샘플) 첨부(JSON 배열, 경로는 /uploads/…)
|
||||
ALTER TABLE prompt_community_entries ADD COLUMN IF NOT EXISTS prompt_attachments JSONB NOT NULL DEFAULT '[]';
|
||||
ALTER TABLE prompt_community_entries ADD COLUMN IF NOT EXISTS result_sample_attachments JSONB NOT NULL DEFAULT '[]';
|
||||
|
||||
Reference in New Issue
Block a user