diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-07 06:53:06 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-07 06:53:06 +0000 |
| commit | 121a382b2d3c547f8facce73f57dbdbcf847d879 (patch) | |
| tree | 46cb96da0302ad15ba8c71829a4e3a62c1bb5db1 /lib | |
| parent | 8daa2aeee017c642d2fd171094cf5d442966eb12 (diff) | |
(최겸) 구매 정보시스템 user vendorid 변경 기능 개발(신규)
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/change-vendor/service.ts | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/lib/change-vendor/service.ts b/lib/change-vendor/service.ts new file mode 100644 index 00000000..09c93a26 --- /dev/null +++ b/lib/change-vendor/service.ts @@ -0,0 +1,258 @@ +'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) }; + } +} + |
