summaryrefslogtreecommitdiff
path: root/lib/sedp/sync-package.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-06-01 13:52:21 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-06-01 13:52:21 +0000
commitbac0228d21b7195065e9cddcc327ae33659c7bcc (patch)
tree8f3016ae4533c8706d0c00a605d9b1d41968c2bc /lib/sedp/sync-package.ts
parent2fdce8d7a57c792bba0ac36fa554dca9c9cc31e3 (diff)
(대표님) 20250601까지 작업사항
Diffstat (limited to 'lib/sedp/sync-package.ts')
-rw-r--r--lib/sedp/sync-package.ts282
1 files changed, 282 insertions, 0 deletions
diff --git a/lib/sedp/sync-package.ts b/lib/sedp/sync-package.ts
new file mode 100644
index 00000000..c8f39ad8
--- /dev/null
+++ b/lib/sedp/sync-package.ts
@@ -0,0 +1,282 @@
+"use server"
+// src/lib/cron/syncItemsFromCodeLists.ts
+import db from "@/db/db";
+import { projects, items } 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/api';
+
+async function getCodeLists(projectCode: string): Promise<Map<string, CodeList>> {
+ try {
+ // 토큰(API 키) 가져오기
+ const apiKey = await getSEDPToken();
+
+ const response = await fetch(
+ `${SEDP_API_BASE_URL}/CodeList/Get`,
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'accept': '*/*',
+ 'ApiKey': apiKey,
+ 'ProjectNo': projectCode
+ },
+ body: JSON.stringify({
+ ProjectNo: projectCode,
+ ContainDeleted: false
+ })
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(`코드 리스트 요청 실패: ${response.status} ${response.statusText}`);
+ }
+
+ // 안전하게 JSON 파싱
+ try {
+ const data = await response.json();
+
+ // 데이터가 배열인지 확인
+ const codeLists: CodeList[] = Array.isArray(data) ? data : [data];
+
+ // CL_ID로 효율적인 조회를 위한 맵 생성
+ const codeListMap = new Map<string, CodeList>();
+ for (const codeList of codeLists) {
+ if (!codeList.DELETED) {
+ codeListMap.set(codeList.CL_ID, codeList);
+ }
+ }
+
+ console.log(`프로젝트 ${projectCode}에서 ${codeListMap.size}개의 코드 리스트를 가져왔습니다`);
+ return codeListMap;
+
+ } catch (parseError) {
+ console.error(`프로젝트 ${projectCode}의 코드 리스트 응답 파싱 실패:`, parseError);
+ // 응답 내용 로깅
+ try {
+ const text = await response.clone().text();
+ console.log(`응답 내용: ${text.substring(0, 200)}${text.length > 200 ? '...' : ''}`);
+ } catch (textError) {
+ console.error('응답 내용 로깅 실패:', textError);
+ }
+ return new Map();
+ }
+ } catch (error) {
+ console.error(`프로젝트 ${projectCode}의 코드 리스트 가져오기 실패:`, error);
+ return new Map();
+ }
+ }
+
+
+interface CodeValue {
+ VALUE: string;
+ DESCC: string;
+ ATTRIBUTES: Array<{
+ ATT_ID: string;
+ VALUE: string;
+ }>;
+}
+
+interface CodeList {
+ PROJ_NO: string;
+ CL_ID: string;
+ DESC: string;
+ REMARK: string | null;
+ PRNT_CD_ID: string | null;
+ REG_TYPE_ID: string | null;
+ VAL_ATT_ID: string | null;
+ VALUES: CodeValue[];
+ LNK_ATT: any[];
+ DELETED: boolean;
+ CRTER_NO: string;
+ CRTE_DTM: string;
+ CHGER_NO: string | null;
+ CHGE_DTM: string | null;
+ _id: string;
+}
+
+export async function syncItemsFromCodeLists(): Promise<void> {
+ try {
+ console.log('아이템 동기화 시작...');
+
+ // 모든 프로젝트 가져오기
+ const allProjects = await db.select().from(projects);
+ console.log(`총 ${allProjects.length}개의 프로젝트를 처리합니다.`);
+
+ let totalItemsProcessed = 0;
+ let totalItemsInserted = 0;
+ let totalItemsUpdated = 0;
+
+ for (const project of allProjects) {
+ try {
+ console.log(`프로젝트 ${project.code} (${project.name}) 처리 중...`);
+
+ // 프로젝트의 코드리스트 가져오기
+ const codeListMap = await getCodeLists(project.code);
+
+ // PKG_NO 코드리스트 찾기
+ const pkgNoCodeList = codeListMap.get('PKG_NO');
+
+ if (!pkgNoCodeList) {
+ console.log(`프로젝트 ${project.code}에서 PKG_NO 코드리스트를 찾을 수 없습니다.`);
+ continue;
+ }
+
+ console.log(`프로젝트 ${project.code}에서 ${pkgNoCodeList.VALUES.length}개의 아이템을 처리합니다.`);
+
+ // VALUES 배열 순회하며 items 테이블에 삽입/업데이트
+ for (const codeValue of pkgNoCodeList.VALUES) {
+ try {
+ // ATTRIBUTES에서 필요한 값들 추출
+ const packageCodeAttr = codeValue.ATTRIBUTES?.find(attr => attr.ATT_ID === 'SHI_PACK_NO');
+ const smCodeAttr = codeValue.ATTRIBUTES?.find(attr => attr.ATT_ID === 'SM_code');
+
+ const itemData = {
+ ProjectNo: project.code,
+ itemCode: codeValue.VALUE,
+ itemName: codeValue.DESCC || '',
+ packageCode: packageCodeAttr?.VALUE || '',
+ smCode: smCodeAttr?.VALUE || null,
+ description: null, // 필요시 추가 매핑
+ parentItemCode: null, // 필요시 추가 매핑
+ itemLevel: null, // 필요시 추가 매핑
+ deleteFlag: 'N', // 기본값
+ unitOfMeasure: null, // 필요시 추가 매핑
+ steelType: null, // 필요시 추가 매핑
+ gradeMaterial: null, // 필요시 추가 매핑
+ changeDate: null, // 필요시 추가 매핑
+ baseUnitOfMeasure: null, // 필요시 추가 매핑
+ updatedAt: new Date()
+ };
+
+ // 기존 아이템 확인 (itemCode로 조회)
+ const existingItem = await db.select()
+ .from(items)
+ .where(eq(items.itemCode, codeValue.VALUE))
+ .limit(1);
+
+ if (existingItem.length > 0) {
+ // 기존 아이템 업데이트
+ await db.update(items)
+ .set(itemData)
+ .where(eq(items.itemCode, codeValue.VALUE));
+ totalItemsUpdated++;
+ } else {
+ // 새 아이템 삽입
+ await db.insert(items).values(itemData);
+ totalItemsInserted++;
+ }
+
+ totalItemsProcessed++;
+ } catch (itemError) {
+ console.error(`아이템 ${codeValue.VALUE} 처리 중 오류:`, itemError);
+ }
+ }
+
+ console.log(`프로젝트 ${project.code} 완료`);
+ } catch (projectError) {
+ console.error(`프로젝트 ${project.code} 처리 중 오류:`, projectError);
+ }
+ }
+
+ console.log(`아이템 동기화 완료:`);
+ console.log(`- 총 처리된 아이템: ${totalItemsProcessed}개`);
+ console.log(`- 새로 삽입된 아이템: ${totalItemsInserted}개`);
+ console.log(`- 업데이트된 아이템: ${totalItemsUpdated}개`);
+
+ } catch (error) {
+ console.error('아이템 동기화 중 전체 오류:', error);
+ throw error;
+ }
+}
+
+// 특정 프로젝트만 동기화하는 함수
+export async function syncItemsForProject(projectCode: string): Promise<void> {
+ try {
+ console.log(`프로젝트 ${projectCode}의 아이템 동기화 시작...`);
+
+ // 프로젝트 존재 확인
+ const project = await db.select()
+ .from(projects)
+ .where(eq(projects.code, projectCode))
+ .limit(1);
+
+ if (project.length === 0) {
+ throw new Error(`프로젝트 ${projectCode}를 찾을 수 없습니다.`);
+ }
+
+ // 프로젝트의 코드리스트 가져오기
+ const codeListMap = await getCodeLists(projectCode);
+
+ // PKG_NO 코드리스트 찾기
+ const pkgNoCodeList = codeListMap.get('PKG_NO');
+
+ if (!pkgNoCodeList) {
+ console.log(`프로젝트 ${projectCode}에서 PKG_NO 코드리스트를 찾을 수 없습니다.`);
+ return;
+ }
+
+ console.log(`${pkgNoCodeList.VALUES.length}개의 아이템을 처리합니다.`);
+
+ let itemsProcessed = 0;
+ let itemsInserted = 0;
+ let itemsUpdated = 0;
+
+ // VALUES 배열 순회하며 items 테이블에 삽입/업데이트
+ for (const codeValue of pkgNoCodeList.VALUES) {
+ try {
+ // ATTRIBUTES에서 필요한 값들 추출
+ const packageCodeAttr = codeValue.ATTRIBUTES?.find(attr => attr.ATT_ID === 'SHI_PACK_NO');
+ const smCodeAttr = codeValue.ATTRIBUTES?.find(attr => attr.ATT_ID === 'SM_code');
+
+ const itemData = {
+ ProjectNo: projectCode,
+ itemCode: codeValue.VALUE,
+ itemName: codeValue.DESCC || '',
+ packageCode: packageCodeAttr?.VALUE || '',
+ smCode: smCodeAttr?.VALUE || null,
+ description: null,
+ parentItemCode: null,
+ itemLevel: null,
+ deleteFlag: 'N',
+ unitOfMeasure: null,
+ steelType: null,
+ gradeMaterial: null,
+ changeDate: null,
+ baseUnitOfMeasure: null,
+ updatedAt: new Date()
+ };
+
+ // 기존 아이템 확인
+ const existingItem = await db.select()
+ .from(items)
+ .where(eq(items.itemCode, codeValue.VALUE))
+ .limit(1);
+
+ if (existingItem.length > 0) {
+ await db.update(items)
+ .set(itemData)
+ .where(eq(items.itemCode, codeValue.VALUE));
+ itemsUpdated++;
+ } else {
+ await db.insert(items).values(itemData);
+ itemsInserted++;
+ }
+
+ itemsProcessed++;
+ } catch (itemError) {
+ console.error(`아이템 ${codeValue.VALUE} 처리 중 오류:`, itemError);
+ }
+ }
+
+ console.log(`프로젝트 ${projectCode} 아이템 동기화 완료:`);
+ console.log(`- 처리된 아이템: ${itemsProcessed}개`);
+ console.log(`- 새로 삽입된 아이템: ${itemsInserted}개`);
+ console.log(`- 업데이트된 아이템: ${itemsUpdated}개`);
+
+ } catch (error) {
+ console.error(`프로젝트 ${projectCode} 아이템 동기화 중 오류:`, error);
+ throw error;
+ }
+} \ No newline at end of file