'use server'; import { and, asc, count, desc, eq, ilike, or, sql, } from 'drizzle-orm'; import db from '@/db/db'; import { approvalLogs } from '@/db/schema/knox/approvals'; import { filterColumns } from '@/lib/filter-columns'; // --------------------------------------------- // Types // --------------------------------------------- export type ApprovalLog = typeof approvalLogs.$inferSelect; // --------------------------------------------- // Revalidation helpers (사용하지 않음 - 추후 필요시 추가) // --------------------------------------------- // --------------------------------------------- // List & read helpers // --------------------------------------------- interface ListInput { page: number; perPage: number; search?: string; filters?: Record[]; joinOperator?: 'and' | 'or'; sort?: Array<{ id: string; desc: boolean }>; } export async function getApprovalLogList(input: ListInput) { const offset = (input.page - 1) * input.perPage; /* ------------------------------------------------------------------ * WHERE 절 구성 * ----------------------------------------------------------------*/ const advancedWhere = filterColumns({ table: approvalLogs, // eslint-disable-next-line @typescript-eslint/no-explicit-any filters: (input.filters ?? []) as any, joinOperator: (input.joinOperator ?? 'and') as 'and' | 'or', }); // 전역 검색 (subject, content, emailAddress, userId) let globalWhere; if (input.search) { const s = `%${input.search}%`; globalWhere = or( ilike(approvalLogs.subject, s), ilike(approvalLogs.content, s), ilike(approvalLogs.emailAddress, s), ilike(approvalLogs.userId, s), ); } let where = eq(approvalLogs.isDeleted, false); // 기본적으로 삭제되지 않은 것만 조회 if (advancedWhere && globalWhere) { where = and(where, advancedWhere, globalWhere); } else if (advancedWhere) { where = and(where, advancedWhere); } else if (globalWhere) { where = and(where, globalWhere); } /* ------------------------------------------------------------------ * ORDER BY 절 구성 * ----------------------------------------------------------------*/ let orderBy; try { orderBy = input.sort && input.sort.length > 0 ? input.sort .map((item) => { if (!item || !item.id || typeof item.id !== 'string') return null; if (!(item.id in approvalLogs)) return null; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const col = approvalLogs[item.id]; return item.desc ? desc(col) : asc(col); }) .filter((v): v is Exclude => v !== null) : [desc(approvalLogs.createdAt)]; } catch { orderBy = [desc(approvalLogs.createdAt)]; } /* ------------------------------------------------------------------ * 데이터 조회 * ----------------------------------------------------------------*/ const data = await db .select() .from(approvalLogs) .where(where) .orderBy(...orderBy) .limit(input.perPage) .offset(offset); const totalResult = await db .select({ count: count() }) .from(approvalLogs) .where(where); const total = totalResult[0]?.count ?? 0; const pageCount = Math.ceil(total / input.perPage); return { data, pageCount, }; } // ---------------------------------------------------- // Distinct categories for filter // ---------------------------------------------------- export async function getApprovalLogStatuses(): Promise { const rows = await db .select({ status: approvalLogs.status }) .from(approvalLogs) .where(eq(approvalLogs.isDeleted, false)) .groupBy(approvalLogs.status) .orderBy(asc(approvalLogs.status)); return rows.map((r) => r.status).filter((status) => status !== null && status !== undefined && status !== ''); } // ---------------------------------------------------- // Get distinct user IDs for filter // ---------------------------------------------------- export async function getApprovalLogUserIds(): Promise { const rows = await db .select({ userId: approvalLogs.userId }) .from(approvalLogs) .where(and(eq(approvalLogs.isDeleted, false), sql`${approvalLogs.userId} IS NOT NULL`)) .groupBy(approvalLogs.userId) .orderBy(asc(approvalLogs.userId)); return rows.map((r) => r.userId!).filter((id) => id !== null && id !== undefined && id !== ''); } // ---------------------------------------------------- // Server Action for fetching distinct statuses // ---------------------------------------------------- export async function getApprovalLogStatusesAction() { try { const data = await getApprovalLogStatuses() return { success: true, data } } catch (error) { return { success: false, error: error instanceof Error ? error.message : '상태 조회에 실패했습니다.' } } } // ---------------------------------------------------- // Server Action for fetching distinct user IDs // ---------------------------------------------------- export async function getApprovalLogUserIdsAction() { try { const data = await getApprovalLogUserIds() return { success: true, data } } catch (error) { return { success: false, error: error instanceof Error ? error.message : '사용자 조회에 실패했습니다.' } } } // ---------------------------------------------------- // Get single approval log // ---------------------------------------------------- export async function getApprovalLog(apInfId: string): Promise { const [log] = await db .select() .from(approvalLogs) .where(and(eq(approvalLogs.apInfId, apInfId), eq(approvalLogs.isDeleted, false))) .limit(1); return log || null; } // ---------------------------------------------------- // Server Action for getting approval log list // ---------------------------------------------------- export async function getApprovalLogListAction(input: ListInput) { try { const data = await getApprovalLogList(input); return { success: true, data: data.data, pageCount: data.pageCount }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : '결재 로그 조회에 실패했습니다.', data: [], pageCount: 0 }; } }