diff options
Diffstat (limited to 'lib/rfq-last/service.ts')
| -rw-r--r-- | lib/rfq-last/service.ts | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/lib/rfq-last/service.ts b/lib/rfq-last/service.ts new file mode 100644 index 00000000..f2710f02 --- /dev/null +++ b/lib/rfq-last/service.ts @@ -0,0 +1,141 @@ +// 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<unknown> | 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<unknown> | 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<unknown> | undefined = undefined; + if (input.search) { + const s = `%${input.search}%`; + + const searchConditions: SQL<unknown>[] = [ + 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<unknown>[] = []; + 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 }; + } +} + |
