// lib/rfq/service.ts 'use server' import { unstable_noStore } from "next/cache"; import db from "@/db/db"; import { rfqsLastView } from "@/db/schema"; import { and, desc, asc, ilike, or, eq, SQL, count, gte, lte,isNotNull,ne } from "drizzle-orm"; import { filterColumns } from "@/lib/filter-columns"; import { GetRfqsSchema } from "./validations"; export async function getRfqs(input: GetRfqsSchema) { unstable_noStore(); try { const offset = (input.page - 1) * input.perPage; // 1. RFQ 타입별 필터링 let typeFilter: SQL | undefined = undefined; if (input.rfqCategory) { switch (input.rfqCategory) { case "general": // 일반견적: rfqType이 있는 경우 typeFilter = and( isNotNull(rfqsLastView.rfqType), ne(rfqsLastView.rfqType, '') ); break; case "itb": // ITB: projectCompany가 있는 경우 typeFilter = and( isNotNull(rfqsLastView.projectCompany), ne(rfqsLastView.projectCompany, '') ); break; case "rfq": // RFQ: prNumber가 있는 경우 typeFilter = and( isNotNull(rfqsLastView.prNumber), ne(rfqsLastView.prNumber, '') ); break; } } // 2. 고급 필터 처리 let advancedWhere: SQL | undefined = undefined; if (input.filters && Array.isArray(input.filters) && input.filters.length > 0) { console.log("필터 적용:", input.filters.map(f => `${f.id} ${f.operator} ${f.value}`)); try { advancedWhere = filterColumns({ table: rfqsLastView, filters: input.filters, joinOperator: input.joinOperator || 'and', }); console.log("필터 조건 생성 완료"); } catch (error) { console.error("필터 조건 생성 오류:", error); advancedWhere = undefined; } } // 3. 글로벌 검색 조건 let globalWhere: SQL | undefined = undefined; if (input.search) { const s = `%${input.search}%`; const searchConditions: SQL[] = [ ilike(rfqsLastView.rfqCode, s), ilike(rfqsLastView.itemCode, s), ilike(rfqsLastView.itemName, s), ilike(rfqsLastView.packageNo, s), ilike(rfqsLastView.packageName, s), ilike(rfqsLastView.picName, s), ilike(rfqsLastView.engPicName, s), ilike(rfqsLastView.projectCode, s), ilike(rfqsLastView.projectName, s), ilike(rfqsLastView.rfqTitle, s), ilike(rfqsLastView.prNumber, s), ].filter(Boolean); if (searchConditions.length > 0) { globalWhere = or(...searchConditions); } } // 4. 최종 WHERE 조건 결합 const whereConditions: SQL[] = []; if (typeFilter) whereConditions.push(typeFilter); if (advancedWhere) whereConditions.push(advancedWhere); if (globalWhere) whereConditions.push(globalWhere); const finalWhere = whereConditions.length > 0 ? and(...whereConditions) : undefined; // 5. 전체 데이터 수 조회 const totalResult = await db .select({ count: count() }) .from(rfqsLastView) .where(finalWhere); const total = totalResult[0]?.count || 0; if (total === 0) { return { data: [], pageCount: 0, total: 0 }; } console.log("총 데이터 수:", total); // 6. 정렬 및 페이징 처리 const orderByColumns = input.sort.map((sort) => { const column = sort.id as keyof typeof rfqsLastView.$inferSelect; return sort.desc ? desc(rfqsLastView[column]) : asc(rfqsLastView[column]); }); if (orderByColumns.length === 0) { orderByColumns.push(desc(rfqsLastView.createdAt)); } const rfqData = await db .select() .from(rfqsLastView) .where(finalWhere) .orderBy(...orderByColumns) .limit(input.perPage) .offset(offset); const pageCount = Math.ceil(total / input.perPage); console.log("반환 데이터 수:", rfqData.length); return { data: rfqData, pageCount, total }; } catch (err) { console.error("getRfqs 오류:", err); return { data: [], pageCount: 0, total: 0 }; } }