diff options
| author | joonhoekim <26rote@gmail.com> | 2025-10-14 20:27:47 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-10-14 20:27:47 +0900 |
| commit | f63cf682d6846210a04ce4a3eb8ebe9afd6d6dba (patch) | |
| tree | 0a4717c11814c45e2b7d6531723700b1ae0a4974 /components/common/selectors/material/material-service.ts | |
| parent | d1cdcf9f35eca0552d1011e6d3c11a1d2d9abee4 (diff) | |
(김준회) 자재코드 선택기 구현 및 일반견적 생성시 반영
Diffstat (limited to 'components/common/selectors/material/material-service.ts')
| -rw-r--r-- | components/common/selectors/material/material-service.ts | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/components/common/selectors/material/material-service.ts b/components/common/selectors/material/material-service.ts new file mode 100644 index 00000000..1f238ed7 --- /dev/null +++ b/components/common/selectors/material/material-service.ts @@ -0,0 +1,155 @@ +"use server"; + +import { sql, SQL } from "drizzle-orm"; +import db from "@/db/db"; +import { MATERIAL_MASTER_PART_MATL } from "@/db/schema/MDG/mdg"; + +export interface MaterialSearchItem { + materialCode: string; // 자재코드 (MATNR) + materialName: string; // 자재명 (ZZNAME) + displayText: string; // 애플리케이션 레벨에서 계산된 필드 +} + +export interface MaterialSearchResult { + success: boolean; + data: MaterialSearchItem[]; + pagination: { + page: number; + perPage: number; + total: number; + pageCount: number; + hasNextPage: boolean; + hasPrevPage: boolean; + }; +} + +/** + * 자재 검색 함수 - MATERIAL_MASTER_PART_MATL 테이블에서 검색 (페이지네이션) + * 사용자는 자재코드를 직접 입력하여 검색함 (자재명이 아닌 자재코드만 검색 대상) + * 자재 레코드가 수억개 수준이므로 항상 페이지네이션 사용 + */ +export async function searchMaterialsForSelector( + query: string, + page: number = 1, + perPage: number = 10 +): Promise<MaterialSearchResult> { + try { + const offset = (page - 1) * perPage; + + // 검색 조건 - 자재코드(MATNR)로만 검색 + let searchWhere: SQL<unknown> | undefined; + if (query.trim()) { + const searchPattern = `%${query.trim()}%`; + searchWhere = sql`${MATERIAL_MASTER_PART_MATL.MATNR} ILIKE ${searchPattern}`; + } + + const { data, total } = await db.transaction(async (tx) => { + // 데이터 조회 - MATNR과 ZZNAME만 선택 + const data = await tx + .select({ + materialCode: MATERIAL_MASTER_PART_MATL.MATNR, + materialName: MATERIAL_MASTER_PART_MATL.ZZNAME, + }) + .from(MATERIAL_MASTER_PART_MATL) + .where(searchWhere) + .orderBy(MATERIAL_MASTER_PART_MATL.MATNR) + .limit(perPage) + .offset(offset); + + // 총 개수 조회 + const countResult = await tx + .select({ count: sql<number>`count(*)` }) + .from(MATERIAL_MASTER_PART_MATL) + .where(searchWhere); + + const total = countResult[0]?.count || 0; + + return { + data: data.map((row) => ({ + materialCode: row.materialCode || '', + materialName: row.materialName || '', + displayText: `${row.materialCode || ''} - ${row.materialName || ''}`, // 애플리케이션 레벨에서 생성 + })), + 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, + }, + }; + } +} + +/** + * Dialog용 자재 목록 조회 함수 - 페이지네이션 + * Dialog에서는 효율적인 사용자 경험을 위해 10개씩 페이지네이션하여 조회 + * 자재 레코드가 수억개 수준이므로 무한 스크롤이나 전체 로드가 아닌 페이지네이션 사용 + */ +export async function searchMaterialsForDialog( + query: string, + page: number = 1, + perPage: number = 10 +): Promise<{ + success: boolean; + data: MaterialSearchItem[]; + pagination: { + page: number; + perPage: number; + total: number; + pageCount: number; + hasNextPage: boolean; + hasPrevPage: boolean; + }; + error?: string; +}> { + try { + const result = await searchMaterialsForSelector(query, page, perPage); + + return { + success: result.success, + data: result.data, + pagination: result.pagination, + error: result.success ? undefined : "검색 중 오류가 발생했습니다.", + }; + } catch (error) { + console.error("Dialog용 자재 검색 오류:", error); + return { + success: false, + data: [], + pagination: { + page: 1, + perPage: 10, + total: 0, + pageCount: 0, + hasNextPage: false, + hasPrevPage: false, + }, + error: "데이터를 불러오는데 실패했습니다.", + }; + } +}
\ No newline at end of file |
