diff options
Diffstat (limited to 'app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_MODEL_MASTER/route.ts')
| -rw-r--r-- | app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_MODEL_MASTER/route.ts | 121 |
1 files changed, 52 insertions, 69 deletions
diff --git a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_MODEL_MASTER/route.ts b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_MODEL_MASTER/route.ts index cb8de491..4e7cdf35 100644 --- a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_MODEL_MASTER/route.ts +++ b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_MODEL_MASTER/route.ts @@ -122,58 +122,68 @@ export async function POST(request: NextRequest) { } // XML 데이터를 DB 삽입 가능한 형태로 변환 +/** + * MODEL 마스터 데이터 변환 함수 + * + * 데이터 처리 아키텍처: + * 1. 최상위 테이블 (MODEL_MASTER_MATL) + * - MATNR이 unique 필드로 충돌 시 upsert 처리 + * + * 2. 하위 테이블들 (DESC, PLNT, UNIT, CLASSASGN, CHARASGN) + * - FK(MATNR)로 연결 + * - 별도 필수 필드 없음 (스키마에서 notNull() 제거 예정) + * - 전체 데이터셋 기반 삭제 후 재삽입 처리 + * + * XML 패턴: + * - MODEL 인터페이스는 XML에 MATNR이 이미 포함된 패턴 + * - 하위 테이블에도 MATNR 필드가 있어서 XML 값 우선 사용됨 + * + * @param matlData XML에서 파싱된 MODEL 데이터 + * @returns 처리된 MODEL 데이터 구조 + */ function transformMatlData(matlData: MatlXML[]): ProcessedMaterialData[] { if (!matlData || !Array.isArray(matlData)) { return []; } return matlData.map(matl => { - // 메인 Material 데이터 변환 (자동) + const matnrKey = matl.MATNR || ''; + const fkData = { MATNR: matnrKey }; + + // 1단계: MATL (루트 - unique 필드: MATNR) const material = convertXMLToDBData<MatlData>( - matl as Record<string, string | undefined>, - ['MATNR'] + matl as Record<string, string | undefined>, + fkData ); - // 필수 필드 보정 (MATNR이 빈 문자열이면 안됨) - if (!material.MATNR) { - material.MATNR = ''; - } - - // FK 데이터 준비 - const fkData = { MATNR: matl.MATNR || '' }; - - // Description 데이터 변환 (자동) + // 2단계: 하위 테이블들 (FK: MATNR) const descriptions = processNestedArray( matl.DESC, - (desc) => convertXMLToDBData<MatlDescData>(desc, ['MATNR'], fkData), + (desc) => convertXMLToDBData<MatlDescData>(desc as Record<string, string | undefined>, fkData), fkData ); - // Plant 데이터 변환 (자동) const plants = processNestedArray( matl.PLNT, - (plnt) => convertXMLToDBData<MatlPlntData>(plnt, ['MATNR'], fkData), + (plnt) => convertXMLToDBData<MatlPlntData>(plnt as Record<string, string | undefined>, fkData), fkData ); - // Unit 데이터 변환 (자동) const units = processNestedArray( matl.UNIT, - (unit) => convertXMLToDBData<MatlUnitData>(unit, ['MATNR'], fkData), + (unit) => convertXMLToDBData<MatlUnitData>(unit as Record<string, string | undefined>, fkData), fkData ); - // Class Assignment 데이터 변환 (자동) const classAssignments = processNestedArray( matl.CLASSASGN, - (cls) => convertXMLToDBData<MatlClassAsgnData>(cls, ['MATNR'], fkData), + (cls) => convertXMLToDBData<MatlClassAsgnData>(cls as Record<string, string | undefined>, fkData), fkData ); - // Characteristic Assignment 데이터 변환 (자동) const characteristicAssignments = processNestedArray( matl.CHARASGN, - (char) => convertXMLToDBData<MatlCharAsgnData>(char, ['MATNR'], fkData), + (char) => convertXMLToDBData<MatlCharAsgnData>(char as Record<string, string | undefined>, fkData), fkData ); @@ -189,8 +199,19 @@ function transformMatlData(matlData: MatlXML[]): ProcessedMaterialData[] { } // 데이터베이스 저장 함수 +/** + * 처리된 MODEL 데이터를 데이터베이스에 저장 + * + * 저장 전략: + * 1. 최상위 테이블: MATNR 기준 upsert (충돌 시 업데이트) + * 2. 하위 테이블들: FK(MATNR) 기준 전체 삭제 후 재삽입 + * - 송신 XML이 전체 데이터셋을 포함하므로 부분 업데이트 불필요 + * - 데이터 일관성과 단순성 확보 + * + * @param processedMaterials 변환된 MODEL 데이터 배열 + */ async function saveToDatabase(processedMaterials: ProcessedMaterialData[]) { - console.log(`데이터베이스 저장 함수가 호출됨. ${processedMaterials.length}개의 자재 데이터 수신.`); + console.log(`데이터베이스 저장 시작: ${processedMaterials.length}개 모델 데이터`); try { await db.transaction(async (tx) => { @@ -202,7 +223,7 @@ async function saveToDatabase(processedMaterials: ProcessedMaterialData[]) { continue; } - // 1. MATL 테이블 Upsert (최상위 테이블) + // 1. MATL 테이블 Upsert (최상위 테이블 - unique 필드: MATNR) await tx.insert(MODEL_MASTER_MATL) .values(material) .onConflictDoUpdate({ @@ -213,57 +234,19 @@ async function saveToDatabase(processedMaterials: ProcessedMaterialData[]) { } }); - // 2. 하위 테이블 데이터 처리 - FK 기준으로 전체 삭제 후 재삽입 + // 2. 하위 테이블들 처리 - FK(MATNR) 기준 전체 삭제 후 재삽입 + // 전체 데이터셋 기반 처리로 데이터 일관성 확보 await Promise.all([ - // DESC 테이블 처리 - replaceSubTableData( - tx, - MODEL_MASTER_MATL_DESC, - descriptions, - 'MATNR', - material.MATNR - ), - - // PLNT 테이블 처리 - replaceSubTableData( - tx, - MODEL_MASTER_MATL_PLNT, - plants, - 'MATNR', - material.MATNR - ), - - // UNIT 테이블 처리 - replaceSubTableData( - tx, - MODEL_MASTER_MATL_UNIT, - units, - 'MATNR', - material.MATNR - ), - - // CLASSASGN 테이블 처리 - replaceSubTableData( - tx, - MODEL_MASTER_MATL_CLASSASGN, - classAssignments, - 'MATNR', - material.MATNR - ), - - // CHARASGN 테이블 처리 - replaceSubTableData( - tx, - MODEL_MASTER_MATL_CHARASGN, - characteristicAssignments, - 'MATNR', - material.MATNR - ) + replaceSubTableData(tx, MODEL_MASTER_MATL_DESC, descriptions, 'MATNR', material.MATNR), + replaceSubTableData(tx, MODEL_MASTER_MATL_PLNT, plants, 'MATNR', material.MATNR), + replaceSubTableData(tx, MODEL_MASTER_MATL_UNIT, units, 'MATNR', material.MATNR), + replaceSubTableData(tx, MODEL_MASTER_MATL_CLASSASGN, classAssignments, 'MATNR', material.MATNR), + replaceSubTableData(tx, MODEL_MASTER_MATL_CHARASGN, characteristicAssignments, 'MATNR', material.MATNR) ]); } }); - console.log(`${processedMaterials.length}개의 자재 데이터 처리 완료.`); + console.log(`데이터베이스 저장 완료: ${processedMaterials.length}개 모델`); return true; } catch (error) { console.error('데이터베이스 저장 중 오류 발생:', error); |
