diff options
Diffstat (limited to 'lib/material/material-group-service.ts')
| -rw-r--r-- | lib/material/material-group-service.ts | 122 |
1 files changed, 91 insertions, 31 deletions
diff --git a/lib/material/material-group-service.ts b/lib/material/material-group-service.ts index bf58d243..41f06fac 100644 --- a/lib/material/material-group-service.ts +++ b/lib/material/material-group-service.ts @@ -30,7 +30,8 @@ export interface MaterialSearchResult { export async function searchMaterialsForSelector( query: string, page: number = 1, - perPage: number = 10 + perPage: number = 10, + hideCode: boolean = false ): Promise<MaterialSearchResult> { try { const offset = (page - 1) * perPage; @@ -39,42 +40,101 @@ export async function searchMaterialsForSelector( let searchWhere: SQL<unknown> | undefined; if (query.trim()) { const searchPattern = `%${query.trim()}%`; - searchWhere = sql`( - ${MATERIAL_GROUP_MASTER.materialGroupCode} ILIKE ${searchPattern} OR - ${MATERIAL_GROUP_MASTER.materialGroupDescription} ILIKE ${searchPattern} - )`; + if (hideCode) { + // 코드 보호 모드: 설명만 검색 + searchWhere = sql`${MATERIAL_GROUP_MASTER.materialGroupDescription} ILIKE ${searchPattern}`; + } else { + // 일반 모드: 코드와 설명 모두 검색 + searchWhere = sql`( + ${MATERIAL_GROUP_MASTER.materialGroupCode} ILIKE ${searchPattern} OR + ${MATERIAL_GROUP_MASTER.materialGroupDescription} ILIKE ${searchPattern} + )`; + } } const { data, total } = await db.transaction(async (tx) => { - // 데이터 조회 - const data = await tx - .select({ - materialGroupCode: MATERIAL_GROUP_MASTER.materialGroupCode, - materialGroupDescription: MATERIAL_GROUP_MASTER.materialGroupDescription, - materialGroupUom: MATERIAL_GROUP_MASTER.materialGroupUom, - }) - .from(MATERIAL_GROUP_MASTER) - .where(searchWhere) - .orderBy(MATERIAL_GROUP_MASTER.materialGroupCode, MATERIAL_GROUP_MASTER.materialGroupDescription) - .limit(perPage) - .offset(offset); - - // 총 개수 조회 - const countResult = await tx - .select({ count: sql<number>`count(*)` }) - .from(MATERIAL_GROUP_MASTER) - .where(searchWhere); - - const total = countResult[0]?.count || 0; + let data; + let totalCount; + + if (hideCode) { + // 코드 보호 모드: 같은 이름의 자재 중복 제거 (DISTINCT ON) + data = await tx + .select({ + materialGroupCode: MATERIAL_GROUP_MASTER.materialGroupCode, + materialGroupDescription: MATERIAL_GROUP_MASTER.materialGroupDescription, + materialGroupUom: MATERIAL_GROUP_MASTER.materialGroupUom, + }) + .from(MATERIAL_GROUP_MASTER) + .where(searchWhere) + .orderBy(MATERIAL_GROUP_MASTER.materialGroupDescription, MATERIAL_GROUP_MASTER.materialGroupCode) + .$dynamic(); // Drizzle에서 DISTINCT ON을 위해 dynamic 쿼리 사용 + + // 실제로는 DISTINCT ON을 위해 raw SQL 사용 + const distinctQuery = sql` + SELECT DISTINCT ON (material_group_description) + material_group_code, material_group_description, material_group_uom + FROM ${MATERIAL_GROUP_MASTER} + ${searchWhere ? sql`WHERE ${searchWhere}` : sql``} + ORDER BY material_group_description, material_group_code + LIMIT ${perPage} OFFSET ${offset} + `; + + const distinctResult = await tx.execute(distinctQuery); + data = distinctResult.rows as { + material_group_code: string; + material_group_description: string; + material_group_uom: string | null; + }[]; + + // 총 개수도 DISTINCT로 계산 + const countQuery = sql` + SELECT COUNT(DISTINCT material_group_description) as count + FROM ${MATERIAL_GROUP_MASTER} + ${searchWhere ? sql`WHERE ${searchWhere}` : sql``} + `; + + const countResult = await tx.execute(countQuery); + totalCount = Number(countResult.rows[0]?.count) || 0; + } else { + // 일반 모드: 기존 방식 유지 + data = await tx + .select({ + materialGroupCode: MATERIAL_GROUP_MASTER.materialGroupCode, + materialGroupDescription: MATERIAL_GROUP_MASTER.materialGroupDescription, + materialGroupUom: MATERIAL_GROUP_MASTER.materialGroupUom, + }) + .from(MATERIAL_GROUP_MASTER) + .where(searchWhere) + .orderBy(MATERIAL_GROUP_MASTER.materialGroupCode, MATERIAL_GROUP_MASTER.materialGroupDescription) + .limit(perPage) + .offset(offset); + + // 총 개수 조회 + const countResult = await tx + .select({ count: sql<number>`count(*)` }) + .from(MATERIAL_GROUP_MASTER) + .where(searchWhere); + + totalCount = countResult[0]?.count || 0; + } return { - data: data.map((row) => ({ - materialGroupCode: row.materialGroupCode, - materialGroupDescription: row.materialGroupDescription, - materialGroupUom: row.materialGroupUom, - displayText: `${row.materialGroupCode || ''} - ${row.materialGroupDescription || ''}`, // 애플리케이션 레벨에서 생성 + data: data.map((row: { + material_group_code?: string; + materialGroupCode?: string; + material_group_description?: string; + materialGroupDescription?: string; + material_group_uom?: string | null; + materialGroupUom?: string | null; + }) => ({ + materialGroupCode: row.material_group_code || row.materialGroupCode, + materialGroupDescription: row.material_group_description || row.materialGroupDescription, + materialGroupUom: row.material_group_uom || row.materialGroupUom, + displayText: hideCode + ? `${(row.material_group_description || row.materialGroupDescription) || ''}` // 코드 보호 모드: 설명만 + : `${(row.material_group_code || row.materialGroupCode) || ''} - ${(row.material_group_description || row.materialGroupDescription) || ''}`, // 일반 모드: 코드 + 설명 })), - total, + total: totalCount, }; }); |
