diff options
Diffstat (limited to 'app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts')
| -rw-r--r-- | app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts new file mode 100644 index 00000000..c3f214e6 --- /dev/null +++ b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts @@ -0,0 +1,435 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { NextRequest } from "next/server"; +import db from "@/db/db"; +import { + ORGANIZATION_MASTER_HRHMTB_CCTR, + ORGANIZATION_MASTER_HRHMTB_CCTR_TEXT, + ORGANIZATION_MASTER_HRHMTB_PCTR, + ORGANIZATION_MASTER_HRHMTB_ZBUKRS, + ORGANIZATION_MASTER_HRHMTB_ZEKGRP, + ORGANIZATION_MASTER_HRHMTB_ZEKORG, + ORGANIZATION_MASTER_HRHMTB_ZGSBER, + ORGANIZATION_MASTER_HRHMTB_ZGSBER_TEXT, + ORGANIZATION_MASTER_HRHMTB_ZLGORT, + ORGANIZATION_MASTER_HRHMTB_ZSPART, + ORGANIZATION_MASTER_HRHMTB_ZVKBUR, + ORGANIZATION_MASTER_HRHMTB_ZVKGRP, + ORGANIZATION_MASTER_HRHMTB_ZVKORG, + ORGANIZATION_MASTER_HRHMTB_ZVSTEL, + ORGANIZATION_MASTER_HRHMTB_ZVTWEG, + ORGANIZATION_MASTER_HRHMTB_ZWERKS +} from "@/db/schema/MDG/mdg"; +import { + ToXMLFields, + serveWsdl, + createXMLParser, + extractRequestData, + convertXMLToDBData, + processNestedArray, + createErrorResponse, + createSuccessResponse, + replaceSubTableData, + withSoapLogging +} from "../utils"; + +// 스키마에서 직접 타입 추론 +type CctrData = typeof ORGANIZATION_MASTER_HRHMTB_CCTR.$inferInsert; +type CctrTextData = typeof ORGANIZATION_MASTER_HRHMTB_CCTR_TEXT.$inferInsert; +type PctrData = typeof ORGANIZATION_MASTER_HRHMTB_PCTR.$inferInsert; +type ZbukrsData = typeof ORGANIZATION_MASTER_HRHMTB_ZBUKRS.$inferInsert; +type ZekgrpData = typeof ORGANIZATION_MASTER_HRHMTB_ZEKGRP.$inferInsert; +type ZekorgData = typeof ORGANIZATION_MASTER_HRHMTB_ZEKORG.$inferInsert; +type ZgsberData = typeof ORGANIZATION_MASTER_HRHMTB_ZGSBER.$inferInsert; +type ZgsberTextData = typeof ORGANIZATION_MASTER_HRHMTB_ZGSBER_TEXT.$inferInsert; +type ZlgortData = typeof ORGANIZATION_MASTER_HRHMTB_ZLGORT.$inferInsert; +type ZspartData = typeof ORGANIZATION_MASTER_HRHMTB_ZSPART.$inferInsert; +type ZvkburData = typeof ORGANIZATION_MASTER_HRHMTB_ZVKBUR.$inferInsert; +type ZvkgrpData = typeof ORGANIZATION_MASTER_HRHMTB_ZVKGRP.$inferInsert; +type ZvkorgData = typeof ORGANIZATION_MASTER_HRHMTB_ZVKORG.$inferInsert; +type ZvstelData = typeof ORGANIZATION_MASTER_HRHMTB_ZVSTEL.$inferInsert; +type ZvtwegData = typeof ORGANIZATION_MASTER_HRHMTB_ZVTWEG.$inferInsert; +type ZwerksData = typeof ORGANIZATION_MASTER_HRHMTB_ZWERKS.$inferInsert; + +// XML에서 받는 데이터 구조 +type CctrXML = ToXMLFields<Omit<CctrData, 'id' | 'createdAt' | 'updatedAt'>> & { + TEXT?: TextXML[]; +}; + +type TextXML = ToXMLFields<Omit<CctrTextData, 'id' | 'createdAt' | 'updatedAt'>>; + +type PctrXML = ToXMLFields<Omit<PctrData, 'id' | 'createdAt' | 'updatedAt'>> & { + TEXT?: TextXML[]; +}; + +type ZbukrsXML = ToXMLFields<Omit<ZbukrsData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZekgrpXML = ToXMLFields<Omit<ZekgrpData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZekorgXML = ToXMLFields<Omit<ZekorgData, 'id' | 'createdAt' | 'updatedAt'>>; + +type ZgsberXML = ToXMLFields<Omit<ZgsberData, 'id' | 'createdAt' | 'updatedAt'>> & { + TEXT?: ZgsberTextXML[]; +}; + +type ZgsberTextXML = ToXMLFields<Omit<ZgsberTextData, 'id' | 'createdAt' | 'updatedAt'>>; + +type ZlgortXML = ToXMLFields<Omit<ZlgortData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZspartXML = ToXMLFields<Omit<ZspartData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZvkburXML = ToXMLFields<Omit<ZvkburData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZvkgrpXML = ToXMLFields<Omit<ZvkgrpData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZvkorgXML = ToXMLFields<Omit<ZvkorgData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZvstelXML = ToXMLFields<Omit<ZvstelData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZvtwegXML = ToXMLFields<Omit<ZvtwegData, 'id' | 'createdAt' | 'updatedAt'>>; +type ZwerksXML = ToXMLFields<Omit<ZwerksData, 'id' | 'createdAt' | 'updatedAt'>>; + +// 처리된 데이터 구조 +interface ProcessedOrganizationData { + cctrItems: Array<{ cctr: CctrData; texts: CctrTextData[] }>; + pctrItems: Array<{ pctr: PctrData; texts: CctrTextData[] }>; + zbukrsItems: ZbukrsData[]; + zekgrpItems: ZekgrpData[]; + zekorgItems: ZekorgData[]; + zgsberItems: Array<{ zgsber: ZgsberData; texts: ZgsberTextData[] }>; + zlgortItems: ZlgortData[]; + zspartItems: ZspartData[]; + zvkburItems: ZvkburData[]; + zvkgrpItems: ZvkgrpData[]; + zvkorgItems: ZvkorgData[]; + zvstelItems: ZvstelData[]; + zvtwegItems: ZvtwegData[]; + zwerksItems: ZwerksData[]; +} + +export async function GET(request: NextRequest) { + const url = new URL(request.url); + if (url.searchParams.has('wsdl')) { + return serveWsdl('IF_MDZ_EVCP_ORGANIZATION_MASTER.wsdl'); + } + + return new Response('Method Not Allowed', { status: 405 }); +} + +export async function POST(request: NextRequest) { + const url = new URL(request.url); + if (url.searchParams.has('wsdl')) { + return serveWsdl('IF_MDZ_EVCP_ORGANIZATION_MASTER.wsdl'); + } + + const body = await request.text(); + + return withSoapLogging( + 'INBOUND', + 'S-ERP', + 'IF_MDZ_EVCP_ORGANIZATION_MASTER', + body, + async () => { + console.log('🚀 ORGANIZATION_MASTER 수신 시작, 데이터 길이:', body.length); + + const parser = createXMLParser([ + 'HRHMTB_CCTR', 'HRHMTB_PCTR', 'HRHMTB_ZBUKRS', 'HRHMTB_ZEKGRP', + 'HRHMTB_ZEKORG', 'HRHMTB_ZGSBER', 'HRHMTB_ZLGORT', 'HRHMTB_ZSPART', + 'HRHMTB_ZVKBUR', 'HRHMTB_ZVKGRP', 'HRHMTB_ZVKORG', 'HRHMTB_ZVSTEL', + 'HRHMTB_ZVTWEG', 'HRHMTB_ZWERKS', 'TEXT' + ]); + + const parsedData = parser.parse(body); + console.log('XML root keys:', Object.keys(parsedData)); + + const requestData = extractRequestData(parsedData, 'IF_MDZ_EVCP_ORGANIZATION_MASTERReq'); + + if (!requestData) { + console.error('Could not find valid request data in the received payload'); + console.error('Received XML structure:', JSON.stringify(parsedData, null, 2)); + throw new Error('Missing request data - could not find IF_MDZ_EVCP_ORGANIZATION_MASTERReq data'); + } + + console.log('Validating request data structure:', + Object.keys(requestData).map(key => `${key}: ${requestData[key] ? 'found' : 'not found'}`).join(', ') + ); + + // XML 데이터를 DB 삽입 가능한 형태로 변환 + const processedOrganizations = transformOrganizationData(requestData); + + // 데이터베이스 저장 + await saveToDatabase(processedOrganizations); + + console.log('🎉 처리 완료: 조직 마스터 데이터'); + + return createSuccessResponse('http://60.101.108.100/api/IF_MDZ_EVCP_ORGANIZATION_MASTER/'); + } + ).catch(error => { + return createErrorResponse(error); + }); +} + +// XML 데이터를 DB 삽입 가능한 형태로 변환 +function transformOrganizationData(requestData: any): ProcessedOrganizationData { + const result: ProcessedOrganizationData = { + cctrItems: [], + pctrItems: [], + zbukrsItems: [], + zekgrpItems: [], + zekorgItems: [], + zgsberItems: [], + zlgortItems: [], + zspartItems: [], + zvkburItems: [], + zvkgrpItems: [], + zvkorgItems: [], + zvstelItems: [], + zvtwegItems: [], + zwerksItems: [] + }; + + // HRHMTB_CCTR 처리 + if (requestData.items1 && Array.isArray(requestData.items1)) { + result.cctrItems = requestData.items1.map((item: CctrXML) => { + const cctr = convertXMLToDBData<CctrData>( + item as Record<string, string | undefined>, + ['CCTR', 'KOKRS', 'DATBI'] + ); + + const fkData = { CCTR: item.CCTR || '' }; + const texts = processNestedArray( + item.TEXT, + (text) => convertXMLToDBData<CctrTextData>(text, [], fkData), + fkData + ); + + return { cctr, texts }; + }); + } + + // HRHMTB_PCTR 처리 + if (requestData.items2 && Array.isArray(requestData.items2)) { + result.pctrItems = requestData.items2.map((item: PctrXML) => { + const pctr = convertXMLToDBData<PctrData>( + item as Record<string, string | undefined>, + ['PCTR', 'KOKRS', 'DATBI'] + ); + + const fkData = { CCTR: item.PCTR || '' }; // TEXT 테이블은 CCTR 필드를 사용 + const texts = processNestedArray( + item.TEXT, + (text) => convertXMLToDBData<CctrTextData>(text, [], fkData), + fkData + ); + + return { pctr, texts }; + }); + } + + // HRHMTB_ZBUKRS 처리 + if (requestData.items3 && Array.isArray(requestData.items3)) { + result.zbukrsItems = requestData.items3.map((item: ZbukrsXML) => + convertXMLToDBData<ZbukrsData>( + item as Record<string, string | undefined>, + ['ZBUKRS'] + ) + ); + } + + // HRHMTB_ZEKGRP 처리 + if (requestData.items4 && Array.isArray(requestData.items4)) { + result.zekgrpItems = requestData.items4.map((item: ZekgrpXML) => + convertXMLToDBData<ZekgrpData>( + item as Record<string, string | undefined>, + ['ZEKGRP'] + ) + ); + } + + // HRHMTB_ZEKORG 처리 + if (requestData.items5 && Array.isArray(requestData.items5)) { + result.zekorgItems = requestData.items5.map((item: ZekorgXML) => + convertXMLToDBData<ZekorgData>( + item as Record<string, string | undefined>, + ['ZEKORG'] + ) + ); + } + + // HRHMTB_ZGSBER 처리 + if (requestData.items6 && Array.isArray(requestData.items6)) { + result.zgsberItems = requestData.items6.map((item: ZgsberXML) => { + const zgsber = convertXMLToDBData<ZgsberData>( + item as Record<string, string | undefined>, + ['ZGSBER'] + ); + + const fkData = { ZGSBER: item.ZGSBER || '' }; + const texts = processNestedArray( + item.TEXT, + (text) => convertXMLToDBData<ZgsberTextData>(text, ['LANGU'], fkData), + fkData + ); + + return { zgsber, texts }; + }); + } + + // HRHMTB_ZLGORT 처리 + if (requestData.items7 && Array.isArray(requestData.items7)) { + result.zlgortItems = requestData.items7.map((item: ZlgortXML) => + convertXMLToDBData<ZlgortData>( + item as Record<string, string | undefined>, + ['ZLGORT', 'ZWERKS'] + ) + ); + } + + // HRHMTB_ZSPART 처리 + if (requestData.items8 && Array.isArray(requestData.items8)) { + result.zspartItems = requestData.items8.map((item: ZspartXML) => + convertXMLToDBData<ZspartData>( + item as Record<string, string | undefined>, + ['ZSPART'] + ) + ); + } + + // HRHMTB_ZVKBUR 처리 + if (requestData.items9 && Array.isArray(requestData.items9)) { + result.zvkburItems = requestData.items9.map((item: ZvkburXML) => + convertXMLToDBData<ZvkburData>( + item as Record<string, string | undefined>, + ['ZVKBUR'] + ) + ); + } + + // HRHMTB_ZVKGRP 처리 + if (requestData.items10 && Array.isArray(requestData.items10)) { + result.zvkgrpItems = requestData.items10.map((item: ZvkgrpXML) => + convertXMLToDBData<ZvkgrpData>( + item as Record<string, string | undefined>, + ['ZVKGRP'] + ) + ); + } + + // HRHMTB_ZVKORG 처리 + if (requestData.items11 && Array.isArray(requestData.items11)) { + result.zvkorgItems = requestData.items11.map((item: ZvkorgXML) => + convertXMLToDBData<ZvkorgData>( + item as Record<string, string | undefined>, + ['ZVKORG'] + ) + ); + } + + // HRHMTB_ZVSTEL 처리 + if (requestData.items12 && Array.isArray(requestData.items12)) { + result.zvstelItems = requestData.items12.map((item: ZvstelXML) => + convertXMLToDBData<ZvstelData>( + item as Record<string, string | undefined>, + ['ZVSTEL'] + ) + ); + } + + // HRHMTB_ZVTWEG 처리 + if (requestData.items13 && Array.isArray(requestData.items13)) { + result.zvtwegItems = requestData.items13.map((item: ZvtwegXML) => + convertXMLToDBData<ZvtwegData>( + item as Record<string, string | undefined>, + ['ZVTWEG'] + ) + ); + } + + // HRHMTB_ZWERKS 처리 + if (requestData.items14 && Array.isArray(requestData.items14)) { + result.zwerksItems = requestData.items14.map((item: ZwerksXML) => + convertXMLToDBData<ZwerksData>( + item as Record<string, string | undefined>, + ['ZWERKS'] + ) + ); + } + + return result; +} + +// 데이터베이스 저장 함수 +async function saveToDatabase(processedOrganizations: ProcessedOrganizationData) { + console.log('데이터베이스 저장 함수가 호출됨. 조직 마스터 데이터 수신.'); + + try { + await db.transaction(async (tx) => { + // CCTR 테이블 처리 + for (const { cctr, texts } of processedOrganizations.cctrItems) { + if (!cctr.CCTR) continue; + + await tx.insert(ORGANIZATION_MASTER_HRHMTB_CCTR) + .values(cctr) + .onConflictDoUpdate({ + target: ORGANIZATION_MASTER_HRHMTB_CCTR.CCTR, + set: { ...cctr, updatedAt: new Date() } + }); + + await replaceSubTableData(tx, ORGANIZATION_MASTER_HRHMTB_CCTR_TEXT, texts, 'CCTR', cctr.CCTR); + } + + // PCTR 테이블 처리 + for (const { pctr, texts } of processedOrganizations.pctrItems) { + if (!pctr.PCTR) continue; + + await tx.insert(ORGANIZATION_MASTER_HRHMTB_PCTR) + .values(pctr) + .onConflictDoUpdate({ + target: ORGANIZATION_MASTER_HRHMTB_PCTR.PCTR, + set: { ...pctr, updatedAt: new Date() } + }); + + // PCTR의 TEXT는 CCTR_TEXT 테이블을 사용하므로 처리하지 않음 + } + + // 나머지 단일 테이블들 처리 + const tableProcessors = [ + { items: processedOrganizations.zbukrsItems, table: ORGANIZATION_MASTER_HRHMTB_ZBUKRS, key: 'ZBUKRS' }, + { items: processedOrganizations.zekgrpItems, table: ORGANIZATION_MASTER_HRHMTB_ZEKGRP, key: 'ZEKGRP' }, + { items: processedOrganizations.zekorgItems, table: ORGANIZATION_MASTER_HRHMTB_ZEKORG, key: 'ZEKORG' }, + { items: processedOrganizations.zlgortItems, table: ORGANIZATION_MASTER_HRHMTB_ZLGORT, key: 'ZLGORT' }, + { items: processedOrganizations.zspartItems, table: ORGANIZATION_MASTER_HRHMTB_ZSPART, key: 'ZSPART' }, + { items: processedOrganizations.zvkburItems, table: ORGANIZATION_MASTER_HRHMTB_ZVKBUR, key: 'ZVKBUR' }, + { items: processedOrganizations.zvkgrpItems, table: ORGANIZATION_MASTER_HRHMTB_ZVKGRP, key: 'ZVKGRP' }, + { items: processedOrganizations.zvkorgItems, table: ORGANIZATION_MASTER_HRHMTB_ZVKORG, key: 'ZVKORG' }, + { items: processedOrganizations.zvstelItems, table: ORGANIZATION_MASTER_HRHMTB_ZVSTEL, key: 'ZVSTEL' }, + { items: processedOrganizations.zvtwegItems, table: ORGANIZATION_MASTER_HRHMTB_ZVTWEG, key: 'ZVTWEG' }, + { items: processedOrganizations.zwerksItems, table: ORGANIZATION_MASTER_HRHMTB_ZWERKS, key: 'ZWERKS' } + ]; + + for (const { items, table, key } of tableProcessors) { + for (const item of items) { + if (!(item as any)[key]) continue; + + await tx.insert(table) + .values(item) + .onConflictDoUpdate({ + target: (table as any)[key], + set: { ...item, updatedAt: new Date() } + }); + } + } + + // ZGSBER 테이블 처리 (TEXT 포함) + for (const { zgsber, texts } of processedOrganizations.zgsberItems) { + if (!zgsber.ZGSBER) continue; + + await tx.insert(ORGANIZATION_MASTER_HRHMTB_ZGSBER) + .values(zgsber) + .onConflictDoUpdate({ + target: ORGANIZATION_MASTER_HRHMTB_ZGSBER.ZGSBER, + set: { ...zgsber, updatedAt: new Date() } + }); + + await replaceSubTableData(tx, ORGANIZATION_MASTER_HRHMTB_ZGSBER_TEXT, texts, 'ZGSBER', zgsber.ZGSBER); + } + }); + + console.log('조직 마스터 데이터 처리 완료.'); + return true; + } catch (error) { + console.error('데이터베이스 저장 중 오류 발생:', error); + throw error; + } +} |
