diff options
Diffstat (limited to 'lib/soap/ecc/mapper/rfq-and-pr-mapper.ts')
| -rw-r--r-- | lib/soap/ecc/mapper/rfq-and-pr-mapper.ts | 177 |
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 }); |
