summaryrefslogtreecommitdiff
path: root/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/soap/ecc/mapper/rfq-and-pr-mapper.ts')
-rw-r--r--lib/soap/ecc/mapper/rfq-and-pr-mapper.ts177
1 files changed, 31 insertions, 146 deletions
diff --git a/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts b/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
index e8697bae..7d1c2ab8 100644
--- a/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
+++ b/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
@@ -1,3 +1,9 @@
+/**
+ * pr 발행 후, pr을 묶어서 rfq, bidding 을 sap ecc에서 생성한 경우
+ * ZBSART = AN인 경우, 즉 rfq인 경우 해당 케이스를 soap으로 수신한 뒤 이 함수에서 rqfLast, rfqPrItems 테이블에 매핑
+ * bidding인 경우는 bidding-and-pr-mapper.ts 파일에서 매핑
+ */
+
import { debugLog, debugSuccess, debugError } from '@/lib/debug-utils';
import db from '@/db/db';
import {
@@ -8,10 +14,15 @@ import {
PR_INFORMATION_T_BID_HEADER,
PR_INFORMATION_T_BID_ITEM,
} from '@/db/schema/ECC/ecc';
-import { users } from '@/db/schema';
-import { projects } from '@/db/schema/projects';
-import { MATERIAL_MASTER_PART_MATL } from '@/db/schema/MDG/mdg';
import { eq, inArray, max, sql } from 'drizzle-orm';
+import {
+ findUserInfoByEKGRP,
+ findProjectInfoByPSPID,
+ findMaterialNameByMATNR,
+ parseSAPDateTime,
+ type UserInfo,
+ type ProjectInfo,
+} from './common-mapper-utils';
// ECC 데이터 타입 정의
export type ECCBidHeader = typeof PR_INFORMATION_T_BID_HEADER.$inferInsert;
@@ -43,39 +54,6 @@ function computeSeriesFromItems(items: ECCBidItem[]): string | null {
return uniquePspids.size === 1 ? 'SS' : '||';
}
-/**
- * 담당자 찾는 함수 (userCode 기반으로 직접 조회)
- * EKGRP(구매그룹코드)를 users 테이블의 userCode와 매칭하여 사용자 찾기
- */
-async function findInChargeUserIdByEKGRP(EKGRP: string | null): Promise<number | null> {
- try {
- debugLog('담당자 찾기 시작', { EKGRP });
-
- if (!EKGRP) {
- debugError('EKGRP가 null 또는 undefined', { EKGRP });
- return null;
- }
-
- // users 테이블에서 userCode로 직접 조회
- const userResult = await db
- .select({ id: users.id })
- .from(users)
- .where(eq(users.userCode, EKGRP))
- .limit(1);
-
- if (userResult.length === 0) {
- debugError('EKGRP에 해당하는 사용자를 찾을 수 없음', { EKGRP });
- return null;
- }
-
- const userId = userResult[0].id;
- debugSuccess('담당자 찾음', { EKGRP, userId });
- return userId;
- } catch (error) {
- debugError('담당자 찾기 중 오류 발생', { EKGRP, error });
- return null;
- }
-}
/**
* RFQ 코드 생성 함수 (배치 처리용)
@@ -125,7 +103,7 @@ async function generateRfqCodes(eccHeaders: ECCBidHeader[]): Promise<Map<string,
for (const header of headers) {
const seqString = nextSeq.toString().padStart(5, '0');
const rfqCode = `RFQ${ekgrp}${seqString}`;
- rfqCodeMap.set(header.ANFNR, rfqCode);
+ rfqCodeMap.set(header.ANFNR || '', rfqCode);
nextSeq++; // 다음 시퀀스로 증가
}
}
@@ -143,77 +121,13 @@ async function generateRfqCodes(eccHeaders: ECCBidHeader[]): Promise<Map<string,
eccHeaders.forEach((header, index) => {
const ekgrp = header.EKGRP || 'UNKNOWN';
const seqString = (index + 1).toString().padStart(5, '0');
- fallbackMap.set(header.ANFNR, `RFQ${ekgrp}${seqString}`);
+ fallbackMap.set(header.ANFNR || '', `RFQ${ekgrp}${seqString}`);
});
return fallbackMap;
}
}
-/**
- * 프로젝트 ID 찾기 함수
- * 첫번째 PR Item의 PSPID와 projects.code 매칭
- */
-async function findProjectIdByPSPID(PSPID: string | null): Promise<number | null> {
- try {
- debugLog('프로젝트 ID 찾기 시작', { 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;
- }
-
- const projectId = projectResult[0].id;
- debugSuccess('프로젝트 ID 찾음', { PSPID, projectId });
- return projectId;
- } catch (error) {
- debugError('프로젝트 ID 찾기 중 오류 발생', { PSPID, error });
- return null;
- }
-}
-
-/**
- * 자재명 조회 함수
- * MATNR을 기반으로 MDG 테이블에서 ZZNAME 조회
- */
-async function findMaterialNameByMATNR(MATNR: string | null): Promise<string | null> {
- try {
- debugLog('자재명 조회 시작', { MATNR });
-
- if (!MATNR) {
- debugError('MATNR이 null 또는 undefined', { MATNR });
- return null;
- }
-
- const materialResult = await db
- .select({ ZZNAME: MATERIAL_MASTER_PART_MATL.ZZNAME })
- .from(MATERIAL_MASTER_PART_MATL)
- .where(eq(MATERIAL_MASTER_PART_MATL.MATNR, MATNR))
- .limit(1);
-
- if (materialResult.length === 0) {
- debugError('MATNR에 해당하는 자재를 찾을 수 없음', { MATNR });
- return null;
- }
-
- const materialName = materialResult[0].ZZNAME;
- debugSuccess('자재명 조회 완료', { MATNR, materialName });
- return materialName;
- } catch (error) {
- debugError('자재명 조회 중 오류 발생', { MATNR, error });
- return null;
- }
-}
// *****************************mapping functions*********************************
@@ -232,32 +146,11 @@ export async function mapECCRfqHeaderToRfqLast(
const firstItem = eccItems.find(item => item.ANFNR === eccHeader.ANFNR);
// 날짜 파싱 (실패시 현재 Date 들어감)
- let interfacedAt: Date = new Date();
-
- if (eccHeader.ZRFQ_TRS_DT != null && eccHeader.ZRFQ_TRS_TM != null) {
- try {
- // SAP 날짜 형식 (YYYYMMDD) 파싱
- const dateStr = eccHeader.ZRFQ_TRS_DT;
- if (dateStr.length === 8) {
- const year = parseInt(dateStr.substring(0, 4));
- const month = parseInt(dateStr.substring(4, 6)) - 1; // 0-based
- const day = parseInt(dateStr.substring(6, 8));
- const hour = parseInt(eccHeader.ZRFQ_TRS_TM.substring(0, 2));
- const minute = parseInt(eccHeader.ZRFQ_TRS_TM.substring(2, 4));
- const second = parseInt(eccHeader.ZRFQ_TRS_TM.substring(4, 6));
- interfacedAt = new Date(year, month, day, hour, minute, second);
- }
- } catch (error) {
- debugError('날짜 파싱 오류', {
- date: eccHeader.ZRFQ_TRS_DT,
- time: eccHeader.ZRFQ_TRS_TM,
- error,
- });
- }
- }
+ const interfacedAt = parseSAPDateTime(eccHeader.ZRFQ_TRS_DT || null, eccHeader.ZRFQ_TRS_TM || null);
// 담당자 찾기
- const inChargeUserId = await findInChargeUserIdByEKGRP(eccHeader.EKGRP || null);
+ const inChargeUserInfo = await findUserInfoByEKGRP(eccHeader.EKGRP || null);
+ const inChargeUserId = inChargeUserInfo?.userId || null;
// 첫번째 PR Item 기반으로 projectId, itemCode, itemName 설정
let projectId: number | null = null;
@@ -267,7 +160,8 @@ export async function mapECCRfqHeaderToRfqLast(
if (firstItem) {
// projectId: 첫번째 PR Item의 PSPID와 projects.code 매칭
- projectId = await findProjectIdByPSPID(firstItem.PSPID || null);
+ const projectInfo = await findProjectInfoByPSPID(firstItem.PSPID || null);
+ projectId = projectInfo?.id || null;
// itemCode: 첫번째 PR Item의 MATKL
itemCode = firstItem.MATKL || null;
@@ -332,17 +226,8 @@ export function mapECCRfqItemToRfqPrItem(
// 날짜 파싱
let deliveryDate: Date | null = null;
if (eccItem.LFDAT) {
- try {
- const dateStr = eccItem.LFDAT;
- if (dateStr.length === 8) {
- const year = parseInt(dateStr.substring(0, 4));
- const month = parseInt(dateStr.substring(4, 6)) - 1;
- const day = parseInt(dateStr.substring(6, 8));
- deliveryDate = new Date(year, month, day);
- }
- } catch (error) {
- debugError('아이템 날짜 파싱 오류', { date: eccItem.LFDAT, error });
- }
+ const dateStr = parseSAPDateTime(eccItem.LFDAT, '000000');
+ deliveryDate = dateStr;
}
const mappedData: RfqPrItemData = {
@@ -434,14 +319,14 @@ export async function mapAndSaveECCRfqDataToRfqLast(
set: {
updatedAt: new Date(),
// ANFNR이 같으면 기존 데이터를 업데이트
- projectId: sql`EXCLUDED.project_id`,
- series: sql`EXCLUDED.series`,
- itemCode: sql`EXCLUDED.item_code`,
- itemName: sql`EXCLUDED.item_name`,
- picCode: sql`EXCLUDED.pic_code`,
- pic: sql`EXCLUDED.pic`,
- prNumber: sql`EXCLUDED.pr_number`,
- prIssueDate: sql`EXCLUDED.pr_issue_date`,
+ projectId: sql`EXCLUDED."project_id"`,
+ series: sql`EXCLUDED."series"`,
+ itemCode: sql`EXCLUDED."item_code"`,
+ itemName: sql`EXCLUDED."item_name"`,
+ picCode: sql`EXCLUDED."pic_code"`,
+ pic: sql`EXCLUDED."pic"`,
+ prNumber: sql`EXCLUDED."pr_number"`,
+ prIssueDate: sql`EXCLUDED."pr_issue_date"`,
}
})
.returning({ id: rfqsLast.id, rfqCode: rfqsLast.rfqCode });