diff options
| author | joonhoekim <26rote@gmail.com> | 2025-09-09 11:59:51 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-09-09 11:59:51 +0000 |
| commit | 6459d90482efa57fed6f43204c20fdfbe33ffbd8 (patch) | |
| tree | 344afc13cff2c14763f50a8e45c665edbca1ded4 /lib/material-groups | |
| parent | 085aae795bd0fb20dca7a8a113fd91f483661617 (diff) | |
(김준회) EDP-Progress 프로젝트 목록 찾기 쿼리 오류 수정, 자재그룹 싱크 및 테이블 관련 오류 수정
Diffstat (limited to 'lib/material-groups')
| -rw-r--r-- | lib/material-groups/services.ts | 2 | ||||
| -rw-r--r-- | lib/material-groups/sync-service.ts | 89 | ||||
| -rw-r--r-- | lib/material-groups/table/material-group-table-columns.tsx | 2 |
3 files changed, 53 insertions, 40 deletions
diff --git a/lib/material-groups/services.ts b/lib/material-groups/services.ts index ecbbc9e8..be683077 100644 --- a/lib/material-groups/services.ts +++ b/lib/material-groups/services.ts @@ -43,7 +43,7 @@ export async function getMaterialGroups(input: GetMaterialGroupsInput) { const s = `%${input.search}%`; globalWhere = or( ilike(materialSearchView.materialGroupCode, s), // 자재그룹코드 - ilike(materialSearchView.materialGroupDesc, s), // 자재그룹 설명 + ilike(materialSearchView.materialGroupDesc, s), // 자재그룹명 ); } diff --git a/lib/material-groups/sync-service.ts b/lib/material-groups/sync-service.ts index eda5dba5..9bcdd8bf 100644 --- a/lib/material-groups/sync-service.ts +++ b/lib/material-groups/sync-service.ts @@ -32,44 +32,58 @@ export async function syncMaterialGroupMaster(): Promise<SyncResult> { console.log("📊 자재그룹 마스터 동기화 시작..."); const result = await db.transaction(async (tx) => { - // 1단계: 기존 MDG 테이블에서 MATKL별 영어 설명 조회 + // 1단계: MATKL별로 첫 번째 MATNR 선택 (DISTINCT ON 사용) + const matklWithMatnr = await tx.execute(sql` + SELECT DISTINCT ON (${MATERIAL_MASTER_PART_MATL.MATKL}) + ${MATERIAL_MASTER_PART_MATL.MATKL} as "MATKL", + ${MATERIAL_MASTER_PART_MATL.MATNR} as "MATNR" + FROM ${MATERIAL_MASTER_PART_MATL} + WHERE ${MATERIAL_MASTER_PART_MATL.MATKL} IS NOT NULL + AND ${MATERIAL_MASTER_PART_MATL.MATKL} != '' + ORDER BY ${MATERIAL_MASTER_PART_MATL.MATKL}, ${MATERIAL_MASTER_PART_MATL.MATNR} + `); + + console.log(`🔍 발견된 고유 자재그룹코드: ${matklWithMatnr.rowCount}개`); + + if (matklWithMatnr.rowCount === 0) { + return { + totalProcessed: 0, + newRecords: 0, + updatedRecords: 0, + skippedRecords: 0 + }; + } + + // 2단계: 선택된 MATNR들로 DESC 테이블에서 영어 설명 조회 + const matnrList = matklWithMatnr.rows.map(item => item.MATNR as string); + const materialGroupData = await tx .select({ MATKL: MATERIAL_MASTER_PART_MATL.MATKL, - MAKTX: sql<string>` - ( - SELECT ${MATERIAL_MASTER_PART_MATL_DESC.MAKTX} - FROM ${MATERIAL_MASTER_PART_MATL_DESC} - WHERE ${MATERIAL_MASTER_PART_MATL_DESC.MATNR} = ${MATERIAL_MASTER_PART_MATL.MATNR} - AND ${MATERIAL_MASTER_PART_MATL_DESC.SPRAS} = 'E' - AND ${MATERIAL_MASTER_PART_MATL_DESC.MAKTX} IS NOT NULL - AND ${MATERIAL_MASTER_PART_MATL_DESC.MAKTX} != '' - LIMIT 1 - ) - `.as("MAKTX") + MAKTX: MATERIAL_MASTER_PART_MATL_DESC.MAKTX }) .from(MATERIAL_MASTER_PART_MATL) + .innerJoin( + MATERIAL_MASTER_PART_MATL_DESC, + sql`${MATERIAL_MASTER_PART_MATL.MATNR} = ${MATERIAL_MASTER_PART_MATL_DESC.MATNR}` + ) .where(sql` - ${MATERIAL_MASTER_PART_MATL.MATKL} IS NOT NULL - AND ${MATERIAL_MASTER_PART_MATL.MATKL} != '' - `) - .groupBy(MATERIAL_MASTER_PART_MATL.MATKL); // MATKL별 중복 제거 - - console.log(`🔍 발견된 고유 자재그룹코드: ${materialGroupData.length}개`); + ${MATERIAL_MASTER_PART_MATL.MATNR} IN (${sql.join(matnrList.map(matnr => sql`${matnr}`), sql`, `)}) + AND ${MATERIAL_MASTER_PART_MATL_DESC.SPRAS} = 'E' + AND ${MATERIAL_MASTER_PART_MATL_DESC.MAKTX} IS NOT NULL + AND ${MATERIAL_MASTER_PART_MATL_DESC.MAKTX} != '' + `); - // 2단계: MAKTX가 있는 레코드만 필터링 - const validData = materialGroupData.filter(item => - item.MAKTX && item.MAKTX.trim() !== '' - ); + console.log(`✅ 유효한 자재그룹 데이터: ${materialGroupData.length}개`); - console.log(`✅ 유효한 자재그룹 데이터: ${validData.length}개`); + const validData = materialGroupData; if (validData.length === 0) { return { totalProcessed: 0, newRecords: 0, updatedRecords: 0, - skippedRecords: materialGroupData.length + skippedRecords: matklWithMatnr.rowCount || 0 }; } @@ -80,9 +94,13 @@ export async function syncMaterialGroupMaster(): Promise<SyncResult> { const existingMatkls = new Set(existingRecords.map(r => r.MATKL)); - // 4단계: 신규/업데이트 데이터 분류 - const newRecords = validData.filter(item => !existingMatkls.has(item.MATKL)); - const updateRecords = validData.filter(item => existingMatkls.has(item.MATKL)); + // 4단계: 신규/업데이트 데이터 분류 (null 값 제외하고 타입 안전하게) + const filteredData = validData.filter((item): item is { MATKL: string; MAKTX: string } => + !!item.MATKL && !!item.MAKTX + ); + + const newRecords = filteredData.filter(item => !existingMatkls.has(item.MATKL)); + const updateRecords = filteredData.filter(item => existingMatkls.has(item.MATKL)); let insertedCount = 0; let updatedCount = 0; @@ -91,12 +109,7 @@ export async function syncMaterialGroupMaster(): Promise<SyncResult> { if (newRecords.length > 0) { await tx .insert(MATERIAL_GROUP_MASTER) - .values( - newRecords.map(item => ({ - MATKL: item.MATKL, - MAKTX: item.MAKTX - })) - ); + .values(newRecords); insertedCount = newRecords.length; console.log(`➕ 신규 삽입: ${insertedCount}개`); } @@ -105,10 +118,10 @@ export async function syncMaterialGroupMaster(): Promise<SyncResult> { if (updateRecords.length > 0) { // PostgreSQL의 UPDATE ... FROM 구문 사용 await tx.execute(sql` - UPDATE ${MATERIAL_GROUP_MASTER} + UPDATE mdg."MATERIAL_GROUP_MASTER" SET - ${MATERIAL_GROUP_MASTER.MAKTX} = temp_data.maktx, - ${MATERIAL_GROUP_MASTER.updatedAt} = NOW() + "MAKTX" = temp_data.maktx, + "updated_at" = NOW() FROM ( VALUES ${sql.join( updateRecords.map(item => @@ -117,7 +130,7 @@ export async function syncMaterialGroupMaster(): Promise<SyncResult> { sql`, ` )} ) AS temp_data(matkl, maktx) - WHERE ${MATERIAL_GROUP_MASTER.MATKL} = temp_data.matkl + WHERE "MATKL" = temp_data.matkl `); updatedCount = updateRecords.length; console.log(`🔄 업데이트: ${updatedCount}개`); @@ -127,7 +140,7 @@ export async function syncMaterialGroupMaster(): Promise<SyncResult> { totalProcessed: validData.length, newRecords: insertedCount, updatedRecords: updatedCount, - skippedRecords: materialGroupData.length - validData.length + skippedRecords: (matklWithMatnr.rowCount || 0) - validData.length }; }); diff --git a/lib/material-groups/table/material-group-table-columns.tsx b/lib/material-groups/table/material-group-table-columns.tsx index 3d304325..08e730e3 100644 --- a/lib/material-groups/table/material-group-table-columns.tsx +++ b/lib/material-groups/table/material-group-table-columns.tsx @@ -38,7 +38,7 @@ export function getColumns(): ColumnDef<MaterialGroup>[] { { accessorKey: "materialGroupDesc", header: ({ column }) => ( - <DataTableColumnHeaderSimple column={column} title="자재그룹 설명" /> + <DataTableColumnHeaderSimple column={column} title="자재그룹명" /> ), cell: ({ row }) => { const value = row.getValue("materialGroupDesc") as string | null |
