'use server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import db from '@/db/db'; import { users, vendors } from '@/db/schema'; import { and, eq, ilike, or, asc } from 'drizzle-orm'; import { revalidatePath } from 'next/cache'; import { getErrorMessage } from '@/lib/handle-error'; import { unstable_noStore } from 'next/cache'; /** * 유저 목록 검색 (limit 100) */ export async function searchUsers(search?: string) { unstable_noStore(); try { const session = await getServerSession(authOptions); if (!session?.user) { return { data: null, error: '로그인이 필요합니다.' }; } let whereCondition; // 검색어가 있으면 이름 또는 이메일로 검색 if (search && search.trim()) { const searchPattern = `%${search.trim()}%`; whereCondition = or( ilike(users.name, searchPattern), ilike(users.email, searchPattern) ); } const usersList = await db .select({ id: users.id, name: users.name, email: users.email, companyId: users.companyId, }) .from(users) .where(whereCondition) .orderBy(asc(users.name)) .limit(100); return { data: usersList, error: null, }; } catch (error) { return { data: null, error: getErrorMessage(error) }; } } /** * 특정 유저의 벤더 정보 조회 */ export async function getUserVendorInfo(userId: number) { unstable_noStore(); try { const session = await getServerSession(authOptions); if (!session?.user) { return { data: null, error: '로그인이 필요합니다.' }; } // 사용자 정보 조회 const user = await db .select({ id: users.id, name: users.name, email: users.email, companyId: users.companyId, }) .from(users) .where(eq(users.id, userId)) .limit(1); if (!user[0]) { return { data: null, error: '사용자를 찾을 수 없습니다.' }; } // 현재 벤더 정보 조회 (companyId가 있는 경우) let vendor = null; if (user[0].companyId) { const vendorResult = await db .select({ id: vendors.id, vendorName: vendors.vendorName, vendorCode: vendors.vendorCode, }) .from(vendors) .where(eq(vendors.id, user[0].companyId)) .limit(1); vendor = vendorResult[0] || null; } return { data: { userId: user[0].id, userName: user[0].name, userEmail: user[0].email, currentVendorId: user[0].companyId, currentVendorName: vendor?.vendorName || null, currentVendorCode: vendor?.vendorCode || null, }, error: null, }; } catch (error) { return { data: null, error: getErrorMessage(error) }; } } /** * 벤더 목록 조회 (활성 상태만, 검색 기능 포함, limit 100) */ export async function getVendorList(search?: string) { unstable_noStore(); try { const statusCondition = eq(vendors.status, 'ACTIVE'); // 검색어가 있으면 벤더명 또는 벤더코드로 검색 if (search && search.trim()) { const searchPattern = `%${search.trim()}%`; const searchConditions = [ ilike(vendors.vendorName, searchPattern), ilike(vendors.vendorCode, searchPattern), ]; const whereCondition = and( statusCondition, or(...searchConditions) ); const vendorsList = await db .select({ id: vendors.id, vendorName: vendors.vendorName, vendorCode: vendors.vendorCode, status: vendors.status, }) .from(vendors) .where(whereCondition) .orderBy(asc(vendors.vendorName)) .limit(100); return { data: vendorsList, error: null, }; } // 검색어가 없으면 활성 상태만 조회 const whereCondition = statusCondition; const vendorsList = await db .select({ id: vendors.id, vendorName: vendors.vendorName, vendorCode: vendors.vendorCode, status: vendors.status, }) .from(vendors) .where(whereCondition) .orderBy(asc(vendors.vendorName)) .limit(100); return { data: vendorsList, error: null, }; } catch (error) { return { data: null, error: getErrorMessage(error) }; } } /** * 벤더 변경 서버 액션 (특정 유저의 벤더 변경) */ export async function changeVendor(userId: number, newVendorId: number) { unstable_noStore(); try { const session = await getServerSession(authOptions); if (!session?.user) { return { success: false, error: '로그인이 필요합니다.' }; } // 대상 사용자 확인 const targetUser = await db .select({ id: users.id, name: users.name, email: users.email, }) .from(users) .where(eq(users.id, userId)) .limit(1); if (!targetUser[0]) { return { success: false, error: '사용자를 찾을 수 없습니다.' }; } // 새 벤더 정보 확인 const newVendor = await db .select({ id: vendors.id, vendorName: vendors.vendorName, vendorCode: vendors.vendorCode, status: vendors.status, }) .from(vendors) .where(eq(vendors.id, newVendorId)) .limit(1); if (!newVendor[0]) { return { success: false, error: '벤더를 찾을 수 없습니다.' }; } if (newVendor[0].status !== 'ACTIVE') { return { success: false, error: '활성 상태인 벤더만 선택할 수 있습니다.' }; } // 사용자의 companyId 업데이트 await db .update(users) .set({ companyId: newVendorId, updatedAt: new Date(), }) .where(eq(users.id, userId)); // 세션 재검증을 위해 경로 재검증 revalidatePath('/', 'layout'); return { success: true, data: { userId: targetUser[0].id, userName: targetUser[0].name, userEmail: targetUser[0].email, vendorId: newVendor[0].id, vendorName: newVendor[0].vendorName, vendorCode: newVendor[0].vendorCode, }, error: null, }; } catch (error) { return { success: false, error: getErrorMessage(error) }; } }