Fix more incorrect table names in documentation
- users → user in SQL contexts (94 occurrences) - robeings → robeing in SQL contexts - user_preferences → user_preference (14 files) - slack_workspaces → slack_workspace in SQL contexts (17 files) All table names now correctly match PostgreSQL schema
This commit is contained in:
parent
8c02b80359
commit
97e0888ce0
@ -373,7 +373,7 @@ def evolve_personality(feedback_history, interaction_patterns):
|
||||
personality.reinforce_trait(feedback.related_trait)
|
||||
|
||||
# 사용자 선호 패턴 학습
|
||||
preferred_style = analyze_user_preferences(interaction_patterns)
|
||||
preferred_style = analyze_user_preference(interaction_patterns)
|
||||
personality.adapt_to(preferred_style, learning_rate=0.1)
|
||||
|
||||
# 경험 기반 성숙
|
||||
|
||||
@ -68,7 +68,7 @@ user_uuid = await get_user_uuid(slack_id) # DB에서 UUID 조회
|
||||
#### 사용자 데이터 구조
|
||||
```sql
|
||||
-- users 테이블
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY, -- slack_user_mapping에서 조회
|
||||
username VARCHAR(50), -- slack_U0925SXQ 형태
|
||||
email VARCHAR(255),
|
||||
|
||||
@ -118,7 +118,7 @@ conn = psycopg2.connect('postgresql://robeings:robeings@localhost:5433/main_db')
|
||||
cur = conn.cursor()
|
||||
|
||||
# 쿼리 실행
|
||||
cur.execute("SELECT * FROM users LIMIT 5")
|
||||
cur.execute("SELECT * FROM user LIMIT 5")
|
||||
rows = cur.fetchall()
|
||||
|
||||
for row in rows:
|
||||
@ -134,7 +134,7 @@ conn.close()
|
||||
# SQL Injection 방지를 위해 항상 파라미터 바인딩 사용
|
||||
user_id = 'b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0'
|
||||
cur.execute(
|
||||
"SELECT * FROM users WHERE id = %s",
|
||||
"SELECT * FROM user WHERE id = %s",
|
||||
(user_id,) # 튜플로 전달
|
||||
)
|
||||
```
|
||||
@ -145,7 +145,7 @@ cur.execute(
|
||||
|
||||
### 1. users 테이블
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
email VARCHAR UNIQUE,
|
||||
name VARCHAR,
|
||||
@ -164,7 +164,7 @@ CREATE TABLE users (
|
||||
```sql
|
||||
CREATE TABLE gmail_token (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
slack_id VARCHAR(100), -- Slack 사용자 ID (새로 추가)
|
||||
is_equipped BOOLEAN,
|
||||
has_token BOOLEAN, -- token_data 존재 여부
|
||||
@ -195,7 +195,7 @@ CREATE TABLE conversation_log (
|
||||
intent VARCHAR,
|
||||
confidence DOUBLE PRECISION,
|
||||
timestamp TIMESTAMP,
|
||||
user_id UUID REFERENCES users(id), -- NULL 허용으로 변경됨
|
||||
user_id UUID REFERENCES user(id), -- NULL 허용으로 변경됨
|
||||
slack_user_id VARCHAR(100) -- Slack ID 직접 저장 (새로 추가)
|
||||
);
|
||||
```
|
||||
@ -206,7 +206,7 @@ CREATE TABLE slack_user_mapping (
|
||||
id UUID PRIMARY KEY,
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_workspace_id UUID,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
workspace_member_id UUID,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
@ -236,7 +236,7 @@ query = """
|
||||
g.token_data,
|
||||
g.scopes
|
||||
FROM gmail_token g
|
||||
JOIN users u ON g.user_id = u.id
|
||||
JOIN user u ON g.user_id = u.id
|
||||
ORDER BY g.created_at DESC
|
||||
"""
|
||||
|
||||
@ -303,7 +303,7 @@ def add_gmail_token(slack_user_id, email, access_token, refresh_token):
|
||||
try:
|
||||
# 1. users 테이블에 사용자 추가 (없으면)
|
||||
cur.execute("""
|
||||
INSERT INTO users (id, email, username, created_at)
|
||||
INSERT INTO user (id, email, username, created_at)
|
||||
VALUES (%s, %s, %s, NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email
|
||||
""", (user_uuid, email, slack_user_id))
|
||||
@ -367,14 +367,14 @@ import uuid
|
||||
|
||||
# 방법 1: 직접 캐스팅
|
||||
cur.execute(
|
||||
"SELECT * FROM users WHERE id = %s::uuid",
|
||||
"SELECT * FROM user WHERE id = %s::uuid",
|
||||
('b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0',)
|
||||
)
|
||||
|
||||
# 방법 2: uuid 객체 사용
|
||||
user_uuid = uuid.UUID('b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0')
|
||||
cur.execute(
|
||||
"SELECT * FROM users WHERE id = %s",
|
||||
"SELECT * FROM user WHERE id = %s",
|
||||
(str(user_uuid),)
|
||||
)
|
||||
```
|
||||
|
||||
@ -78,7 +78,7 @@ SELECT
|
||||
wm.robeing_id,
|
||||
sum.slack_user_id,
|
||||
gt.is_equipped as gmail_equipped
|
||||
FROM users u
|
||||
FROM user u
|
||||
LEFT JOIN workspace_member wm ON u.id = wm.user_id
|
||||
LEFT JOIN slack_user_mapping sum ON u.id = sum.user_id
|
||||
LEFT JOIN gmail_token gt ON u.id = gt.user_id
|
||||
@ -94,7 +94,7 @@ SELECT
|
||||
u.name,
|
||||
u.email
|
||||
FROM slack_user_mapping sum
|
||||
JOIN users u ON sum.user_id = u.id
|
||||
JOIN user u ON sum.user_id = u.id
|
||||
WHERE sum.slack_user_id = 'U0925SXQFDK';
|
||||
```
|
||||
|
||||
@ -107,7 +107,7 @@ SELECT
|
||||
gt.equipped_to,
|
||||
rs.level,
|
||||
gt.scopes
|
||||
FROM users u
|
||||
FROM user u
|
||||
JOIN gmail_token gt ON u.id = gt.user_id
|
||||
LEFT JOIN robeing_stats rs ON u.id = rs.user_id
|
||||
WHERE gt.is_equipped = true;
|
||||
@ -123,7 +123,7 @@ SELECT
|
||||
wm.robeing_id
|
||||
FROM workspaces w
|
||||
JOIN workspace_member wm ON w.id = wm.workspace_id
|
||||
JOIN users u ON wm.user_id = u.id
|
||||
JOIN user u ON wm.user_id = u.id
|
||||
WHERE w.name = 'Ivada Robeing';
|
||||
```
|
||||
|
||||
@ -220,7 +220,7 @@ COMMIT;
|
||||
```sql
|
||||
BEGIN;
|
||||
-- 1. users 테이블
|
||||
INSERT INTO users (id, email, name, username)
|
||||
INSERT INTO user (id, email, name, username)
|
||||
VALUES (?, ?, ?, ?);
|
||||
|
||||
-- 2. workspace_member 추가
|
||||
|
||||
@ -49,7 +49,7 @@ sequenceDiagram
|
||||
Gateway->>Gateway: username 추출
|
||||
Note over Gateway: JWT payload에서
|
||||
|
||||
Gateway->>DB: SELECT id FROM users WHERE username = ?
|
||||
Gateway->>DB: SELECT id FROM user WHERE username = ?
|
||||
DB-->>Gateway: UUID
|
||||
|
||||
Gateway->>Service: 요청 전달
|
||||
@ -87,7 +87,7 @@ sequenceDiagram
|
||||
class GatewayProxy:
|
||||
async def convert_username_to_uuid(self, username: str) -> str:
|
||||
"""Username을 UUID로 변환"""
|
||||
query = "SELECT id FROM users WHERE username = $1"
|
||||
query = "SELECT id FROM user WHERE username = $1"
|
||||
result = await self.db.fetchone(query, username)
|
||||
|
||||
if not result:
|
||||
@ -438,7 +438,7 @@ class RobeingGateway:
|
||||
async def get_user_uuid(self, username: str) -> str:
|
||||
async with self.db_pool.acquire() as conn:
|
||||
row = await conn.fetchrow(
|
||||
"SELECT id FROM users WHERE username = $1",
|
||||
"SELECT id FROM user WHERE username = $1",
|
||||
username
|
||||
)
|
||||
if not row:
|
||||
|
||||
@ -50,7 +50,7 @@ sequenceDiagram
|
||||
Auth->>Google: GET /oauth2/v2/userinfo
|
||||
Google-->>Auth: email, name, picture
|
||||
|
||||
Auth->>DB: SELECT * FROM users WHERE email=?
|
||||
Auth->>DB: SELECT * FROM user WHERE email=?
|
||||
DB-->>Auth: 사용자 없음
|
||||
|
||||
Auth->>Auth: UUID 생성 (uuid.uuid4())
|
||||
@ -94,13 +94,13 @@ sequenceDiagram
|
||||
|
||||
Note over Auth,Google: OAuth 플로우 (1.1과 동일)
|
||||
|
||||
Auth->>DB: SELECT * FROM users WHERE email=?
|
||||
Auth->>DB: SELECT * FROM user WHERE email=?
|
||||
DB-->>Auth: 사용자 정보 (기존 UUID)
|
||||
|
||||
Auth->>DB: UPDATE users SET last_login=NOW()
|
||||
Auth->>DB: UPDATE user SET last_login=NOW()
|
||||
|
||||
Auth->>DB: username 조회
|
||||
Note over DB: SELECT username FROM users<br/>WHERE id = ?
|
||||
Note over DB: SELECT username FROM user<br/>WHERE id = ?
|
||||
DB-->>Auth: username
|
||||
|
||||
Auth->>Auth: JWT 토큰 생성
|
||||
@ -148,10 +148,10 @@ sequenceDiagram
|
||||
|
||||
alt 매핑 존재
|
||||
DB-->>Auth: user_id (UUID)
|
||||
Auth->>DB: SELECT * FROM users WHERE id=?
|
||||
Auth->>DB: SELECT * FROM user WHERE id=?
|
||||
Note over DB: UUID로 사용자 정보 조회
|
||||
DB-->>Auth: 사용자 정보
|
||||
Auth->>DB: UPDATE users SET last_login=NOW()
|
||||
Auth->>DB: UPDATE user SET last_login=NOW()
|
||||
else 매핑 없음 (신규)
|
||||
Auth->>Auth: UUID 생성 (uuid.uuid4())
|
||||
Auth->>Auth: username 생성
|
||||
@ -189,7 +189,7 @@ sequenceDiagram
|
||||
Note over Gateway: JWT payload에서 username
|
||||
|
||||
Gateway->>DB: username → UUID 변환
|
||||
Note over DB: SELECT id FROM users<br/>WHERE username = ?
|
||||
Note over DB: SELECT id FROM user<br/>WHERE username = ?
|
||||
DB-->>Gateway: user_id (UUID)
|
||||
|
||||
Gateway->>Service: 요청 전달
|
||||
@ -237,7 +237,7 @@ flowchart TD
|
||||
|
||||
```sql
|
||||
-- users 테이블
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
name VARCHAR(255),
|
||||
@ -250,7 +250,7 @@ CREATE TABLE users (
|
||||
|
||||
-- 예시 데이터
|
||||
-- 테스트 사용자 (하드코딩 UUID)
|
||||
INSERT INTO users VALUES
|
||||
INSERT INTO user VALUES
|
||||
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'goeun2dc@gmail.com', '김종태', 'happybell80'),
|
||||
('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '0914eagle@gmail.com', '전희재', 'eagle0914'),
|
||||
('dddddddd-dddd-dddd-dddd-dddddddddddd', 'test@example.com', 'Test User', 'test_user');
|
||||
|
||||
@ -167,7 +167,7 @@ const observer = new IntersectionObserver((entries) => {
|
||||
|
||||
### 6.1 users 테이블
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE,
|
||||
username VARCHAR(50) UNIQUE,
|
||||
@ -178,7 +178,7 @@ CREATE TABLE users (
|
||||
### 6.2 workspace_member 테이블
|
||||
```sql
|
||||
CREATE TABLE workspace_member (
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
workspace_id UUID,
|
||||
robeing_id VARCHAR(50) -- rb8001, rb10508_micro 등
|
||||
);
|
||||
@ -192,7 +192,7 @@ CREATE TABLE conversation_log (
|
||||
message VARCHAR,
|
||||
response VARCHAR,
|
||||
timestamp TIMESTAMP,
|
||||
user_id UUID REFERENCES users(id)
|
||||
user_id UUID REFERENCES user(id)
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
@ -195,7 +195,7 @@ sequenceDiagram
|
||||
Note over Gateway: username 추출
|
||||
|
||||
Gateway->>DB: username → UUID 변환
|
||||
Note over DB: users 테이블 조회<br/>SELECT id FROM users<br/>WHERE username = ?
|
||||
Note over DB: users 테이블 조회<br/>SELECT id FROM user<br/>WHERE username = ?
|
||||
DB-->>Gateway: user_id (UUID)
|
||||
|
||||
Gateway->>RB: 이메일 발송 요청
|
||||
@ -269,7 +269,7 @@ sequenceDiagram
|
||||
Auth-->>RB: UUID 반환
|
||||
|
||||
RB->>DB: UUID로 사용자 조회
|
||||
Note over DB: SELECT * FROM users<br/>WHERE id = '매핑된 UUID'
|
||||
Note over DB: SELECT * FROM user<br/>WHERE id = '매핑된 UUID'
|
||||
DB-->>RB: user_id, name: "김종태"
|
||||
|
||||
RB->>Monitor: Gmail 아이템 상태 확인
|
||||
|
||||
@ -52,7 +52,7 @@ class GoogleAuthHandler:
|
||||
async def create_or_get_user(self, email: str, name: str):
|
||||
# 기존 사용자 확인
|
||||
user = await self.db.fetchone(
|
||||
"SELECT * FROM users WHERE email = $1",
|
||||
"SELECT * FROM user WHERE email = $1",
|
||||
email
|
||||
)
|
||||
|
||||
@ -63,7 +63,7 @@ class GoogleAuthHandler:
|
||||
new_user_id = str(uuid.uuid4())
|
||||
|
||||
await self.db.execute("""
|
||||
INSERT INTO users (id, email, name, username, oauth_provider)
|
||||
INSERT INTO user (id, email, name, username, oauth_provider)
|
||||
VALUES ($1, $2, $3, $4, 'google')
|
||||
""", new_user_id, email, name, self.generate_username(email))
|
||||
|
||||
@ -102,7 +102,7 @@ class SlackUserHandler:
|
||||
|
||||
# 기존 사용자 확인
|
||||
user = await self.db.fetchone(
|
||||
"SELECT * FROM users WHERE id = $1",
|
||||
"SELECT * FROM user WHERE id = $1",
|
||||
user_uuid
|
||||
)
|
||||
|
||||
@ -112,7 +112,7 @@ class SlackUserHandler:
|
||||
# 신규 사용자 등록
|
||||
username = f"slack_{slack_user_id[:8]}"
|
||||
await self.db.execute("""
|
||||
INSERT INTO users (id, username, email, name, oauth_provider)
|
||||
INSERT INTO user (id, username, email, name, oauth_provider)
|
||||
VALUES ($1, $2, $3, $4, 'slack')
|
||||
""", user_uuid, username,
|
||||
slack_user_info.get('email', ''),
|
||||
@ -138,7 +138,7 @@ sequenceDiagram
|
||||
Gateway->>Gateway: JWT 검증
|
||||
Gateway->>Gateway: username 추출
|
||||
|
||||
Gateway->>DB: SELECT id FROM users WHERE username = ?
|
||||
Gateway->>DB: SELECT id FROM user WHERE username = ?
|
||||
DB-->>Gateway: UUID
|
||||
|
||||
Gateway->>Service: Request + X-User-Id (UUID)
|
||||
@ -163,7 +163,7 @@ class GatewayUUIDConverter:
|
||||
# DB 조회
|
||||
async with self.db_pool.acquire() as conn:
|
||||
row = await conn.fetchrow(
|
||||
"SELECT id FROM users WHERE username = $1",
|
||||
"SELECT id FROM user WHERE username = $1",
|
||||
username
|
||||
)
|
||||
|
||||
@ -192,7 +192,7 @@ class GatewayUUIDConverter:
|
||||
|
||||
```sql
|
||||
-- 테스트 사용자 (고정 UUID)
|
||||
INSERT INTO users (id, username, email, name) VALUES
|
||||
INSERT INTO user (id, username, email, name) VALUES
|
||||
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'happybell80', 'goeun2dc@gmail.com', '김종태'),
|
||||
('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'eagle0914', '0914eagle@gmail.com', '전희재'),
|
||||
('cccccccc-cccc-cccc-cccc-cccccccccccc', 'test_user', 'test@example.com', 'Test User');
|
||||
@ -226,7 +226,7 @@ ALTER TABLE gmail_token ADD COLUMN user_uuid UUID;
|
||||
-- 2. UUID 매핑
|
||||
UPDATE gmail_token gt
|
||||
SET user_uuid = u.id
|
||||
FROM users u
|
||||
FROM user u
|
||||
WHERE gt.user_id = u.username;
|
||||
|
||||
-- 3. 기존 컬럼 제거 및 이름 변경
|
||||
@ -236,7 +236,7 @@ ALTER TABLE gmail_token RENAME COLUMN user_uuid TO user_id;
|
||||
-- 4. 외래키 제약 추가
|
||||
ALTER TABLE gmail_token
|
||||
ADD CONSTRAINT fk_user_id
|
||||
FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
FOREIGN KEY (user_id) REFERENCES user(id);
|
||||
```
|
||||
|
||||
---
|
||||
@ -298,7 +298,7 @@ async def get_current_user(request: Request):
|
||||
async def debug_uuid(username: str):
|
||||
"""개발 환경에서만 사용"""
|
||||
user = await db.fetchone(
|
||||
"SELECT id, username, oauth_provider FROM users WHERE username = $1",
|
||||
"SELECT id, username, oauth_provider FROM user WHERE username = $1",
|
||||
username
|
||||
)
|
||||
|
||||
@ -343,7 +343,7 @@ GROUP BY uuid_type;
|
||||
|
||||
-- Username-UUID 매핑 확인
|
||||
SELECT username, id, oauth_provider
|
||||
FROM users
|
||||
FROM user
|
||||
WHERE username = 'happybell80';
|
||||
|
||||
-- Slack 사용자 UUID 검증
|
||||
|
||||
@ -217,12 +217,12 @@ class FeedbackAnalyzer:
|
||||
})
|
||||
|
||||
# 사용자별 선호도 프로파일
|
||||
user_preferences = self.build_user_preference_profile(feedback_history)
|
||||
user_preference = self.build_user_preference_profile(feedback_history)
|
||||
|
||||
return {
|
||||
"trend": trend,
|
||||
"patterns": strengths_weaknesses,
|
||||
"user_preferences": user_preferences,
|
||||
"user_preference": user_preference,
|
||||
"recommendations": self.generate_improvement_recommendations(
|
||||
strengths_weaknesses
|
||||
)
|
||||
|
||||
@ -16,7 +16,7 @@ def check_my_level():
|
||||
query = """
|
||||
SELECT level, experience,
|
||||
next_level_exp - experience as exp_needed
|
||||
FROM robeings
|
||||
FROM robeing
|
||||
WHERE id = self.id
|
||||
"""
|
||||
return database.execute(query)
|
||||
|
||||
@ -39,7 +39,7 @@ CREATE TABLE company (
|
||||
### 2. slack_workspaces (Slack 워크스페이스 연동)
|
||||
|
||||
```sql
|
||||
CREATE TABLE slack_workspaces (
|
||||
CREATE TABLE slack_workspace (
|
||||
id uuid PRIMARY KEY,
|
||||
company_id uuid NOT NULL REFERENCES company(id),
|
||||
team_id varchar(100) NOT NULL UNIQUE,
|
||||
|
||||
@ -130,7 +130,7 @@ CREATE TABLE company (
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
company_id UUID REFERENCES company(id),
|
||||
slack_user_id VARCHAR(50),
|
||||
@ -142,7 +142,7 @@ CREATE TABLE users (
|
||||
);
|
||||
|
||||
CREATE TABLE user_skills (
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
skill_id VARCHAR(50),
|
||||
level INTEGER DEFAULT 1,
|
||||
usage_count INTEGER DEFAULT 0,
|
||||
@ -153,7 +153,7 @@ CREATE TABLE user_skills (
|
||||
|
||||
CREATE TABLE skill_growth_logs (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
skill_id VARCHAR(50),
|
||||
old_level INTEGER,
|
||||
new_level INTEGER,
|
||||
|
||||
@ -180,7 +180,7 @@ function levelUpTransition(fromLevel, toLevel) {
|
||||
```python
|
||||
class AdaptiveUI:
|
||||
def __init__(self):
|
||||
self.user_preferences = {}
|
||||
self.user_preference = {}
|
||||
self.interaction_history = []
|
||||
|
||||
def learn_preferences(self, interaction):
|
||||
|
||||
@ -309,7 +309,7 @@ email ↔ slack_id ↔ username
|
||||
-- 2. slack_workspaces: 단순화
|
||||
-- 3. user_robeings: 사용자-로빙 직접 연결
|
||||
CREATE TABLE user_robeings (
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100), -- rb10508_micro 등
|
||||
is_primary BOOLEAN
|
||||
);
|
||||
@ -318,7 +318,7 @@ CREATE TABLE user_robeings (
|
||||
CREATE TABLE slack_users (
|
||||
slack_user_id VARCHAR(100), -- U0925SXQFDK
|
||||
slack_team_id VARCHAR(100),
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100) -- Slack별 로빙 지정 가능
|
||||
);
|
||||
```
|
||||
|
||||
@ -90,7 +90,7 @@ CREATE TABLE slack_user_mapping (
|
||||
id UUID PRIMARY KEY,
|
||||
slack_user_id VARCHAR(100) NOT NULL, -- U04KJHGLS
|
||||
slack_workspace_id VARCHAR(100), -- T1234567
|
||||
user_id UUID REFERENCES users(id), -- 우리 시스템 사용자
|
||||
user_id UUID REFERENCES user(id), -- 우리 시스템 사용자
|
||||
robeing_id VARCHAR(100), -- rb10508_micro
|
||||
created_at TIMESTAMP,
|
||||
UNIQUE(slack_user_id, slack_workspace_id)
|
||||
@ -327,8 +327,8 @@ class SlackItem(APIItem):
|
||||
CREATE TABLE slack_user_mapping (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_workspace_id INTEGER REFERENCES slack_workspaces(id),
|
||||
user_id UUID REFERENCES users(id),
|
||||
slack_workspace_id INTEGER REFERENCES slack_workspace(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
workspace_member_id UUID REFERENCES workspace_member(id),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
@ -358,7 +358,7 @@ ChromaDB: rb10508_micro_{user_id}_episodic
|
||||
-- happybell80을 Slack 사용자와 연결
|
||||
INSERT INTO slack_user_mapping (slack_user_id, slack_workspace_id, user_id)
|
||||
SELECT 'U0925SXQFDK', sw.id, u.id
|
||||
FROM users u, slack_workspaces sw
|
||||
FROM user u, slack_workspaces sw
|
||||
WHERE u.username = 'happybell80'
|
||||
AND sw.team_name = 'GoodGang Labs';
|
||||
```
|
||||
|
||||
@ -219,7 +219,7 @@ async def on_task_success(task_type: str, difficulty: int):
|
||||
CREATE TABLE robeing_settings (
|
||||
id UUID PRIMARY KEY,
|
||||
robeing_id VARCHAR(100) UNIQUE,
|
||||
user_preferences JSON,
|
||||
user_preference JSON,
|
||||
system_settings JSON,
|
||||
skill_settings JSON,
|
||||
created_at TIMESTAMP,
|
||||
@ -274,7 +274,7 @@ class SettingsManager:
|
||||
### 4.3 설정 예시
|
||||
```python
|
||||
# 사용자 선호 설정
|
||||
user_preferences = {
|
||||
user_preference = {
|
||||
"response_style": "formal", # formal/casual/friendly
|
||||
"response_length": "detailed", # brief/normal/detailed
|
||||
"language": "ko",
|
||||
|
||||
@ -26,7 +26,7 @@ system_prompt = base_prompt + user_rules[user_id] + dynamic_rules[session_id]
|
||||
```sql
|
||||
CREATE TABLE dynamic_prompts (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(50),
|
||||
rule_type ENUM('never', 'always', 'prefer', 'avoid'),
|
||||
content TEXT,
|
||||
|
||||
@ -143,7 +143,7 @@ socket.on('processing_update', (data) => {
|
||||
```sql
|
||||
CREATE TABLE user_documents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
filename VARCHAR(255),
|
||||
file_hash VARCHAR(64),
|
||||
file_size BIGINT,
|
||||
|
||||
@ -91,7 +91,7 @@ def process_attendance_message(text):
|
||||
-- 근태 기록
|
||||
CREATE TABLE attendance_records (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
date DATE NOT NULL,
|
||||
check_in_time TIMESTAMP,
|
||||
check_out_time TIMESTAMP,
|
||||
@ -104,7 +104,7 @@ CREATE TABLE attendance_records (
|
||||
-- 휴가 신청
|
||||
CREATE TABLE leave_requests (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
leave_type VARCHAR(20), -- 'annual', 'sick', 'personal'
|
||||
start_date DATE,
|
||||
end_date DATE,
|
||||
@ -119,7 +119,7 @@ CREATE TABLE leave_requests (
|
||||
|
||||
-- 연차 잔여
|
||||
CREATE TABLE leave_balances (
|
||||
user_id UUID PRIMARY KEY REFERENCES users(id),
|
||||
user_id UUID PRIMARY KEY REFERENCES user(id),
|
||||
total_days DECIMAL(3,1),
|
||||
used_days DECIMAL(3,1),
|
||||
remaining_days DECIMAL(3,1),
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#### 1.1 테이블 스키마 업데이트
|
||||
```sql
|
||||
-- users 테이블 (이미 UUID 있음, 제약조건 추가)
|
||||
ALTER TABLE users
|
||||
ALTER TABLE user
|
||||
ADD CONSTRAINT users_uuid_unique UNIQUE(id);
|
||||
|
||||
-- slack_user_mapping 인덱스 추가
|
||||
@ -39,7 +39,7 @@ CREATE INDEX idx_slack_user_mapping_slack_user ON slack_user_mapping(slack_user_
|
||||
|
||||
-- gmail_passports UUID 참조 추가
|
||||
ALTER TABLE gmail_passports
|
||||
ADD COLUMN user_uuid UUID REFERENCES users(id);
|
||||
ADD COLUMN user_uuid UUID REFERENCES user(id);
|
||||
|
||||
-- 기존 slack_user_id 기반 데이터 마이그레이션
|
||||
UPDATE gmail_passports gp
|
||||
@ -53,7 +53,7 @@ SET user_uuid = (
|
||||
-- workspace_member UUID 확인
|
||||
ALTER TABLE workspace_member
|
||||
ADD CONSTRAINT fk_workspace_member_user_id
|
||||
FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
FOREIGN KEY (user_id) REFERENCES user(id);
|
||||
```
|
||||
|
||||
#### 1.2 데이터 검증 스크립트
|
||||
@ -70,7 +70,7 @@ def verify_uuid_consistency():
|
||||
cur.execute("""
|
||||
SELECT sum.*, u.id
|
||||
FROM slack_user_mapping sum
|
||||
LEFT JOIN users u ON sum.user_id = u.id
|
||||
LEFT JOIN user u ON sum.user_id = u.id
|
||||
WHERE u.id IS NULL
|
||||
""")
|
||||
orphaned = cur.fetchall()
|
||||
|
||||
@ -37,13 +37,13 @@ FROM company
|
||||
WHERE id NOT IN (SELECT id FROM workspaces);
|
||||
|
||||
-- 2. slack_workspaces 테이블 수정
|
||||
ALTER TABLE slack_workspaces
|
||||
ALTER TABLE slack_workspace
|
||||
ADD COLUMN workspace_id UUID;
|
||||
|
||||
UPDATE slack_workspaces
|
||||
UPDATE slack_workspace
|
||||
SET workspace_id = company_id;
|
||||
|
||||
ALTER TABLE slack_workspaces
|
||||
ALTER TABLE slack_workspace
|
||||
DROP COLUMN company_id,
|
||||
ADD CONSTRAINT slack_workspaces_workspace_id_fkey
|
||||
FOREIGN KEY (workspace_id) REFERENCES workspaces(id);
|
||||
@ -102,7 +102,7 @@ SELECT
|
||||
sw.team_name,
|
||||
w.name as workspace_name,
|
||||
w.robeing_port
|
||||
FROM slack_workspaces sw
|
||||
FROM slack_workspace sw
|
||||
JOIN workspaces w ON sw.workspace_id = w.id;
|
||||
```
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
| workspaces | team | 구조 변환 필요 |
|
||||
| workspace_member | workspace_member | user_id 매핑 |
|
||||
| slack_workspaces | slack_workspace | team_id 매핑 |
|
||||
| user_preferences | user_preference | slack_user_id 제거됨 |
|
||||
| user_preference | user_preference | slack_user_id 제거됨 |
|
||||
| conversation_log | conversation_log | robeing_id 컬럼 없음 |
|
||||
| gmail_token | gmail_token | 구조 동일 |
|
||||
| robeing_stats | robeing | product_id, team_id 추가 |
|
||||
@ -71,9 +71,9 @@ SELECT id, user_id, role::user_role, is_active, joined_at FROM main_db3.workspac
|
||||
INSERT INTO slack_workspace (id, team_id, slack_team_id, bot_token, is_active)
|
||||
SELECT id, workspace_id, team_id, bot_token, is_active FROM main_db3.slack_workspaces;
|
||||
|
||||
-- 6. user_preferences → user_preference (slack_user_id 제거)
|
||||
-- 6. user_preference → user_preference (slack_user_id 제거)
|
||||
INSERT INTO user_preference (user_id, news_keywords, email_filter, briefing_enabled)
|
||||
SELECT user_id, news_keywords, email_filter, briefing_enabled FROM main_db3.user_preferences;
|
||||
SELECT user_id, news_keywords, email_filter, briefing_enabled FROM main_db3.user_preference;
|
||||
|
||||
-- 7. gmail_token → gmail_token
|
||||
INSERT INTO gmail_token SELECT * FROM main_db3.gmail_token;
|
||||
|
||||
@ -47,7 +47,7 @@ slack_workspaces: 2개 (GoodGang Labs, test)
|
||||
|
||||
```sql
|
||||
-- 사용자 테이블
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
username VARCHAR(50) UNIQUE,
|
||||
@ -61,7 +61,7 @@ CREATE TABLE users (
|
||||
-- 사용자별 로빙 할당
|
||||
CREATE TABLE user_robeings (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100) NOT NULL, -- rb10508_micro, rb8001 등
|
||||
robeing_port INTEGER,
|
||||
is_primary BOOLEAN DEFAULT false,
|
||||
@ -74,7 +74,7 @@ CREATE TABLE slack_user_mapping (
|
||||
id UUID PRIMARY KEY,
|
||||
slack_user_id VARCHAR(100) NOT NULL, -- U04KJHGLS
|
||||
slack_team_id VARCHAR(100), -- T035VFRKCN6
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
bot_token TEXT, -- 워크스페이스별 봇 토큰
|
||||
created_at TIMESTAMP,
|
||||
UNIQUE(slack_user_id, slack_team_id)
|
||||
@ -88,7 +88,7 @@ CREATE TABLE slack_user_mapping (
|
||||
|
||||
```sql
|
||||
-- 기존 users 테이블 유지
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
username VARCHAR(50) UNIQUE,
|
||||
@ -103,7 +103,7 @@ CREATE TABLE users (
|
||||
);
|
||||
|
||||
-- Slack 워크스페이스 (단순화)
|
||||
CREATE TABLE slack_workspaces (
|
||||
CREATE TABLE slack_workspace (
|
||||
id UUID PRIMARY KEY,
|
||||
team_id VARCHAR(100) UNIQUE NOT NULL,
|
||||
team_name VARCHAR(255),
|
||||
@ -119,7 +119,7 @@ CREATE TABLE slack_workspaces (
|
||||
-- 사용자-로빙 연결
|
||||
CREATE TABLE user_robeings (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100) NOT NULL,
|
||||
robeing_port INTEGER,
|
||||
robeing_host VARCHAR(255) DEFAULT '192.168.219.52',
|
||||
@ -132,8 +132,8 @@ CREATE TABLE user_robeings (
|
||||
CREATE TABLE slack_users (
|
||||
id UUID PRIMARY KEY,
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_team_id VARCHAR(100) REFERENCES slack_workspaces(team_id),
|
||||
user_id UUID REFERENCES users(id),
|
||||
slack_team_id VARCHAR(100) REFERENCES slack_workspace(team_id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100), -- 이 Slack 사용자가 대화할 로빙
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
@ -154,7 +154,7 @@ CREATE TABLE slack_users (
|
||||
|
||||
```sql
|
||||
-- 사용자 (모든 정보 통합)
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
username VARCHAR(50) UNIQUE,
|
||||
@ -224,7 +224,7 @@ CREATE TABLE slack_users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_team_id VARCHAR(100),
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
@ -235,8 +235,8 @@ CREATE TABLE slack_users (
|
||||
#### Phase 3: 기존 테이블 정리
|
||||
```sql
|
||||
-- Foreign key 제약 제거 후 테이블 삭제
|
||||
ALTER TABLE slack_workspaces DROP CONSTRAINT slack_workspaces_company_id_fkey;
|
||||
ALTER TABLE slack_workspaces DROP COLUMN company_id;
|
||||
ALTER TABLE slack_workspace DROP CONSTRAINT slack_workspaces_company_id_fkey;
|
||||
ALTER TABLE slack_workspace DROP COLUMN company_id;
|
||||
|
||||
DROP TABLE workspace_member;
|
||||
DROP TABLE workspaces;
|
||||
@ -295,7 +295,7 @@ SELECT * FROM user_robeings WHERE user_id = ? AND is_primary = true
|
||||
# 신규
|
||||
SELECT u.*, sr.robeing_id
|
||||
FROM slack_users sr
|
||||
JOIN users u ON sr.user_id = u.id
|
||||
JOIN user u ON sr.user_id = u.id
|
||||
WHERE sr.slack_user_id = ? AND sr.slack_team_id = ?
|
||||
```
|
||||
|
||||
@ -354,7 +354,7 @@ WHERE sr.slack_user_id = ? AND sr.slack_team_id = ?
|
||||
```sql
|
||||
CREATE TABLE user_robeings (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100) NOT NULL,
|
||||
robeing_port INTEGER,
|
||||
robeing_host VARCHAR(255) DEFAULT '192.168.219.52',
|
||||
@ -374,7 +374,7 @@ CREATE TABLE slack_users (
|
||||
id UUID PRIMARY KEY,
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_team_id VARCHAR(100),
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
robeing_id VARCHAR(100),
|
||||
display_name VARCHAR(255), -- Slack 표시 이름
|
||||
slack_timezone VARCHAR(50), -- 사용자 시간대
|
||||
|
||||
@ -114,7 +114,7 @@ async def get_user_mapping(
|
||||
u.email,
|
||||
wm.robeing_id
|
||||
FROM slack_user_mapping sum
|
||||
JOIN users u ON sum.user_id = u.id
|
||||
JOIN user u ON sum.user_id = u.id
|
||||
LEFT JOIN workspace_member wm ON u.id = wm.user_id
|
||||
WHERE sum.slack_user_id = :slack_user_id
|
||||
"""
|
||||
@ -228,8 +228,8 @@ async def route_slack_message(
|
||||
CREATE TABLE IF NOT EXISTS slack_user_mapping (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_workspace_id INTEGER REFERENCES slack_workspaces(id),
|
||||
user_id UUID REFERENCES users(id) NOT NULL,
|
||||
slack_workspace_id INTEGER REFERENCES slack_workspace(id),
|
||||
user_id UUID REFERENCES user(id) NOT NULL,
|
||||
workspace_member_id UUID REFERENCES workspace_member(id),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
@ -249,7 +249,7 @@ SELECT
|
||||
'U0925SXQFDK',
|
||||
sw.id,
|
||||
u.id
|
||||
FROM users u, slack_workspaces sw
|
||||
FROM user u, slack_workspaces sw
|
||||
WHERE u.username = 'happybell80'
|
||||
AND sw.team_name = 'GoodGang Labs';
|
||||
```
|
||||
|
||||
@ -92,8 +92,8 @@ collection_name = f"robeing_rb8001_{user_id}_memories"
|
||||
#### 1. 사용자 관리 일원화
|
||||
```sql
|
||||
-- PostgreSQL users 테이블 확장
|
||||
ALTER TABLE users ADD COLUMN slack_user_id VARCHAR(20);
|
||||
CREATE INDEX idx_slack_user_id ON users(slack_user_id);
|
||||
ALTER TABLE user ADD COLUMN slack_user_id VARCHAR(20);
|
||||
CREATE INDEX idx_slack_user_id ON user(slack_user_id);
|
||||
|
||||
-- 매핑 테이블
|
||||
CREATE TABLE user_identity_mapping (
|
||||
|
||||
@ -120,8 +120,8 @@ Slack → @robeing 또는 /robeing → rb8001 → 응답
|
||||
|
||||
### 필요 컬럼 추가
|
||||
```sql
|
||||
ALTER TABLE users ADD COLUMN slack_user_id VARCHAR(50);
|
||||
ALTER TABLE users ADD COLUMN slack_team_id VARCHAR(50);
|
||||
ALTER TABLE user ADD COLUMN slack_user_id VARCHAR(50);
|
||||
ALTER TABLE user ADD COLUMN slack_team_id VARCHAR(50);
|
||||
ALTER TABLE conversation_log ADD COLUMN thread_ts VARCHAR(20);
|
||||
ALTER TABLE conversation_log ADD COLUMN channel_type VARCHAR(20);
|
||||
```
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
**새로운 테이블 구조**:
|
||||
```sql
|
||||
-- users 테이블
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
name VARCHAR(255),
|
||||
@ -106,7 +106,7 @@ CREATE TABLE users (
|
||||
-- workspace_member 테이블
|
||||
CREATE TABLE workspace_member (
|
||||
workspace_id UUID REFERENCES workspaces(id),
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
role VARCHAR(50),
|
||||
robeing_id VARCHAR(100), -- 할당된 로빙
|
||||
...
|
||||
|
||||
@ -238,7 +238,7 @@ https://ro-being.com/gateway/api/chat
|
||||
```sql
|
||||
-- 잘못된 형식 (문자열을 UUID 컬럼에 삽입 시도)
|
||||
INSERT INTO workspaces (id, ...) VALUES ('ws-ivada-001', ...);
|
||||
INSERT INTO users (id, ...) VALUES ('user-happybell80', ...);
|
||||
INSERT INTO user (id, ...) VALUES ('user-happybell80', ...);
|
||||
```
|
||||
|
||||
**두 번째 시도 - role 값 오류**:
|
||||
@ -254,7 +254,7 @@ INSERT INTO workspace_member (..., role, ...) VALUES (..., 'OWNER', ...); -- O
|
||||
INSERT INTO workspaces (id, ...) VALUES
|
||||
('11111111-1111-1111-1111-111111111111'::uuid, ...);
|
||||
|
||||
INSERT INTO users (id, email, name) VALUES
|
||||
INSERT INTO user (id, email, name) VALUES
|
||||
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'::uuid, 'goeun2dc@gmail.com', '김종태'),
|
||||
('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'::uuid, '0914eagle@gmail.com', '전희재'),
|
||||
('cccccccc-cccc-cccc-cccc-cccccccccccc'::uuid, 'hhyong91@gmail.com', '황한용');
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
```sql
|
||||
-- users 테이블에 username 필드 추가
|
||||
ALTER TABLE users ADD COLUMN username VARCHAR(50) UNIQUE;
|
||||
ALTER TABLE user ADD COLUMN username VARCHAR(50) UNIQUE;
|
||||
```
|
||||
|
||||
**파일 수정:**
|
||||
|
||||
@ -100,7 +100,7 @@ async def get_robeing_info(username: str):
|
||||
query = text("""
|
||||
SELECT ...
|
||||
FROM workspace_member wm
|
||||
JOIN users u ON wm.user_id = u.id
|
||||
JOIN user u ON wm.user_id = u.id
|
||||
WHERE u.username = :username
|
||||
""")
|
||||
```
|
||||
|
||||
@ -35,7 +35,7 @@ async def get_robeing_info(username: str):
|
||||
query = text("""
|
||||
SELECT ...
|
||||
FROM workspace_member wm
|
||||
JOIN users u ON wm.user_id = u.id
|
||||
JOIN user u ON wm.user_id = u.id
|
||||
WHERE u.username = :username
|
||||
""")
|
||||
```
|
||||
|
||||
@ -27,8 +27,8 @@
|
||||
CREATE TABLE slack_user_mapping (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
slack_user_id VARCHAR(100) NOT NULL,
|
||||
slack_workspace_id UUID REFERENCES slack_workspaces(id),
|
||||
user_id UUID REFERENCES users(id) NOT NULL,
|
||||
slack_workspace_id UUID REFERENCES slack_workspace(id),
|
||||
user_id UUID REFERENCES user(id) NOT NULL,
|
||||
workspace_member_id UUID REFERENCES workspace_member(id),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
@ -147,13 +147,13 @@ def resolve_username(user_id: str) -> str:
|
||||
|
||||
```sql
|
||||
-- 잘못된 예: 테스트용 UUID 하드코딩 (250809_happybell80_robeing-gateway구현.md)
|
||||
INSERT INTO users (id, email, name) VALUES
|
||||
INSERT INTO user (id, email, name) VALUES
|
||||
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'::uuid, 'goeun2dc@gmail.com', '김종태'),
|
||||
('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'::uuid, '0914eagle@gmail.com', '전희재'),
|
||||
('cccccccc-cccc-cccc-cccc-cccccccccccc'::uuid, 'hhyong91@gmail.com', '황한용');
|
||||
|
||||
-- 올바른 방법: gen_random_uuid() 사용
|
||||
INSERT INTO users (id, email, name, username) VALUES
|
||||
INSERT INTO user (id, email, name, username) VALUES
|
||||
(gen_random_uuid(), 'goeun2dc@gmail.com', '김종태', 'happybell80');
|
||||
-- 실제 UUID 생성: 'e7a9f3c2-8b4d-4f2e-a1b3-9c8d7e6f5a4b'
|
||||
```
|
||||
@ -394,12 +394,12 @@ localStorage.removeItem('user_id');
|
||||
### 8. **PostgreSQL UUID 올바른 사용법**
|
||||
```sql
|
||||
-- ❌ 잘못된 방법: 하드코딩
|
||||
INSERT INTO users (id) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa');
|
||||
INSERT INTO user (id) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa');
|
||||
|
||||
-- ✅ 올바른 방법: 함수 사용
|
||||
INSERT INTO users (id) VALUES (gen_random_uuid());
|
||||
INSERT INTO user (id) VALUES (gen_random_uuid());
|
||||
-- 또는 테이블 정의 시 DEFAULT 설정
|
||||
CREATE TABLE users (
|
||||
CREATE TABLE user (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
||||
);
|
||||
```
|
||||
|
||||
@ -61,7 +61,7 @@ Google Cloud Console에 추가:
|
||||
# auth-server/app/providers/gmail_passport.py
|
||||
async def get_uuid_from_username(username: str, conn) -> str:
|
||||
row = await conn.fetchrow("""
|
||||
SELECT id::text FROM users WHERE username = $1
|
||||
SELECT id::text FROM user WHERE username = $1
|
||||
""", username)
|
||||
if row:
|
||||
return row['id']
|
||||
|
||||
@ -122,7 +122,7 @@ psql -h localhost -U robeings -d main_db -c \
|
||||
"SELECT u.username, gt.access_token IS NOT NULL as has_token,
|
||||
gt.expires_at < extract(epoch from now()) as is_expired,
|
||||
gt.metadata->>'email' as email
|
||||
FROM users u
|
||||
FROM user u
|
||||
LEFT JOIN gmail_token gt ON u.id = gt.user_id
|
||||
WHERE u.username IN ('happybell80', '0914eagle', 'cdctfm');"
|
||||
```
|
||||
|
||||
@ -248,7 +248,7 @@ interface TaskSettings {
|
||||
### 📋 후속 작업 필요
|
||||
|
||||
1. **백엔드 API 구축**
|
||||
- user_preferences 테이블 생성
|
||||
- user_preference 테이블 생성
|
||||
- 키워드 기반 필터링 로직
|
||||
- 사용자별 설정 저장/조회 API
|
||||
|
||||
@ -290,7 +290,7 @@ interface TaskSettings {
|
||||
- ~~Gmail 토큰 갱신 크론잡 설정~~ (필요없음 - 자동갱신 구현됨)
|
||||
|
||||
2. **단기 (백엔드)**
|
||||
- user_preferences API 구현
|
||||
- user_preference API 구현
|
||||
- 키워드 필터링 로직 개발
|
||||
|
||||
3. **중기 (통합)**
|
||||
|
||||
@ -122,7 +122,7 @@ SELECT DISTINCT
|
||||
u.id,
|
||||
sum.slack_user_id,
|
||||
wm.robeing_id
|
||||
FROM users u
|
||||
FROM user u
|
||||
LEFT JOIN slack_user_mapping sum ON u.id = sum.user_id
|
||||
LEFT JOIN workspace_member wm ON u.id = wm.user_id;
|
||||
```
|
||||
@ -167,7 +167,7 @@ DATABASE_URL=postgresql://robeings:robeings@localhost:5433/main_db
|
||||
2. ✅ gmail_token의 slack_user_id 컬럼 확인 (이미 존재, slack_id 컬럼 없음 - 2025-08-27 확인)
|
||||
3. ✅ **뉴스 키워드 하드코딩 제거** (2025-08-26 21:00 완료)
|
||||
- rb8001/app/skills/dm_skill.py 수정 (커밋: aed931e)
|
||||
- user_preferences 테이블 활용
|
||||
- user_preference 테이블 활용
|
||||
- 사용자별 맞춤 키워드 설정 가능
|
||||
4. ✅ **이메일 요약 프롬프트 수정** (2025-08-26 21:00 완료)
|
||||
- Slack mrkdwn 형식으로 변경 (커밋: 7103599)
|
||||
@ -203,7 +203,7 @@ SELECT
|
||||
u.username,
|
||||
wm.robeing_id
|
||||
FROM slack_user_mapping sum
|
||||
JOIN users u ON sum.user_id = u.id
|
||||
JOIN user u ON sum.user_id = u.id
|
||||
LEFT JOIN workspace_member wm ON u.id = wm.user_id;
|
||||
```
|
||||
|
||||
|
||||
@ -46,12 +46,12 @@ CREATE INDEX idx_gmail_token_slack_user_id ON gmail_token(slack_user_id); --
|
||||
- ~~rb8001이 `["AI", "기술", "IT"]`만 사용 (dm_skill.py:309)~~
|
||||
- ~~매일 같은 뉴스 반복~~
|
||||
|
||||
### ✅ 구현 완료: user_preferences 테이블 (생성 확인됨)
|
||||
### ✅ 구현 완료: user_preference 테이블 (생성 확인됨)
|
||||
|
||||
```sql
|
||||
CREATE TABLE user_preferences ( -- ✅ 테이블 생성 완료
|
||||
CREATE TABLE user_preference ( -- ✅ 테이블 생성 완료
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
slack_user_id VARCHAR(100),
|
||||
news_keywords VARCHAR(128)[], -- ✅ 배열 타입 적용됨
|
||||
email_filter VARCHAR(128)[], -- ✅ 배열 타입 적용됨
|
||||
@ -64,7 +64,7 @@ CREATE TABLE user_preferences ( -- ✅ 테이블 생성 완료
|
||||
### ✅ rb8001 코드 수정 완료 (커밋: aed931e, 7103599)
|
||||
- dm_skill.py의 get_news_content() 메서드에서 사용자별 키워드 조회 구현
|
||||
- _get_user_news_keywords() 메서드 추가
|
||||
- user_preferences 테이블에서 조회, 없으면 기본값 사용
|
||||
- user_preference 테이블에서 조회, 없으면 기본값 사용
|
||||
- send_daily_summary_dm()에서 사용자별 뉴스 제공
|
||||
|
||||
### ⏳ 슬랙 명령어 설계 (추후 구현 예정)
|
||||
@ -81,13 +81,13 @@ CREATE TABLE user_preferences ( -- ✅ 테이블 생성 완료
|
||||
|
||||
#### 구현 방법
|
||||
1. rb8001이 메시지에서 "뉴스 키워드 설정:" 패턴 감지
|
||||
2. user_preferences 테이블에 키워드 저장 (INSERT ON CONFLICT UPDATE)
|
||||
2. user_preference 테이블에 키워드 저장 (INSERT ON CONFLICT UPDATE)
|
||||
3. 다음 브리핑부터 해당 키워드로 뉴스 검색
|
||||
|
||||
### 프론트엔드 연동
|
||||
- ActivityPanel 설정 UI에서도 동일하게 user_preferences 수정
|
||||
- ActivityPanel 설정 UI에서도 동일하게 user_preference 수정
|
||||
- Gateway API 엔드포인트로 CRUD 구현
|
||||
- **⚠️ 구조 불일치 문제 발견**(일부 환경 DB 미반영으로 오류 가능): [상세 문서](/home/happybell/projects/ivada/DOCS/troubleshooting/250827_frontend_backend_user_preferences_mismatch.md) 참조
|
||||
- **⚠️ 구조 불일치 문제 발견**(일부 환경 DB 미반영으로 오류 가능): [상세 문서](/home/happybell/projects/ivada/DOCS/troubleshooting/250827_frontend_backend_user_preference_mismatch.md) 참조
|
||||
|
||||
---
|
||||
|
||||
@ -98,7 +98,7 @@ CREATE TABLE user_preferences ( -- ✅ 테이블 생성 완료
|
||||
- gmail_token.slack_id → slack_user_id 변경 완료
|
||||
- 인덱스 idx_gmail_token_slack_user_id 생성됨
|
||||
|
||||
2. **user_preferences 테이블 생성** (2025-08-27 DB 확인)
|
||||
2. **user_preference 테이블 생성** (2025-08-27 DB 확인)
|
||||
- 테이블 존재 확인됨
|
||||
- news_keywords, email_filter 배열 타입 적용됨
|
||||
|
||||
|
||||
@ -132,7 +132,7 @@ jwt_token = create_access_token(data={
|
||||
```python
|
||||
# database.py:170-199 이미 완벽 구현
|
||||
async def get_user_by_username(username: str):
|
||||
# SELECT id::text as user_id FROM users WHERE username = :username
|
||||
# SELECT id::text as user_id FROM user WHERE username = :username
|
||||
# username으로 UUID 조회 정상 작동
|
||||
# JWT sub가 UUID로 바뀌면 이 변환 불필요해짐
|
||||
```
|
||||
@ -166,7 +166,7 @@ username = payload.get("username") # username
|
||||
### 5.1 현재 상태 확인 (51123 검증 완료)
|
||||
```bash
|
||||
# Users 테이블 확인 (51123)
|
||||
SELECT id, username FROM users WHERE username='happybell80';
|
||||
SELECT id, username FROM user WHERE username='happybell80';
|
||||
# id: 1e16e9d5-59f3-54da-a661-8abeabff4230 (정상 UUID4)
|
||||
# username: happybell80
|
||||
|
||||
|
||||
@ -31,13 +31,13 @@
|
||||
- 스케줄 설정 (매일/평일/주말/커스텀)
|
||||
- 포함 항목 선택 (이메일/뉴스/캘린더/슬랙)
|
||||
|
||||
### 2.2 Backend (user_preferences 테이블)
|
||||
### 2.2 Backend (user_preference 테이블)
|
||||
- **위치**: PostgreSQL main_db
|
||||
- **구조**:
|
||||
```sql
|
||||
CREATE TABLE user_preferences (
|
||||
CREATE TABLE user_preference (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
slack_user_id VARCHAR(100),
|
||||
news_keywords VARCHAR(128)[], -- 뉴스 키워드 배열
|
||||
email_filter VARCHAR(128)[], -- 이메일 필터 (미사용)
|
||||
@ -48,7 +48,7 @@
|
||||
```
|
||||
|
||||
### 2.3 rb8001 사용 현황
|
||||
- **dm_skill.py**: user_preferences에서 news_keywords 조회
|
||||
- **dm_skill.py**: user_preference에서 news_keywords 조회
|
||||
- **사용자별 맞춤 뉴스**: 정상 작동 중
|
||||
- **브리핑 시간**: briefing_time 사용 중
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
|
||||
### 3.1 데이터 모델 불일치
|
||||
|
||||
| Frontend TaskSettings | Backend user_preferences | 불일치 내용 |
|
||||
| Frontend TaskSettings | Backend user_preference | 불일치 내용 |
|
||||
|---------------------|------------------------|------------|
|
||||
| keywords: string[] | news_keywords VARCHAR(128)[] | ✅ 호환 가능 |
|
||||
| scheduleTime: string | briefing_time TIME | ⚠️ 타입 변환 필요 |
|
||||
@ -176,12 +176,12 @@ Response: 403 Forbidden - "Can only access your own preferences"
|
||||
### 4.1 단기 해결책 (최소 수정)
|
||||
1. **Backend 스키마 확장**
|
||||
```sql
|
||||
ALTER TABLE user_preferences ADD COLUMN schedule_type VARCHAR(20);
|
||||
ALTER TABLE user_preferences ADD COLUMN schedule_days VARCHAR(10)[];
|
||||
ALTER TABLE user_preferences ADD COLUMN include_email BOOLEAN DEFAULT true;
|
||||
ALTER TABLE user_preferences ADD COLUMN include_news BOOLEAN DEFAULT true;
|
||||
ALTER TABLE user_preferences ADD COLUMN include_calendar BOOLEAN DEFAULT false;
|
||||
ALTER TABLE user_preferences ADD COLUMN include_slack BOOLEAN DEFAULT false;
|
||||
ALTER TABLE user_preference ADD COLUMN schedule_type VARCHAR(20);
|
||||
ALTER TABLE user_preference ADD COLUMN schedule_days VARCHAR(10)[];
|
||||
ALTER TABLE user_preference ADD COLUMN include_email BOOLEAN DEFAULT true;
|
||||
ALTER TABLE user_preference ADD COLUMN include_news BOOLEAN DEFAULT true;
|
||||
ALTER TABLE user_preference ADD COLUMN include_calendar BOOLEAN DEFAULT false;
|
||||
ALTER TABLE user_preference ADD COLUMN include_slack BOOLEAN DEFAULT false;
|
||||
```
|
||||
|
||||
2. **robeing-monitor에 CRUD API 추가**
|
||||
@ -199,7 +199,7 @@ Response: 403 Forbidden - "Can only access your own preferences"
|
||||
```sql
|
||||
CREATE TABLE scheduled_tasks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id UUID REFERENCES users(id),
|
||||
user_id UUID REFERENCES user(id),
|
||||
task_type VARCHAR(50), -- 'daily_briefing', 'weekly_report' 등
|
||||
title VARCHAR(255),
|
||||
schedule_type VARCHAR(20),
|
||||
@ -257,7 +257,7 @@ Gateway (8100) + JWT 인증
|
||||
↓
|
||||
robeing-monitor (9024)
|
||||
↓
|
||||
PostgreSQL user_preferences 테이블
|
||||
PostgreSQL user_preference 테이블
|
||||
```
|
||||
|
||||
### UUID 체계
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
- Mock 데이터 하드코딩
|
||||
|
||||
// Backend (dm_skill.py)
|
||||
- PostgreSQL user_preferences 테이블 사용
|
||||
- PostgreSQL user_preference 테이블 사용
|
||||
- 사용자당 1개 설정만 저장
|
||||
- news_keywords만 활용
|
||||
```
|
||||
@ -47,7 +47,7 @@
|
||||
- API 엔드포인트 미구현
|
||||
- 다중 작업 관리 불가
|
||||
|
||||
**관련 문서:** `/DOCS/troubleshooting/250827_frontend_backend_user_preferences_mismatch.md`
|
||||
**관련 문서:** `/DOCS/troubleshooting/250827_frontend_backend_user_preference_mismatch.md`
|
||||
|
||||
#### B. Gmail 토큰 관련 코드 확인 ✅
|
||||
**현황:**
|
||||
@ -138,7 +138,7 @@ rb8001이 모든 사용자 대화를 하나의 ChromaDB 컬렉션에 저장:
|
||||
- ~~기존 데이터 마이그레이션~~
|
||||
|
||||
2. **Frontend-Backend 연동 재설계**
|
||||
- user_preferences 테이블 구조 확장
|
||||
- user_preference 테이블 구조 확장
|
||||
- API 엔드포인트 구현
|
||||
- 다중 작업 관리 지원
|
||||
|
||||
@ -170,7 +170,7 @@ rb8001이 모든 사용자 대화를 하나의 ChromaDB 컬렉션에 저장:
|
||||
|
||||
## 7. 참고 문서
|
||||
|
||||
- [Frontend-Backend 불일치 분석](./250827_frontend_backend_user_preferences_mismatch.md)
|
||||
- [Frontend-Backend 불일치 분석](./250827_frontend_backend_user_preference_mismatch.md)
|
||||
- [51124 서버 핵심 이슈 (ChromaDB/토큰)](./250827_51124_critical_issues.md)
|
||||
- [ID 체계 표준화](./250826_slack_id_column_standardization.md)
|
||||
- [보안 공격 차단](./250826_security_attack_detection.md)
|
||||
|
||||
@ -69,7 +69,7 @@ async def get_user_mapping(identifier: str, db: Session = Depends(get_db)):
|
||||
# UUID로 직접 조회
|
||||
query = text("""
|
||||
SELECT u.id as user_id, u.username, u.email, wm.robeing_id
|
||||
FROM users u
|
||||
FROM user u
|
||||
LEFT JOIN workspace_member wm ON u.id = wm.user_id
|
||||
WHERE u.id = :user_id
|
||||
""")
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
-- 확인 결과: 모두 0 rows
|
||||
SELECT * FROM slack_user_mapping WHERE user_id = '237494f7-061c-484c-a4f7-f500611e32f1'; -- ❌
|
||||
SELECT * FROM workspace_member WHERE user_id = '237494f7-061c-484c-a4f7-f500611e32f1'; -- ❌
|
||||
SELECT * FROM user_preferences WHERE user_id = '237494f7-061c-484c-a4f7-f500611e32f1'; -- ❌
|
||||
SELECT * FROM user_preference WHERE user_id = '237494f7-061c-484c-a4f7-f500611e32f1'; -- ❌
|
||||
```
|
||||
|
||||
## 3. 근본 원인
|
||||
@ -26,7 +26,7 @@ auth-server의 Slack OAuth 콜백(`/auth/slack/login/callback`)에서:
|
||||
1. ✅ users 테이블 생성/업데이트
|
||||
2. ❌ slack_user_mapping 생성 안 함
|
||||
3. ❌ workspace_member 추가 안 함
|
||||
4. ❌ user_preferences 초기화 안 함
|
||||
4. ❌ user_preference 초기화 안 함
|
||||
|
||||
## 4. 영향
|
||||
- workspace_member 자동 추가 구현됨(9/11), 기본 robeing 할당 정상
|
||||
@ -36,7 +36,7 @@ auth-server의 Slack OAuth 콜백(`/auth/slack/login/callback`)에서:
|
||||
## 5. 즉시 해결 (수동)
|
||||
```sql
|
||||
-- 1. username 설정
|
||||
UPDATE users SET username = 'hongtj' WHERE id = '237494f7-061c-484c-a4f7-f500611e32f1';
|
||||
UPDATE user SET username = 'hongtj' WHERE id = '237494f7-061c-484c-a4f7-f500611e32f1';
|
||||
|
||||
-- 2. workspace_member 추가 (team_id 확인 필요)
|
||||
INSERT INTO workspace_member (user_id, workspace_id, robeing_id)
|
||||
|
||||
@ -62,7 +62,7 @@ async def slack_proxy(request: Request):
|
||||
|
||||
# DB 조회 (team_id 인덱스 활용)
|
||||
token = await db.fetch_one(
|
||||
"SELECT bot_token FROM slack_workspaces WHERE team_id = ?",
|
||||
"SELECT bot_token FROM slack_workspace WHERE team_id = ?",
|
||||
team_id
|
||||
)
|
||||
|
||||
|
||||
@ -33,11 +33,11 @@
|
||||
| 파일 경로 | 라인 번호 | 작업 내용 |
|
||||
|-----------|-----------|-----------|
|
||||
| auth-server/app/models/user.py | 21-35 | 테이블 모델 정의 (picture 컬럼) |
|
||||
| auth-server/app/providers/gmail_passport.py | 178 | SELECT id FROM users WHERE username = $1 |
|
||||
| auth-server/app/providers/gmail_passport.py | 187 | SELECT username FROM users WHERE id = $1 |
|
||||
| auth-server/app/providers/gmail_passport.py | 178 | SELECT id FROM user WHERE username = $1 |
|
||||
| auth-server/app/providers/gmail_passport.py | 187 | SELECT username FROM user WHERE id = $1 |
|
||||
| robeing-gateway/app/database.py | 98-112 | JOIN 쿼리 (workspace_member, workspaces와 함께) |
|
||||
| robeing-gateway/app/database.py | 182-191 | SELECT * FROM users WHERE username = $1 |
|
||||
| robeing-gateway/app/database.py | 321-328 | SELECT * FROM users (전체 조회) |
|
||||
| robeing-gateway/app/database.py | 182-191 | SELECT * FROM user WHERE username = $1 |
|
||||
| robeing-gateway/app/database.py | 321-328 | SELECT * FROM user (전체 조회) |
|
||||
| robeing-gateway/app/models.py | 11-24 | 테이블 모델 정의 (avatar_url 컬럼) |
|
||||
|
||||
### 2.2 company/team 테이블 (실제 DB: company+team, 코드: workspaces 참조)
|
||||
@ -85,8 +85,8 @@
|
||||
|-----------|-----------|-----------|
|
||||
| auth-server/app/models/workspace.py | 43-62 | 테이블 모델 정의 (현재 company_id로 정의됨) |
|
||||
| auth-server/migrations/add_user_workspace_tables.sql | 60-76 | ALTER TABLE 정의 (company_id → workspace_id 변경) |
|
||||
| robeing-gateway/app/main.py | 522-525 | SELECT bot_token FROM slack_workspaces WHERE team_id = $1 |
|
||||
| robeing-gateway/app/main.py | 567-570 | SELECT bot_token FROM slack_workspaces WHERE team_id = $1 |
|
||||
| robeing-gateway/app/main.py | 522-525 | SELECT bot_token FROM slack_workspace WHERE team_id = $1 |
|
||||
| robeing-gateway/app/main.py | 567-570 | SELECT bot_token FROM slack_workspace WHERE team_id = $1 |
|
||||
|
||||
### 2.6 gmail_token 테이블 (실제 DB: gmail_token, 3건)
|
||||
**실제 DB 컬럼**: user_id(FK), token_data(jsonb), oauth_config(jsonb), created_at, updated_at
|
||||
@ -158,7 +158,7 @@
|
||||
|
||||
### 2.11 user_preference 테이블 (실제 DB: user_preference, 0건)
|
||||
**실제 DB 컬럼**: user_id(FK), slack_user_id, news_keywords[], briefing_enabled, briefing_time, created_at, updated_at
|
||||
**코드 모델**: user_preferences 참조 (복수형 차이)
|
||||
**코드 모델**: user_preference 참조 (복수형 차이)
|
||||
|
||||
| 파일 경로 | 라인 번호 | 작업 내용 |
|
||||
|-----------|-----------|-----------|
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user