summaryrefslogtreecommitdiff
path: root/lib/soap/ecc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/soap/ecc')
-rw-r--r--lib/soap/ecc/mapper/common-mapper-utils.ts51
-rw-r--r--lib/soap/ecc/mapper/rfq-and-pr-mapper.ts17
-rw-r--r--lib/soap/ecc/send/create-po.ts49
3 files changed, 73 insertions, 44 deletions
diff --git a/lib/soap/ecc/mapper/common-mapper-utils.ts b/lib/soap/ecc/mapper/common-mapper-utils.ts
index 2199490a..ed655e0e 100644
--- a/lib/soap/ecc/mapper/common-mapper-utils.ts
+++ b/lib/soap/ecc/mapper/common-mapper-utils.ts
@@ -307,6 +307,57 @@ export interface ProjectInfo {
}
/**
+ * 사번(PERNR)으로 사용자 정보 조회 함수
+ * PERNR(사번)으로 users 테이블의 employeeNumber와 매칭하여 사용자 정보 조회
+ */
+export async function findUserInfoByPERNR(PERNR: string | null): Promise<{
+ userId: number;
+ userName: string;
+ userEmail: string | null;
+ userPhone: string | null;
+ employeeNumber: string | null;
+} | null> {
+ try {
+ debugLog('사번으로 사용자 조회 시작', { PERNR });
+
+ if (!PERNR) {
+ debugError('PERNR이 null 또는 undefined', { PERNR });
+ return null;
+ }
+
+ const userResult = await db
+ .select({
+ id: users.id,
+ name: users.name,
+ email: users.email,
+ phone: users.phone,
+ employeeNumber: users.employeeNumber
+ })
+ .from(users)
+ .where(eq(users.employeeNumber, PERNR))
+ .limit(1);
+
+ if (userResult.length === 0) {
+ debugError('PERNR에 해당하는 사용자를 찾을 수 없음', { PERNR });
+ return null;
+ }
+
+ const userInfo = {
+ userId: userResult[0].id,
+ userName: userResult[0].name,
+ userEmail: userResult[0].email,
+ userPhone: userResult[0].phone,
+ employeeNumber: userResult[0].employeeNumber
+ };
+ debugSuccess('사번으로 사용자 정보 찾음', { PERNR, userInfo });
+ return userInfo;
+ } catch (error) {
+ debugError('사번으로 사용자 조회 중 오류 발생', { PERNR, error });
+ return null;
+ }
+}
+
+/**
* 협력업체 코드(LIFNR)로 vendorId 찾기
* LIFNR = 벤더코드 (ex. A0001234)
* vendors 테이블의 vendorCode 필드와 비교하여 vendorId를 찾음
diff --git a/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts b/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
index 85fbb918..d08bc5fb 100644
--- a/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
+++ b/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
@@ -24,6 +24,7 @@ import {
findUserInfoByEKGRP,
findProjectInfoByPSPID,
parseSAPDateTime,
+ findUserInfoByPERNR,
} from './common-mapper-utils';
// ECC 데이터 타입 정의
@@ -154,11 +155,13 @@ export async function mapECCRfqHeaderToRfqLast(
const inChargeUserInfo = await findUserInfoByEKGRP(eccHeader.EKGRP || null);
const inChargeUserId = inChargeUserInfo?.userId || null;
- // 대표 PR Item 기반으로 projectId, itemCode, itemName 설정 (없으면 첫번째 PR Item 사용)
+ // 대표 PR Item 기반으로 projectId, itemCode, itemName, 설계담당자 설정 (없으면 첫번째 PR Item 사용)
let projectId: number | null = null;
let itemCode: string | null = null;
let itemName: string | null = null;
let prNumber: string | null = null;
+ let engPicName: string | null = null;
+ let engPicEmployeeNumber: string | null = null;
let representativeItem: ECCBidItem | undefined;
if (firstItem) {
@@ -185,6 +188,15 @@ export async function mapECCRfqHeaderToRfqLast(
// prNumber: 대표 PR의 BANFN 또는 첫번째 PR의 ZREQ_FN 값
prNumber = representativeItem?.BANFN || firstItem.ZREQ_FN || null;
+
+ // 설계담당자 정보: 대표 PR Item의 PERNR로 조회
+ if (targetItem.PERNR) {
+ const engPicInfo = await findUserInfoByPERNR(targetItem.PERNR);
+ if (engPicInfo) {
+ engPicName = engPicInfo.userName;
+ engPicEmployeeNumber = engPicInfo.employeeNumber;
+ }
+ }
}
// 매핑
@@ -199,7 +211,8 @@ export async function mapECCRfqHeaderToRfqLast(
rfqSendDate: null, // ECC에서 제공되지 않음
status: 'RFQ 생성', // 한글 상태로 변경
rfqSealedYn: false,
- EngPicName: null, // ECC에서 제공되지 않음
+ EngPicName: engPicName, // 대표 PR Item의 PERNR로 조회한 설계담당자명
+ EngPicEmployeeNumber: engPicEmployeeNumber, // 대표 PR Item의 PERNR(사번)
packageNo: null, // ECC에서 제공되지 않음
packageName: null, // ECC에서 제공되지 않음
remark: null,
diff --git a/lib/soap/ecc/send/create-po.ts b/lib/soap/ecc/send/create-po.ts
index 0984a208..1e21d39c 100644
--- a/lib/soap/ecc/send/create-po.ts
+++ b/lib/soap/ecc/send/create-po.ts
@@ -44,23 +44,11 @@ export interface POItemData {
EBELP?: string; // Series PO Item Seq
}
-// PR 반환 데이터 타입
-export interface PRReturnData {
- ANFNR: string; // PR Request Number (M)
- ANFPS: string; // Item Number of PR Request (M)
- EBELN: string; // Purchase Requisition Number (M)
- EBELP: string; // Item Number of Purchase Requisition (M)
- MSGTY: string; // Message Type (M)
- MSGTXT?: string; // Message Text
-}
-
// PO 생성 요청 데이터 타입
+// 참고: T_PR_RETURN, EV_ERDAT, EV_ERZET는 응답용 필드이므로 요청에 포함하지 않음
export interface POCreateRequest {
T_Bidding_HEADER: POHeaderData[];
T_Bidding_ITEM: POItemData[];
- T_PR_RETURN: PRReturnData[];
- EV_ERDAT?: string; // Extract Date
- EV_ERZET?: string; // Extract Time
}
@@ -72,10 +60,8 @@ function createPOSoapBodyContent(poData: POCreateRequest): Record<string, unknow
return {
'p1:MT_P2MM3015_S': { // WSDL에서 사용하는 p1 접두사 적용
'T_Bidding_HEADER': poData.T_Bidding_HEADER,
- 'T_Bidding_ITEM': poData.T_Bidding_ITEM,
- 'T_PR_RETURN': poData.T_PR_RETURN,
- ...(poData.EV_ERDAT && { 'EV_ERDAT': poData.EV_ERDAT }),
- ...(poData.EV_ERZET && { 'EV_ERZET': poData.EV_ERZET })
+ 'T_Bidding_ITEM': poData.T_Bidding_ITEM
+ // T_PR_RETURN, EV_ERDAT, EV_ERZET는 응답용 필드이므로 요청에 포함하지 않음
}
};
}
@@ -112,19 +98,7 @@ function validatePOData(poData: POCreateRequest): { isValid: boolean; errors: st
});
}
- // PR 반환 데이터 검증
- if (!poData.T_PR_RETURN || poData.T_PR_RETURN.length === 0) {
- errors.push('T_PR_RETURN은 필수입니다.');
- } else {
- poData.T_PR_RETURN.forEach((prReturn, index) => {
- const requiredFields = ['ANFNR', 'ANFPS', 'EBELN', 'EBELP', 'MSGTY'];
- requiredFields.forEach(field => {
- if (!prReturn[field as keyof PRReturnData]) {
- errors.push(`T_PR_RETURN[${index}].${field}는 필수입니다.`);
- }
- });
- });
- }
+ // T_PR_RETURN은 응답용 필드이므로 검증하지 않음
return {
isValid: errors.length === 0,
@@ -165,7 +139,7 @@ async function sendPOToECC(poData: POCreateRequest): Promise<SoapSendResult> {
};
console.log(`📤 PO 생성 요청 전송 시작 - ANFNR: ${poData.T_Bidding_HEADER[0]?.ANFNR}`);
- console.log(`🔍 헤더 ${poData.T_Bidding_HEADER.length}개, 아이템 ${poData.T_Bidding_ITEM.length}개, PR 반환 ${poData.T_PR_RETURN.length}개`);
+ console.log(`🔍 헤더 ${poData.T_Bidding_HEADER.length}개, 아이템 ${poData.T_Bidding_ITEM.length}개`);
// SOAP XML 전송
const result = await sendSoapXml(config, logInfo);
@@ -341,17 +315,8 @@ export async function createTestPurchaseOrder(): Promise<{
LFDAT: getCurrentSAPDate(),
ZCON_NO_PO: 'CON001',
EBELP: '00001'
- }],
- T_PR_RETURN: [{
- ANFNR: 'TEST001',
- ANFPS: '00001',
- EBELN: 'PR001',
- EBELP: '00001',
- MSGTY: 'S',
- MSGTXT: 'Test message'
- }],
- EV_ERDAT: getCurrentSAPDate(),
- EV_ERZET: getCurrentSAPTime()
+ }]
+ // T_PR_RETURN, EV_ERDAT, EV_ERZET는 응답용 필드이므로 요청에 포함하지 않음
};
const result = await sendPOToECC(testPOData);