diff options
Diffstat (limited to 'lib/material/material-group-service.ts')
| -rw-r--r-- | lib/material/material-group-service.ts | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/lib/material/material-group-service.ts b/lib/material/material-group-service.ts new file mode 100644 index 00000000..216cd0e6 --- /dev/null +++ b/lib/material/material-group-service.ts @@ -0,0 +1,105 @@ +"use server"; + +import { sql, SQL } from "drizzle-orm"; +import db from "@/db/db"; +import { materialSearchView } from "@/db/schema/items"; + +export interface MaterialSearchItem { + materialGroupCode: string; + materialName: string; + displayText: string; +} + +export interface MaterialSearchResult { + success: boolean; + data: MaterialSearchItem[]; + pagination: { + page: number; + perPage: number; + total: number; + pageCount: number; + hasNextPage: boolean; + hasPrevPage: boolean; + }; +} + +/** + * 자재 검색 함수 - material_search_view에서 검색 + */ +export async function searchMaterialsForSelector( + query: string, + page: number = 1, + perPage: number = 10 +): Promise<MaterialSearchResult> { + try { + const offset = (page - 1) * perPage; + + // 검색 조건 + let searchWhere: SQL<unknown> | undefined; + if (query.trim()) { + const searchPattern = `%${query.trim()}%`; + searchWhere = sql`( + ${materialSearchView.materialGroupCode} ILIKE ${searchPattern} OR + ${materialSearchView.materialName} ILIKE ${searchPattern} OR + ${materialSearchView.displayText} ILIKE ${searchPattern} + )`; + } + + const { data, total } = await db.transaction(async (tx) => { + // 데이터 조회 + const data = await tx + .select() + .from(materialSearchView) + .where(searchWhere) + .orderBy(materialSearchView.materialGroupCode, materialSearchView.materialName) + .limit(perPage) + .offset(offset); + + // 총 개수 조회 + const countResult = await tx + .select({ count: sql<number>`count(*)` }) + .from(materialSearchView) + .where(searchWhere); + + const total = countResult[0]?.count || 0; + + return { + data: data.map((row) => ({ + materialGroupCode: row.materialGroupCode, + materialName: row.materialName, + displayText: row.displayText, + })), + total, + }; + }); + + const pageCount = Math.ceil(total / perPage); + + return { + success: true, + data, + pagination: { + page, + perPage, + total, + pageCount, + hasNextPage: page < pageCount, + hasPrevPage: page > 1, + }, + }; + } catch (error) { + console.error("자재 검색 오류:", error); + return { + success: false, + data: [], + pagination: { + page: 1, + perPage: 10, + total: 0, + pageCount: 0, + hasNextPage: false, + hasPrevPage: false, + }, + }; + } +} |
