diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-17 15:47:07 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-17 15:47:07 +0900 |
| commit | a5be73b70e7d8e6be1724252e6923c664c3771f4 (patch) | |
| tree | cc8942f867a8bdeb9d55a000d70f9ee44867b5a8 | |
| parent | b9f575f6110faabc7b062f84bf491d69d88a10a5 (diff) | |
(김준회) 입찰 매핑 안된 필드들 처리
| -rw-r--r-- | lib/soap/ecc/mapper/bidding-and-pr-mapper.ts | 63 | ||||
| -rw-r--r-- | lib/soap/ecc/mapper/common-mapper-utils.ts | 34 |
2 files changed, 78 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 처리로 파라미터 제한 회피) diff --git a/lib/soap/ecc/mapper/common-mapper-utils.ts b/lib/soap/ecc/mapper/common-mapper-utils.ts index cf5e0fdb..2199490a 100644 --- a/lib/soap/ecc/mapper/common-mapper-utils.ts +++ b/lib/soap/ecc/mapper/common-mapper-utils.ts @@ -169,6 +169,40 @@ export async function findProjectInfoByPSPID(PSPID: string | null): Promise<{ } /** + * 프로젝트 정보 조회 함수 (PSPID 기반으로 ID만 반환) + * PSPID(Project Code)와 projects.code 매칭하여 프로젝트 ID 반환 + */ +export async function findProjectIdByPSPID(PSPID: string | null): Promise<number | null> { + try { + debugLog('프로젝트 ID 찾기 시작 (PSPID 기준)', { PSPID }); + + if (!PSPID) { + debugError('PSPID가 null 또는 undefined', { PSPID }); + return null; + } + + const projectResult = await db + .select({ + id: projects.id + }) + .from(projects) + .where(eq(projects.code, PSPID)) + .limit(1); + + if (projectResult.length === 0) { + debugError('PSPID에 해당하는 프로젝트를 찾을 수 없음', { PSPID }); + return null; + } + + debugSuccess('프로젝트 ID 찾음', { PSPID, projectId: projectResult[0].id }); + return projectResult[0].id; + } catch (error) { + debugError('프로젝트 ID 찾기 중 오류 발생', { PSPID, error }); + return null; + } +} + +/** * 자재명 조회 함수 (MATNR 기반) * MATNR을 기반으로 EQUP_MASTER_MATL_CHARASGN 테이블에서 ATWTB 조회 * |
