summaryrefslogtreecommitdiff
path: root/lib/soap
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-17 15:47:07 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-17 15:47:07 +0900
commita5be73b70e7d8e6be1724252e6923c664c3771f4 (patch)
treecc8942f867a8bdeb9d55a000d70f9ee44867b5a8 /lib/soap
parentb9f575f6110faabc7b062f84bf491d69d88a10a5 (diff)
(김준회) 입찰 매핑 안된 필드들 처리
Diffstat (limited to 'lib/soap')
-rw-r--r--lib/soap/ecc/mapper/bidding-and-pr-mapper.ts63
-rw-r--r--lib/soap/ecc/mapper/common-mapper-utils.ts34
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 조회
*