diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-04-08 03:08:19 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-04-08 03:08:19 +0000 |
| commit | 9ceed79cf32c896f8a998399bf1b296506b2cd4a (patch) | |
| tree | f84750fa6cac954d5e31221fc47a54c655fc06a9 /lib/sedp/sync-projects.ts | |
| parent | 230ce796836c25df26c130dbcd616ef97d12b2ec (diff) | |
로그인 및 미들웨어 처리. 구조 변경
Diffstat (limited to 'lib/sedp/sync-projects.ts')
| -rw-r--r-- | lib/sedp/sync-projects.ts | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/lib/sedp/sync-projects.ts b/lib/sedp/sync-projects.ts new file mode 100644 index 00000000..1094b55f --- /dev/null +++ b/lib/sedp/sync-projects.ts @@ -0,0 +1,194 @@ +// src/lib/cron/syncProjects.ts +import db from "@/db/db"; +import { projects } from '@/db/schema'; +import { eq } from 'drizzle-orm'; +import { getSEDPToken } from "./sedp-token"; + +// 환경 변수 +const SEDP_API_BASE_URL = process.env.SEDP_API_BASE_URL || 'http://sedpwebapi.ship.samsung.co.kr/dev/api'; + +// 인터페이스 정의 +interface Project { + PROJ_NO: string; + DESC: string; + TYPE?: string; + DELETED?: boolean; + DEL_USER?: string | null; + DEL_DTM?: string | null; + CRTER_NO?: string; + CRTE_DTM?: string; + CHGER_NO?: string | null; + CHGE_DTM?: string | null; + _id?: string; +} + +interface SyncResult { + success: number; + failed: number; + items: number; + timestamp: string; +} + +// 프로젝트 데이터 가져오기 +async function getProjects(): Promise<Project[]> { + try { + // 토큰(API 키) 가져오기 + const apiKey = await getSEDPToken(); + + const response = await fetch( + `${SEDP_API_BASE_URL}/Project/Get`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'accept': '*/*', + 'ApiKey': apiKey + }, + body: JSON.stringify({ + ContainDeleted: true + }) + } + ); + + if (!response.ok) { + throw new Error(`프로젝트 요청 실패: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + + // 결과가 배열인지 확인 + if (Array.isArray(data)) { + return data; + } else { + // 단일 객체인 경우 배열로 변환 + return [data]; + } + } catch (error) { + console.error('프로젝트 목록 가져오기 실패:', error); + throw error; + } +} + +// 데이터베이스에 프로젝트 저장 +async function saveProjectsToDatabase(projectsData: Project[]): Promise<number> { + try { + // 기존 프로젝트 조회 + const existingProjects = await db.select().from(projects); + + // 코드 기준으로 맵 생성 + const existingProjectMap = new Map( + existingProjects.map(project => [project.code, project]) + ); + + // 새로 추가할 항목 + const toInsert = []; + + // 업데이트할 항목 + const toUpdate = []; + + // API에 있는 코드 목록 + const apiProjectCodes = new Set(projectsData.map(project => project.PROJ_NO)); + + // 삭제할 코드 목록 + const codesToDelete = [...existingProjectMap.keys()] + .filter(code => !apiProjectCodes.has(code)); + + // 프로젝트 데이터 처리 + for (const project of projectsData) { + // 삭제된 프로젝트는 건너뜀 + if (project.DELETED) continue; + + // 프로젝트 레코드 준비 + const projectRecord = { + code: project.PROJ_NO, + name: project.DESC || project.PROJ_NO, + type: project.TYPE || 'ship', + updatedAt: new Date() + }; + + // 이미 존재하는 코드인지 확인 + if (existingProjectMap.has(project.PROJ_NO)) { + // 업데이트 항목에 추가 + toUpdate.push(projectRecord); + } else { + // 새로 추가할 항목에 추가 + toInsert.push({ + ...projectRecord, + createdAt: new Date() + }); + } + } + + // 트랜잭션 실행 + let totalChanged = 0; + + // 1. 새 프로젝트 삽입 + if (toInsert.length > 0) { + await db.insert(projects).values(toInsert); + totalChanged += toInsert.length; + console.log(`${toInsert.length}개의 새 프로젝트 추가 완료`); + } + + // 2. 기존 프로젝트 업데이트 + for (const item of toUpdate) { + await db.update(projects) + .set({ + name: item.name, + type: item.type, + updatedAt: item.updatedAt + }) + .where(eq(projects.code, item.code)); + totalChanged += 1; + } + + if (toUpdate.length > 0) { + console.log(`${toUpdate.length}개 프로젝트 업데이트 완료`); + } + + // 3. 더 이상 존재하지 않는 프로젝트 삭제 + if (codesToDelete.length > 0) { + for (const code of codesToDelete) { + await db.delete(projects) + .where(eq(projects.code, code)); + } + console.log(`${codesToDelete.length}개의 프로젝트 삭제 완료`); + totalChanged += codesToDelete.length; + } + + return totalChanged; + } catch (error) { + console.error('프로젝트 저장 실패:', error); + throw error; + } +} + +// 메인 동기화 함수 +export async function syncProjects(): Promise<SyncResult> { + try { + console.log('프로젝트 동기화 시작:', new Date().toISOString()); + + // 1. 프로젝트 데이터 가져오기 + const projectsData = await getProjects(); + console.log(`${projectsData.length}개의 프로젝트 정보를 가져왔습니다.`); + + // 2. 데이터베이스에 저장 + const totalItems = await saveProjectsToDatabase(projectsData); + + console.log(`프로젝트 동기화 완료: 총 ${totalItems}개 항목 처리됨`); + + return { + success: 1, // 단일 작업이므로 성공은 1 + failed: 0, + items: totalItems, + timestamp: new Date().toISOString() + }; + } catch (error) { + console.error('프로젝트 동기화 중 오류 발생:', error); + return { + success: 0, + failed: 1, + items: 0, + timestamp: new Date().toISOString() + }; + } +}
\ No newline at end of file |
