diff options
| author | joonhoekim <26rote@gmail.com> | 2025-09-03 09:22:56 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-09-03 09:22:56 +0000 |
| commit | bfe354f7633f62350e61eb784cbf1926079339d1 (patch) | |
| tree | 691ad115b89ee1b7e5fb2dab165c85ea325cf920 /lib/nonsap-sync | |
| parent | c5fc7195505d82c60fc9dffc3744782b91d7ebb7 (diff) | |
(김준회) 구매그룹코드를 users 테이블의 userCode 컬럼에 업데이트하도록 cronjob 등록
Diffstat (limited to 'lib/nonsap-sync')
| -rw-r--r-- | lib/nonsap-sync/purchase-group-code/purchase-group-code-sync.ts | 143 | ||||
| -rw-r--r-- | lib/nonsap-sync/purchase-group-code/user-code-sync-scheduler.ts | 46 |
2 files changed, 189 insertions, 0 deletions
diff --git a/lib/nonsap-sync/purchase-group-code/purchase-group-code-sync.ts b/lib/nonsap-sync/purchase-group-code/purchase-group-code-sync.ts new file mode 100644 index 00000000..903a164c --- /dev/null +++ b/lib/nonsap-sync/purchase-group-code/purchase-group-code-sync.ts @@ -0,0 +1,143 @@ +import { oracleKnex } from '@/lib/oracle-db/db'; +import db from '@/db/db'; +import { users } from '@/db/schema/users'; +import { eq } from 'drizzle-orm'; + +/** + * 오라클 NonSAP 데이터베이스에서 구매그룹 정보 조회 + * CMCTB_CD 테이블에서 CD_CLF='MMA070' 조건으로 구매그룹 데이터를 가져옴 + */ +async function fetchPurchasingGroupsFromOracle(): Promise<Array<{ code: string; employeeNumber: string }>> { + try { + console.log('🔍 오라클에서 구매그룹 데이터 조회 시작...'); + + const result = await oracleKnex + .select('CD as code', 'USR_DF_CHAR_9 as employeeNumber') + .from('CMCTB_CD') + .where('CD_CLF', 'MMA070') + .whereNotNull('USR_DF_CHAR_9') + + console.log(`✅ 구매그룹 데이터 ${result.length}건 조회 완료`); + return result; + } catch (error) { + console.error('❌ 오라클에서 구매그룹 데이터 조회 중 오류:', error); + throw error; + } +} + +/** + * employeeNumber 기준으로 users 테이블에 사용자 코드 upsert + */ +async function updateUsersCode(purchasingGroups: Array<{ code: string; employeeNumber: string }>) { + try { + console.log('🔄 사용자 테이블 사용자 코드 업데이트 시작...'); + + let updateCount = 0; + let notFoundCount = 0; + const errors: Array<{ employeeNumber: string; error: string }> = []; + + // 개별 트랜잭션으로 안전하게 처리 + for (const group of purchasingGroups) { + try { + await db.transaction(async (tx) => { + const result = await tx + .update(users) + .set({ + userCode: group.code, + updatedAt: new Date() + }) + .where(eq(users.employeeNumber, group.employeeNumber)) + .returning({ id: users.id }); + + if (result.length > 0) { + updateCount++; + } else { + notFoundCount++; + console.warn(`⚠️ 사번 ${group.employeeNumber}에 해당하는 사용자를 찾을 수 없음 (사용자 코드: ${group.code})`); + } + }); + } catch (error) { + errors.push({ + employeeNumber: group.employeeNumber, + error: error instanceof Error ? error.message : '알 수 없는 오류' + }); + console.error(`❌ 사번 ${group.employeeNumber} 업데이트 중 오류:`, error); + } + } + + // 에러가 있었다면 로그 출력 + if (errors.length > 0) { + console.error(`❌ ${errors.length}건의 업데이트 오류 발생:`); + errors.forEach(({ employeeNumber, error }) => { + console.error(` - 사번 ${employeeNumber}: ${error}`); + }); + } + + console.log(`✅ 사용자 코드 업데이트 완료: 성공 ${updateCount}건, 미발견 ${notFoundCount}건`); + return { updateCount, notFoundCount }; + } catch (error) { + console.error('❌ 사용자 테이블 업데이트 중 오류:', error); + throw error; + } +} + +/** + * 사용자 코드 동기화 메인 함수 + * 오라클에서 구매그룹 데이터를 조회하여 users 테이블을 업데이트 + */ +export async function syncUserCodes(): Promise<{ success: boolean; updateCount: number; notFoundCount: number; error?: string }> { + try { + console.log('🚀 사용자 코드 동기화 작업 시작...'); + const startTime = Date.now(); + + // 1. 오라클에서 구매그룹 데이터 조회 + const purchasingGroups = await fetchPurchasingGroupsFromOracle(); + + if (purchasingGroups.length === 0) { + console.log('⚠️ 조회된 구매그룹 데이터가 없습니다.'); + return { success: true, updateCount: 0, notFoundCount: 0 }; + } + + // 2. users 테이블 업데이트 + const { updateCount, notFoundCount } = await updateUsersCode(purchasingGroups); + + const endTime = Date.now(); + const duration = endTime - startTime; + + console.log(`🎉 사용자 코드 동기화 완료! 소요시간: ${duration}ms`); + console.log(`📊 처리 결과: 총 ${purchasingGroups.length}건 중 업데이트 ${updateCount}건, 미발견 ${notFoundCount}건`); + + return { + success: true, + updateCount, + notFoundCount + }; + } catch (error) { + console.error('💥 사용자 코드 동기화 작업 중 오류:', error); + return { + success: false, + updateCount: 0, + notFoundCount: 0, + error: error instanceof Error ? error.message : '알 수 없는 오류' + }; + } +} + +/** + * 특정 사번의 사용자 코드를 조회하는 함수 (개별 조회용) + */ +export async function getUserCodeByEmployeeNumber(employeeNumber: string): Promise<string | null> { + try { + const result = await oracleKnex + .select('CD') + .from('CMCTB_CD') + .where('CD_CLF', 'MMA070') + .andWhere('USR_DF_CHAR_9', employeeNumber) + .limit(1); + + return result.length > 0 ? result[0].CD : null; + } catch (error) { + console.error(`사용자 코드 조회 중 오류 (사번: ${employeeNumber}):`, error); + return null; + } +} diff --git a/lib/nonsap-sync/purchase-group-code/user-code-sync-scheduler.ts b/lib/nonsap-sync/purchase-group-code/user-code-sync-scheduler.ts new file mode 100644 index 00000000..23d0b568 --- /dev/null +++ b/lib/nonsap-sync/purchase-group-code/user-code-sync-scheduler.ts @@ -0,0 +1,46 @@ +'use server'; + +import * as cron from 'node-cron'; +import { syncUserCodes } from './purchase-group-code-sync'; + +// CRON 스케줄 (기본: 매일 새벽 3시) +const CRON_STRING = process.env.USER_CODE_SYNC_CRON || '0 3 * * *'; + +// 애플리케이션 기동 시 최초 한 번 실행 여부 +const DO_FIRST_RUN = process.env.USER_CODE_SYNC_FIRST_RUN === 'true'; + +/** + * 사용자 코드 동기화 스케줄러 시작 + */ +export async function startUserCodeSyncScheduler(): Promise<void> { + console.log('[USER-CODE-SYNC] 사용자 코드 동기화 스케줄러 초기화 중...'); + + try { + // 환경 변수에 따라 실행시 즉시 실행 여부 결정 + if (DO_FIRST_RUN) { + console.log('[USER-CODE-SYNC] 첫 실행: 사용자 코드 동기화 즉시 시작'); + syncUserCodes().catch((error) => { + console.error('[USER-CODE-SYNC] 첫 실행 중 오류:', error); + }); + } + + // CRON JOB 등록 + cron.schedule(CRON_STRING, async () => { + try { + console.log('[USER-CODE-SYNC] CRON 실행: 사용자 코드 동기화 시작'); + await syncUserCodes(); + } catch (error) { + console.error('[USER-CODE-SYNC] 예약된 동기화 실패:', error); + // 동기화 실패해도 다음 스케줄은 계속 실행 + } + }, { + timezone: 'Asia/Seoul' + }); + + console.log(`[USER-CODE-SYNC] ✅ 사용자 코드 동기화 CRON 작업 등록 완료 (${CRON_STRING})`); + + } catch (error) { + console.error('[USER-CODE-SYNC] 스케줄러 초기화 실패:', error); + throw error; + } +} |
