diff options
Diffstat (limited to 'lib/soap/ecc/mapper/bidding-and-pr-mapper.ts')
| -rw-r--r-- | lib/soap/ecc/mapper/bidding-and-pr-mapper.ts | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts b/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts index af4cecdc..4ab9a745 100644 --- a/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts +++ b/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts @@ -21,10 +21,11 @@ import { PR_INFORMATION_T_BID_HEADER, PR_INFORMATION_T_BID_ITEM, } from '@/db/schema/ECC/ecc'; -import { inArray, max, sql } from 'drizzle-orm'; +import { inArray, max, sql, eq } from 'drizzle-orm'; import { findUserInfoByEKGRP, findProjectInfoByPSPID, + findProjectIdByPSPID, findMaterialNameByMATNR, parseSAPDateTime, parseSAPDateToString, @@ -171,17 +172,15 @@ export async function mapECCBiddingHeaderToBidding( // 담당자 찾기 const inChargeUserInfo = await findUserInfoByEKGRP(eccHeader.EKGRP || null); - // 첫번째 PR Item 기반으로 projectId, projectName, itemName 설정 - let projectId: number | null = null; + // 첫번째 PR Item 기반으로 projectName, itemName 설정 let projectName: string | null = null; let itemName: string | null = null; let prNumber: string | null = null; if (firstItem) { - // projectId, projectName: 첫번째 PR Item의 PSPID와 projects.code 매칭 + // projectName: 첫번째 PR Item의 PSPID와 projects.code 매칭 const projectInfo = await findProjectInfoByPSPID(firstItem.PSPID || null); if (projectInfo) { - projectId = projectInfo.id; projectName = projectInfo.name; } @@ -196,12 +195,10 @@ export async function mapECCBiddingHeaderToBidding( const mappedData: BiddingData = { biddingNumber, // 생성된 Bidding 코드 revision: 0, // 기본 리비전 0 (I/F 해서 가져온 건 보낸 적 없으므로 0 고정) - projectId, // 첫번째 PR Item의 PSPID로 찾은 프로젝트 ID projectName, // 첫번째 PR Item의 PSPID로 찾은 프로젝트 이름 itemName, // 첫번째 PR Item의 MATNR로 조회한 자재명 title: `${firstItem?.PSPID || ''}${itemName || ''}입찰`, // PSPID+자재그룹명+계약구분+입찰, 계약구분은 없으니까 제외했음 description: null, - content: null, // 계약 정보 - ECC에서 제공되지 않으므로 기본값 설정 contractType: 'general', // 일반계약 기본값 (notNull) @@ -235,10 +232,9 @@ export async function mapECCBiddingHeaderToBidding( status: 'bidding_generated', // 입찰생성 상태 isPublic: false, - // 담당자 정보 - EKGRP 기반으로 설정 - managerName: inChargeUserInfo?.userName || null, - managerEmail: inChargeUserInfo?.userEmail || null, - managerPhone: inChargeUserInfo?.userPhone || null, + // 담당자 정보 - EKGRP 기반으로 설정 (입찰담당자로 매핑) + bidPicId: inChargeUserInfo?.userId || null, + bidPicName: inChargeUserInfo?.userName || null, // 메타 정보 remarks: `ECC ANFNR: ${eccHeader.ANFNR}`, @@ -256,10 +252,10 @@ export async function mapECCBiddingHeaderToBidding( /** * ECC Bidding 아이템 데이터를 prItemsForBidding 테이블로 매핑 */ -export function mapECCBiddingItemToPrItemForBidding( +export async function mapECCBiddingItemToPrItemForBidding( eccItem: ECCBidItem, biddingId: number -): PrItemForBiddingData { +): Promise<PrItemForBiddingData> { debugLog('ECC Bidding 아이템 매핑 시작', { anfnr: eccItem.ANFNR, anfps: eccItem.ANFPS, @@ -268,12 +264,25 @@ export function mapECCBiddingItemToPrItemForBidding( // 날짜 파싱 (YYYY-MM-DD 형식의 문자열로 변환) const requestedDeliveryDate = parseSAPDateToString(eccItem.LFDAT || null); + // PSPID(Project Code)로 프로젝트 ID 조회 + const projectId = await findProjectIdByPSPID(eccItem.PSPID || null); + const mappedData: PrItemForBiddingData = { biddingId, // 부모 Bidding ID itemNumber: eccItem.ANFPS || null, // 아이템 번호 + projectId, // PSSID로 조회한 프로젝트 ID projectInfo: eccItem.PSPID || null, // 프로젝트 정보 (PSPID) itemInfo: eccItem.TXZ01 || null, // 품목정보 (자재 설명) shi: null, // ECC에서 제공되지 않음 + + // 자재 그룹 정보 + materialGroupNumber: eccItem.MATKL || null, // 자재그룹번호 (Material Group Code) + materialGroupInfo: null, // ECC에서 제공되지 않음 + + // 자재 정보 + materialNumber: eccItem.MATNR || null, // 자재번호 (Material Number) + materialInfo: eccItem.TXZ01 || null, // 자재정보 (Material Description) + requestedDeliveryDate, // 납품요청일 annualUnitPrice: null, // ECC에서 제공되지 않음 currency: eccItem.WAERS1 || null, // 기본 통화 @@ -281,7 +290,19 @@ export function mapECCBiddingItemToPrItemForBidding( quantityUnit: eccItem.MEINS || null, // 수량단위 totalWeight: eccItem.BRGEW || null, // 총중량 weightUnit: eccItem.GEWEI || null, // 중량단위 - materialDescription: eccItem.TXZ01 || null, // 자재내역상세 + + // WBS 정보 + wbsCode: eccItem.POSID || null, // WBS No + wbsName: null, // ECC에서 제공되지 않음 + + // Cost Center 정보 + costCenterCode: eccItem.KOSTL || null, // Cost Center + costCenterName: null, // ECC에서 제공되지 않음 + + // GL Account 정보 + glAccountCode: eccItem.SAKTO || null, // G/L Account Number + glAccountName: null, // ECC에서 제공되지 않음 + prNumber: eccItem.BANFN || null, // PR번호 hasSpecDocument: false, // 기본값 false }; @@ -289,6 +310,7 @@ export function mapECCBiddingItemToPrItemForBidding( debugSuccess('ECC Bidding 아이템 매핑 완료', { itemNumber: eccItem.ANFPS, prNumber: eccItem.BANFN, + projectId, }); return mappedData; } @@ -361,7 +383,7 @@ export async function mapAndSaveECCBiddingData( // 4) 모든 새로 삽입된 레코드의 ID 매핑은 이미 완료됨 - // 5) 모든 아이템을 한 번에 생성할 데이터로 변환 + // 5) 모든 아이템을 한 번에 생성할 데이터로 변환 (병렬 처리) const allItemsToInsert: PrItemForBiddingData[] = []; for (const group of biddingGroups) { const biddingNumber = group.biddingNumber; @@ -372,10 +394,13 @@ export async function mapAndSaveECCBiddingData( throw new Error(`Bidding ID를 찾을 수 없습니다: ${biddingNumber}`); } - for (const eccItem of group.relatedItems) { - const itemData = mapECCBiddingItemToPrItemForBidding(eccItem, biddingId); - allItemsToInsert.push(itemData); - } + // 각 아이템을 병렬로 매핑 (async 함수로 변경되었으므로) + const itemsData = await Promise.all( + group.relatedItems.map(eccItem => + mapECCBiddingItemToPrItemForBidding(eccItem, biddingId) + ) + ); + allItemsToInsert.push(...itemsData); } // 6) 아이템 일괄 삽입 (chunk 처리로 파라미터 제한 회피) |
