summaryrefslogtreecommitdiff
path: root/lib/sedp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sedp')
-rw-r--r--lib/sedp/get-form-tags-plant.ts933
-rw-r--r--lib/sedp/get-tags-plant.ts639
-rw-r--r--lib/sedp/sync-form.ts9
3 files changed, 1 insertions, 1580 deletions
diff --git a/lib/sedp/get-form-tags-plant.ts b/lib/sedp/get-form-tags-plant.ts
deleted file mode 100644
index 176f1b3f..00000000
--- a/lib/sedp/get-form-tags-plant.ts
+++ /dev/null
@@ -1,933 +0,0 @@
-import db from "@/db/db";
-import {
- contractItems,
- tagsPlant,
- formsPlant,formEntriesPlant,
- items,
- tagTypeClassFormMappings,
- projects,
- tagTypes,
- tagClasses,
- formMetas,
-} from "@/db/schema";
-import { eq, and, like, inArray } from "drizzle-orm";
-import { getSEDPToken } from "./sedp-token";
-import { getFormMappingsByTagTypebyProeject } from "../tags/form-mapping-service";
-
-
-interface Attribute {
- ATT_ID: string;
- VALUE: any;
- VALUE_DBL: number;
- UOM_ID: string | null;
-}
-
-interface TagEntry {
- TAG_IDX: string;
- TAG_NO: string;
- BF_TAG_NO: string;
- TAG_DESC: string;
- EP_ID: string;
- TAG_TYPE_ID: string;
- CLS_ID: string;
- ATTRIBUTES: Attribute[];
- [key: string]: any;
-}
-
-interface Column {
- key: string;
- label: string;
- type: string;
- shi?: string | null;
-}
-
-interface newRegister {
- PROJ_NO: string;
- MAP_ID: string;
- EP_ID: string;
- CATEGORY: string;
- BYPASS: boolean;
- REG_TYPE_ID: string;
- TOOL_ID: string;
- TOOL_TYPE: string;
- SCOPES: string[];
- MAP_CLS: {
- TOOL_ATT_NAME: string;
- ITEMS: ClassItmes[];
- };
- MAP_ATT: MapAttribute[];
- MAP_TMPLS: string[];
- CRTER_NO: string;
- CRTE_DTM: string;
- CHGER_NO: string;
- _id: string;
-}
-
-interface ClassItmes {
- SEDP_OBJ_CLS_ID: string;
- TOOL_VALS: string;
- ISDEFALUT: boolean;
-}
-
-interface MapAttribute {
- SEDP_ATT_ID: string;
- TOOL_ATT_NAME: string;
- KEY_YN: boolean;
- DUE_DATE: string; //"YYYY-MM-DDTHH:mm:ssZ"
- INOUT: string | null;
-}
-
-
-
-async function getNewRegisters(projectCode: string): Promise<newRegister[]> {
- try {
- // 토큰(API 키) 가져오기
- const apiKey = await getSEDPToken();
-
- const SEDP_API_BASE_URL = process.env.SEDP_API_BASE_URL || 'http://sedpwebapi.ship.samsung.co.kr/api';
-
- const response = await fetch(
- `${SEDP_API_BASE_URL}/AdapterDataMapping/GetByToolID`,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'accept': '*/*',
- 'ApiKey': apiKey,
- 'ProjectNo': projectCode
- },
- body: JSON.stringify({
- ProjectNo: projectCode,
- "TOOL_ID": "eVCP"
- })
- }
- );
-
- if (!response.ok) {
- throw new Error(`새 레지스터 요청 실패: ${response.status} ${response.statusText}`);
- }
-
- // 안전하게 JSON 파싱
- let data;
- try {
- data = await response.json();
- } catch (parseError) {
- console.error(`프로젝트 ${projectCode}의 새 레지스터 응답 파싱 실패:`, parseError);
- // 응답 내용 로깅
- const text = await response.clone().text();
- console.log(`응답 내용: ${text.substring(0, 200)}${text.length > 200 ? '...' : ''}`);
- throw new Error(`새 레지스터 응답 파싱 실패: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
- }
-
- // 결과를 배열로 변환 (단일 객체인 경우 배열로 래핑)
- let registers: newRegister[] = Array.isArray(data) ? data : [data];
-
- console.log(`프로젝트 ${projectCode}에서 ${registers.length}개의 새 레지스터를 가져왔습니다.`);
- return registers;
- } catch (error) {
- console.error(`프로젝트 ${projectCode}의 새 레지스터 가져오기 실패:`, error);
- throw error;
- }
-}
-
-
-/**
- * 태그 가져오기 서비스 함수
- * formEntries와 tags 테이블 모두에 데이터를 저장
- */
-export async function importTagsFromSEDP(
- formCode: string,
- projectCode: string,
- packageCode: string,
- progressCallback?: (progress: number) => void
-): Promise<{
- processedCount: number;
- excludedCount: number;
- totalEntries: number;
- formCreated?: boolean;
- errors?: string[];
-}> {
- try {
- // 진행 상황 보고
- if (progressCallback) progressCallback(5);
-
- // 에러 수집 배열
- const errors: string[] = [];
-
- // SEDP API에서 태그 데이터 가져오기
- const tagData = await fetchTagDataFromSEDP(projectCode, formCode);
- const newRegisters = await getNewRegisters(projectCode);
-
- const registerMatched = newRegisters.find(v => v.REG_TYPE_ID === formCode).MAP_ATT
-
-
- // 트랜잭션으로 모든 DB 작업 처리
- return await db.transaction(async (tx) => {
- // 프로젝트 정보 가져오기 (type 포함)
- const projectRecord = await tx.select({ id: projects.id, type: projects.type })
- .from(projects)
- .where(eq(projects.code, projectCode))
- .limit(1);
-
- if (!projectRecord || projectRecord.length === 0) {
- throw new Error(`Project not found for code: ${projectCode}`);
- }
-
- const projectId = projectRecord[0].id;
- const projectType = projectRecord[0].type;
-
- // 프로젝트 타입에 따라 packageCode를 찾을 ATT_ID 결정
- const packageCodeAttId = projectType === "ship" ? "CM3003" : "ME5074";
-
-
-
-
- const targetPackageCode = packageCode;
-
- // 데이터 형식 처리 - tagData의 첫 번째 키 사용
- const tableName = Object.keys(tagData)[0];
-
- if (!tableName || !tagData[tableName]) {
- throw new Error("Invalid tag data format from SEDP API");
- }
-
- const allTagEntries: TagEntry[] = tagData[tableName];
-
- if (!Array.isArray(allTagEntries) || allTagEntries.length === 0) {
- return {
- processedCount: 0,
- excludedCount: 0,
- totalEntries: 0,
- errors: ["No tag entries found in API response"]
- };
- }
-
- // packageCode로 필터링 - ATTRIBUTES에서 지정된 ATT_ID의 VALUE와 packageCode 비교
- const tagEntries = allTagEntries.filter(entry => {
- if (Array.isArray(entry.ATTRIBUTES)) {
- const packageCodeAttr = entry.ATTRIBUTES.find(attr => attr.ATT_ID === packageCodeAttId);
- if (packageCodeAttr && packageCodeAttr.VALUE === targetPackageCode) {
- return true;
- }
- }
- return false;
- });
-
- if (tagEntries.length === 0) {
- return {
- processedCount: 0,
- excludedCount: 0,
- totalEntries: allTagEntries.length,
- errors: [`No tag entries found with ${packageCodeAttId} attribute value matching packageCode: ${targetPackageCode}`]
- };
- }
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(20);
-
- // 나머지 코드는 기존과 동일...
- // form ID 가져오기 - 없으면 생성
- let formRecord = await tx.select({ id: formsPlant.id })
- .from(formsPlant)
- .where(and(
- eq(formsPlant.formCode, formCode),
- eq(formsPlant.projectCode, projectCode),
- eq(formsPlant.packageCode, packageCode)
- ))
- .limit(1);
-
- let formCreated = false;
-
- // form이 없으면 생성
- if (!formRecord || formRecord.length === 0) {
- console.log(`[IMPORT TAGS] Form ${formCode} not found, attempting to create...`);
-
- // 첫 번째 태그의 정보를 사용해서 form mapping을 찾습니다
- // 모든 태그가 같은 formCode를 사용한다고 가정
- if (tagEntries.length > 0) {
- const firstTag = tagEntries[0];
-
- // tagType 조회 (TAG_TYPE_ID -> description)
- let tagTypeDescription = firstTag.TAG_TYPE_ID; // 기본값
- if (firstTag.TAG_TYPE_ID) {
- const tagTypeRecord = await tx.select({ description: tagTypes.description })
- .from(tagTypes)
- .where(and(
- eq(tagTypes.code, firstTag.TAG_TYPE_ID),
- eq(tagTypes.projectId, projectId)
- ))
- .limit(1);
-
- if (tagTypeRecord && tagTypeRecord.length > 0) {
- tagTypeDescription = tagTypeRecord[0].description;
- }
- }
-
- // tagClass 조회 (CLS_ID -> label)
- let tagClassLabel = firstTag.CLS_ID; // 기본값
- if (firstTag.CLS_ID) {
- const tagClassRecord = await tx.select({ id: tagClasses.id, label: tagClasses.label })
- .from(tagClasses)
- .where(and(
- eq(tagClasses.code, firstTag.CLS_ID),
- eq(tagClasses.projectId, projectId)
- ))
- .limit(1);
-
- if (tagClassRecord && tagClassRecord.length > 0) {
- tagClassLabel = tagClassRecord[0].label;
- }
- }
-
- // 태그 타입에 따른 폼 정보 가져오기
- const allFormMappings = await getFormMappingsByTagTypebyProeject(
- projectId,
- );
-
- // 현재 formCode와 일치하는 매핑 찾기
- const targetFormMapping = allFormMappings.find(mapping => mapping.formCode === formCode);
-
- if (targetFormMapping) {
- console.log(`[IMPORT TAGS] Found form mapping for ${formCode}, creating form...`);
-
- // form 생성
- const insertResult = await tx
- .insert(formsPlant)
- .values({
- projectCode,
- packageCode,
- formCode: targetFormMapping.formCode,
- formName: targetFormMapping.formName,
- eng: true, // ENG 모드에서 가져오는 것이므로 eng: true
- im: targetFormMapping.ep === "IMEP" ? true : false
- })
- .returning({ id: formsPlant.id });
-
- formRecord = insertResult;
- formCreated = true;
-
- console.log(`[IMPORT TAGS] Successfully created form:`, insertResult[0]);
- } else {
- console.log(`[IMPORT TAGS] No form mapping found for formCode: ${formCode}`);
- console.log(`[IMPORT TAGS] Available mappings:`, allFormMappings.map(m => m.formCode));
- throw new Error(`Form ${formCode} not found and no mapping available for tag type ${tagTypeDescription}`);
- }
- } else {
- throw new Error(`Form not found for formCode: ${formCode} and, and no tags to derive form mapping`);
- }
- } else {
- console.log(`[IMPORT TAGS] Found existing form:`, formRecord[0].id);
-
- // 기존 form이 있는 경우 eng와 im 필드를 체크하고 업데이트
- const existingForm = await tx.select({
- eng: formsPlant.eng,
- im: formsPlant.im
- })
- .from(formsPlant)
- .where(eq(formsPlant.id, formRecord[0].id))
- .limit(1);
-
- if (existingForm.length > 0) {
- // form mapping 정보 가져오기 (im 필드 업데이트를 위해)
- let shouldUpdateIm = false;
- let targetImValue = false;
-
- // 첫 번째 태그의 정보를 사용해서 form mapping을 확인
- if (tagEntries.length > 0) {
- const firstTag = tagEntries[0];
-
- // tagType 조회
- let tagTypeDescription = firstTag.TAG_TYPE_ID;
- if (firstTag.TAG_TYPE_ID) {
- const tagTypeRecord = await tx.select({ description: tagTypes.description })
- .from(tagTypes)
- .where(and(
- eq(tagTypes.code, firstTag.TAG_TYPE_ID),
- eq(tagTypes.projectId, projectId)
- ))
- .limit(1);
-
- if (tagTypeRecord && tagTypeRecord.length > 0) {
- tagTypeDescription = tagTypeRecord[0].description;
- }
- }
-
- // tagClass 조회
- let tagClassLabel = firstTag.CLS_ID;
- if (firstTag.CLS_ID) {
- const tagClassRecord = await tx.select({ id: tagClasses.id, label: tagClasses.label })
- .from(tagClasses)
- .where(and(
- eq(tagClasses.code, firstTag.CLS_ID),
- eq(tagClasses.projectId, projectId)
- ))
- .limit(1);
-
- if (tagClassRecord && tagClassRecord.length > 0) {
- tagClassLabel = tagClassRecord[0].label;
- }
- }
-
- // form mapping 정보 가져오기
- const allFormMappings = await getFormMappingsByTagTypebyProeject(
- projectId,
- );
-
- // 현재 formCode와 일치하는 매핑 찾기
- const targetFormMapping = allFormMappings.find(mapping => mapping.formCode === formCode);
-
- if (targetFormMapping) {
- targetImValue = targetFormMapping.ep === "IMEP";
- shouldUpdateIm = existingForm[0].im !== targetImValue;
- }
- }
-
- // 업데이트할 필드들 준비
- const updates: any = {};
- let hasUpdates = false;
-
- // eng 필드 체크
- if (existingForm[0].eng !== true) {
- updates.eng = true;
- hasUpdates = true;
- }
-
- // im 필드 체크
- if (shouldUpdateIm) {
- updates.im = targetImValue;
- hasUpdates = true;
- }
-
- // 업데이트 실행
- if (hasUpdates) {
- await tx
- .update(formsPlant)
- .set(updates)
- .where(eq(formsPlant.id, formRecord[0].id));
-
- console.log(`[IMPORT TAGS] Form ${formRecord[0].id} updated with:`, updates);
- }
- }
- }
-
- const formId = formRecord[0].id;
-
- // 나머지 처리 로직은 기존과 동일...
- // (양식 메타데이터 가져오기, 태그 처리 등)
-
- // 양식 메타데이터 가져오기
- const formMetaRecord = await tx.select({ columns: formMetas.columns })
- .from(formMetas)
- .where(and(
- eq(formMetas.projectId, projectId),
- eq(formMetas.formCode, formCode)
- ))
- .limit(1);
-
- if (!formMetaRecord || formMetaRecord.length === 0) {
- throw new Error(`Form metadata not found for formCode: ${formCode} and projectId: ${projectId}`);
- }
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(30);
-
- // 컬럼 정보 파싱
- const columnsJSON: Column[] = (formMetaRecord[0].columns);
-
- // 현재 formEntries 데이터 가져오기
- const existingEntries = await tx.select({ id: formEntriesPlant.id, data: formEntriesPlant.data })
- .from(formEntriesPlant)
- .where(and(
- eq(formEntriesPlant.formCode, formCode),
- eq(formEntriesPlant.projectCode, projectCode),
- eq(formEntriesPlant.packageCode, packageCode)
- ));
-
- // 기존 tags 데이터 가져오기
- const existingTags = await tx.select()
- .from(tagsPlant)
- .where(and(
- eq(tagsPlant.projectCode, projectCode),
- eq(tagsPlant.packageCode, packageCode),
- )
- );
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(50);
-
- // 기존 데이터를 맵으로 변환
- const existingTagMap = new Map();
- const existingTagsMap = new Map();
-
- existingEntries.forEach(entry => {
- const data = entry.data as any[];
- data.forEach(item => {
- if (item.TAG_IDX) {
- existingTagMap.set(item.TAG_IDX, {
- entryId: entry.id,
- data: item
- });
- }
- });
- });
-
- existingTags.forEach(tag => {
- existingTagsMap.set(tag.tagIdx, tag);
- });
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(60);
-
- // 처리 결과 카운터
- let processedCount = 0;
- let excludedCount = 0;
-
- // 새로운 태그 데이터와 업데이트할 데이터 준비
- const newTagData: any[] = [];
- const upsertTagRecords: any[] = []; // 새로 추가되거나 업데이트될 태그들
- const updateData: { entryId: number, tagNo: string, updates: any }[] = [];
-
- // SEDP 태그 데이터 처리
- for (const tagEntry of tagEntries) {
- try {
- if (!tagEntry.TAG_IDX) {
- excludedCount++;
- errors.push(`Missing TAG_NO in tag entry`);
- continue;
- }
-
- // tagType 조회 (TAG_TYPE_ID -> description)
- let tagTypeDescription = tagEntry.TAG_TYPE_ID; // 기본값
- if (tagEntry.TAG_TYPE_ID) {
- const tagTypeRecord = await tx.select({ description: tagTypes.description })
- .from(tagTypes)
- .where(and(
- eq(tagTypes.code, tagEntry.TAG_TYPE_ID),
- eq(tagTypes.projectId, projectId)
- ))
- .limit(1);
-
- if (tagTypeRecord && tagTypeRecord.length > 0) {
- tagTypeDescription = tagTypeRecord[0].description;
- }
- }
-
- // tagClass 조회 (CLS_ID -> label)
- let tagClassLabel = tagEntry.CLS_ID; // 기본값
- let tagClassId = null; // 기본값
- if (tagEntry.CLS_ID) {
- const tagClassRecord = await tx.select({ id: tagClasses.id, label: tagClasses.label })
- .from(tagClasses)
- .where(and(
- eq(tagClasses.code, tagEntry.CLS_ID),
- eq(tagClasses.projectId, projectId)
- ))
- .limit(1);
-
- if (tagClassRecord && tagClassRecord.length > 0) {
- tagClassLabel = tagClassRecord[0].label;
- tagClassId = tagClassRecord[0].id;
- }
- }
-
- const packageCode = projectType === "ship" ? tagEntry.ATTRIBUTES.find(v => v.ATT_ID === "CM3003")?.VALUE : tagEntry.ATTRIBUTES.find(v => v.ATT_ID === "ME5074")?.VALUE
-
- // 기본 태그 데이터 객체 생성 (formEntries용)
- const tagObject: any = {
- TAG_IDX: tagEntry.TAG_IDX, // SEDP 고유 식별자
- TAG_NO: tagEntry.TAG_NO,
- TAG_DESC: tagEntry.TAG_DESC || "",
- CLS_ID: tagEntry.CLS_ID || "",
- VNDRCD: vendorRecord[0].vendorCode,
- VNDRNM_1: vendorRecord[0].vendorName,
- status: "From S-EDP", // SEDP에서 가져온 데이터임을 표시
- source: "S-EDP", // 태그 출처 (불변) - S-EDP에서 가져옴
- ...(projectType === "ship" ? { CM3003: packageCode } : { ME5074: packageCode })
- }
-
- let latestDueDate: Date | null = null;
-
- // tags 테이블용 데이터 (UPSERT용)
- const tagRecord = {
- projectCode,
- packageCode,
- formId: formId,
- tagIdx: tagEntry.TAG_IDX, // SEDP 고유 식별자
- tagNo: tagEntry.TAG_NO,
- tagType: tagTypeDescription || "",
- class: tagClassLabel,
- tagClassId: tagClassId,
- description: tagEntry.TAG_DESC || null,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- // ATTRIBUTES 필드에서 shi=true인 컬럼의 값 추출
- if (Array.isArray(tagEntry.ATTRIBUTES)) {
- for (const attr of tagEntry.ATTRIBUTES) {
- const columnInfo = columnsJSON.find(col => col.key === attr.ATT_ID);
- if (columnInfo && (columnInfo.shi === "BOTH" || columnInfo.shi === "OUT" || columnInfo.shi === null)) {
- if (columnInfo.type === "NUMBER") {
- if (attr.VALUE !== undefined && attr.VALUE !== null) {
- if (typeof attr.VALUE === 'string') {
- const numberMatch = attr.VALUE.match(/(-?\d+(\.\d+)?)/);
- if (numberMatch) {
- tagObject[attr.ATT_ID] = parseFloat(numberMatch[0]);
- } else {
- const parsed = parseFloat(attr.VALUE);
- if (!isNaN(parsed)) {
- tagObject[attr.ATT_ID] = parsed;
- }
- }
- } else if (typeof attr.VALUE === 'number') {
- tagObject[attr.ATT_ID] = attr.VALUE;
- }
- }
- } else if (attr.VALUE !== null && attr.VALUE !== undefined) {
- tagObject[attr.ATT_ID] = attr.VALUE;
- }
- }
-
- // registerMatched에서 해당 SEDP_ATT_ID의 DUE_DATE 찾기
- if (registerMatched && Array.isArray(registerMatched)) {
- const matchedAttribute = registerMatched.find(
- regAttr => regAttr.SEDP_ATT_ID === attr.ATT_ID
- );
-
- if (matchedAttribute && matchedAttribute.DUE_DATE) {
- try {
- const dueDate = new Date(matchedAttribute.DUE_DATE);
-
- // 유효한 날짜인지 확인
- if (!isNaN(dueDate.getTime())) {
- // 첫 번째 DUE_DATE이거나 현재까지 찾은 것보다 더 늦은 날짜인 경우 업데이트
- if (!latestDueDate || dueDate > latestDueDate) {
- latestDueDate = dueDate;
- }
- }
- } catch (dateError) {
- console.warn(`Invalid DUE_DATE format for ${attr.ATT_ID}: ${matchedAttribute.DUE_DATE}`);
- }
- }
- }
-
- }
- }
-
- if (latestDueDate) {
- // ISO 형식의 문자열로 저장 (또는 원하는 형식으로 변경 가능)
- tagObject.DUE_DATE = latestDueDate.toISOString();
-
- // 또는 YYYY-MM-DD 형식을 원한다면:
- // tagObject.DUE_DATE = latestDueDate.toISOString().split('T')[0];
-
- // 또는 원본 형식 그대로 유지하려면:
- // tagObject.DUE_DATE = latestDueDate.toISOString().replace('Z', '');
- }
-
-
-
- // 기존 태그가 있는지 확인하고 처리
- const existingTag = existingTagMap.get(tagEntry.TAG_IDX);
-
- if (existingTag) {
- // 기존 태그가 있으면 formEntries 업데이트 데이터 준비
- const updates: any = {};
- let hasUpdates = false;
-
- for (const key of Object.keys(tagObject)) {
- if (key === "TAG_IDX") continue;
-
- if (key === "TAG_NO" && tagObject[key] !== existingTag.data[key]) {
- updates[key] = tagObject[key];
- hasUpdates = true;
- continue;
- }
-
-
- if (key === "TAG_DESC" && tagObject[key] !== existingTag.data[key]) {
- updates[key] = tagObject[key];
- hasUpdates = true;
- continue;
- }
-
- if (key === "status" && tagObject[key] !== existingTag.data[key]) {
- updates[key] = tagObject[key];
- hasUpdates = true;
- continue;
- }
- if (key === "CLS_ID" && tagObject[key] !== existingTag.data[key]) {
- updates[key] = tagObject[key];
- hasUpdates = true;
- continue;
- }
-
- if (key === "DUE_DATE" && tagObject[key] !== existingTag.data[key]) {
- updates[key] = tagObject[key];
- hasUpdates = true;
- continue;
- }
-
- const columnInfo = columnsJSON.find(col => col.key === key);
- if (columnInfo && (columnInfo.shi === "BOTH" || columnInfo.shi === "OUT" || columnInfo.shi === null)) {
- if (existingTag.data[key] !== tagObject[key]) {
- updates[key] = tagObject[key];
- hasUpdates = true;
- }
- }
- }
-
- if (hasUpdates) {
- updateData.push({
- entryId: existingTag.entryId,
- tagIdx: tagEntry.TAG_IDX, // TAG_IDX로 변경
- updates
- });
- }
- } else {
- // 기존 태그가 없으면 새로 추가
- newTagData.push(tagObject);
- }
-
- // tags 테이블에는 항상 upsert (새로 추가되거나 업데이트)
- upsertTagRecords.push(tagRecord);
-
- processedCount++;
- } catch (error) {
- excludedCount++;
- errors.push(`Error processing tag ${tagEntry.TAG_IDX || 'unknown'}: ${error}`);
- }
- }
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(80);
-
- // formEntries 업데이트 실행
- // entryId별로 업데이트를 그룹화
- const updatesByEntryId = new Map();
-
- for (const update of updateData) {
- if (!updatesByEntryId.has(update.entryId)) {
- updatesByEntryId.set(update.entryId, []);
- }
- updatesByEntryId.get(update.entryId).push(update);
- }
-
- // 그룹화된 업데이트를 처리
- for (const [entryId, updates] of updatesByEntryId) {
- try {
- const entry = existingEntries.find(e => e.id === entryId);
- if (!entry) continue;
-
- const data = entry.data as any[];
-
- // 해당 entryId의 모든 업데이트를 한 번에 적용
- const updatedData = data.map(item => {
- let updatedItem = { ...item };
-
- // 현재 item에 적용할 모든 업데이트를 찾아서 적용
- for (const update of updates) {
- if (item.TAG_IDX === update.tagIdx) {
- updatedItem = { ...updatedItem, ...update.updates };
- }
- }
-
- return updatedItem;
- });
-
- // entryId별로 한 번만 DB 업데이트
- await tx.update(formEntriesPlant)
- .set({
- data: updatedData,
- updatedAt: new Date()
- })
- .where(eq(formEntriesPlant.id, entryId));
-
- } catch (error) {
- const tagNos = updates.map(u => u.tagNo || u.tagIdx).join(', ');
- errors.push(`Error updating formEntry ${entryId} for tags ${tagNos}: ${error}`);
- }
- }
-
- // 새 태그 추가 (formEntriesPlant)
- if (newTagData.length > 0) {
- if (existingEntries.length > 0) {
- const firstEntry = existingEntries[0];
- const existingData = firstEntry.data as any[];
- const updatedData = [...existingData, ...newTagData];
-
- await tx.update(formEntriesPlant)
- .set({
- data: updatedData,
- updatedAt: new Date()
- })
- .where(eq(formEntriesPlant.id, firstEntry.id));
- } else {
- await tx.insert(formEntriesPlant)
- .values({
- formCode,
- projectCode,
- packageCode,
- data: newTagData,
- createdAt: new Date(),
- updatedAt: new Date()
- });
- }
- }
-
- // tags 테이블 처리 (INSERT + UPDATE 분리)
- if (upsertTagRecords.length > 0) {
- const newTagRecords: any[] = [];
- const updateTagRecords: { tagId: number, updates: any }[] = [];
-
- // 각 태그를 확인하여 신규/업데이트 분류
- for (const tagRecord of upsertTagRecords) {
- const existingTagRecord = existingTagsMap.get(tagRecord.tagIdx);
-
- if (existingTagRecord) {
- // 기존 태그가 있으면 업데이트 준비
- const tagUpdates: any = {};
- let hasTagUpdates = false;
-
- // tagNo도 업데이트 가능 (편집된 경우)
- if (existingTagRecord.tagNo !== tagRecord.tagNo) {
- tagUpdates.tagNo = tagRecord.tagNo;
- hasTagUpdates = true;
- }
-
- if (existingTagRecord.tagType !== tagRecord.tagType) {
- tagUpdates.tagType = tagRecord.tagType;
- hasTagUpdates = true;
- }
- if (existingTagRecord.class !== tagRecord.class) {
- tagUpdates.class = tagRecord.class;
- hasTagUpdates = true;
- }
- if (existingTagRecord.tagClassId !== tagRecord.tagClassId) {
- tagUpdates.tagClassId = tagRecord.tagClassId;
- hasTagUpdates = true;
- }
-
- if (existingTagRecord.description !== tagRecord.description) {
- tagUpdates.description = tagRecord.description;
- hasTagUpdates = true;
- }
- if (existingTagRecord.formId !== tagRecord.formId) {
- tagUpdates.formId = tagRecord.formId;
- hasTagUpdates = true;
- }
-
- if (hasTagUpdates) {
- updateTagRecords.push({
- tagId: existingTagRecord.id,
- updates: { ...tagUpdates, updatedAt: new Date() }
- });
- }
- } else {
- // 새로운 태그
- newTagRecords.push(tagRecord);
- }
- }
-
- // 새 태그 삽입
- if (newTagRecords.length > 0) {
- try {
- await tx.insert(tagsPlant)
- .values(newTagRecords)
- .onConflictDoNothing({
- target: [tagsPlant.projectCode,tagsPlant.packageCode, tagsPlant.tagIdx]
- });
- } catch (error) {
- // 개별 삽입으로 재시도
- for (const tagRecord of newTagRecords) {
- try {
- await tx.insert(tagsPlant)
- .values(tagRecord)
- .onConflictDoNothing({
- target: [tagsPlant.projectCode,tagsPlant.packageCode, tagsPlant.tagIdx]
- });
- } catch (individualError) {
- errors.push(`Error inserting tag ${tagRecord.tagIdx}: ${individualError}`);
- }
- }
- }
- }
-
- // 기존 태그 업데이트
- for (const update of updateTagRecords) {
- try {
- await tx.update(tagsPlant)
- .set(update.updates)
- .where(eq(tagsPlant.id, update.tagId));
- } catch (error) {
- errors.push(`Error updating tag record ${update.tagId}: ${error}`);
- }
- }
- }
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(100);
-
- // 최종 결과 반환
- return {
- processedCount,
- excludedCount,
- totalEntries: tagEntries.length,
- formCreated,
- errors: errors.length > 0 ? errors : undefined
- };
- });
-
- } catch (error: any) {
- console.error("Tag import error:", error);
- throw error;
- }
-}
-/**
- * SEDP API에서 태그 데이터 가져오기
- *
- * @param projectCode 프로젝트 코드
- * @param formCode 양식 코드
- * @returns API 응답 데이터
- */
-async function fetchTagDataFromSEDP(projectCode: string, formCode: string): Promise<any> {
- try {
- // Get the token
- const apiKey = await getSEDPToken();
-
- // Define the API base URL
- const SEDP_API_BASE_URL = process.env.SEDP_API_BASE_URL || 'http://sedpwebapi.ship.samsung.co.kr/api';
-
- // Make the API call
- const response = await fetch(
- `${SEDP_API_BASE_URL}/Data/GetPubData`,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'accept': '*/*',
- 'ApiKey': apiKey,
- 'ProjectNo': projectCode
- },
- body: JSON.stringify({
- ProjectNo: projectCode,
- REG_TYPE_ID: formCode,
- // TODO: 이창국 프로 요청으로, ContainDeleted: true로 변경예정, EDP에서 삭제된 데이터도 가져올 수 있어야 한다고 함.
- // 삭제된 게 들어오면 eVCP내에서 지우거나, 비활성화 하는 등의 처리를 해야 할 걸로 보임
- ContainDeleted: false
- })
- }
- );
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`SEDP API request failed: ${response.status} ${response.statusText} - ${errorText}`);
- }
-
- const data = await response.json();
- return data;
- } catch (error: any) {
- console.error('Error calling SEDP API:', error);
- throw new Error(`Failed to fetch data from SEDP API: ${error.message || 'Unknown error'}`);
- }
-} \ No newline at end of file
diff --git a/lib/sedp/get-tags-plant.ts b/lib/sedp/get-tags-plant.ts
deleted file mode 100644
index d1957db4..00000000
--- a/lib/sedp/get-tags-plant.ts
+++ /dev/null
@@ -1,639 +0,0 @@
-import db from "@/db/db";
-import {
- tagsPlant,
- formsPlant,
- formEntriesPlant,
- items,
- tagTypeClassFormMappings,
- projects,
- tagTypes,
- tagClasses,
-} from "@/db/schema";
-import { eq, and, like, inArray } from "drizzle-orm";
-import { revalidateTag } from "next/cache"; // 추가
-import { getSEDPToken } from "./sedp-token";
-
-/**
- * 태그 가져오기 서비스 함수
- * contractItemId(packageId)를 기반으로 외부 시스템에서 태그 데이터를 가져와 DB에 저장
- * TAG_IDX를 기준으로 태그를 식별합니다.
- *
- * @param projectCode 계약 아이템 ID (contractItemId)
- * @param packageCode 계약 아이템 ID (contractItemId)
- * @param progressCallback 진행 상황을 보고하기 위한 콜백 함수
- * @returns 처리 결과 정보 (처리된 태그 수, 오류 목록 등)
- */
-export async function importTagsFromSEDP(
- projectCode: string,
- packageCode: string,
- progressCallback?: (progress: number) => void,
- mode?: string
-): Promise<{
- processedCount: number;
- excludedCount: number;
- totalEntries: number;
- errors?: string[];
-}> {
- try {
- // 진행 상황 보고
- if (progressCallback) progressCallback(5);
-
- const project = await db.query.projects.findFirst({
- where: eq(projects.code, projectCode),
- columns: {
- id: true
- }
- });
-
-
- // 프로젝트 ID 획득
- const projectId = project?.id;
-
- // Step 1-2: Get the item using itemId from contractItem
- const item = await db.query.items.findFirst({
- where: and(eq(items.ProjectNo, projectCode), eq(items.packageCode, packageCode))
- });
-
- if (!item) {
- throw new Error(`Item with ID ${item?.id} not found`);
- }
-
- const itemCode = item.itemCode;
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(10);
-
- // 기본 매핑 검색 - 모든 모드에서 사용
- const baseMappings = await db.query.tagTypeClassFormMappings.findMany({
- where: and(
- like(tagTypeClassFormMappings.remark, `%${itemCode}%`),
- eq(tagTypeClassFormMappings.projectId, projectId)
- )
- });
-
- if (baseMappings.length === 0) {
- throw new Error(`No mapping found for item code ${itemCode}`);
- }
-
- // Step 2: Find the mapping entries - 모드에 따라 다른 조건 적용
- let mappings = [];
-
- if (mode === 'IM') {
- // IM 모드일 때는 먼저 SEDP에서 태그 데이터를 가져와 TAG_TYPE_ID 리스트 확보
-
- // 프로젝트 코드 가져오기
- const project = await db.query.projects.findFirst({
- where: eq(projects.id, projectId)
- });
-
- if (!project) {
- throw new Error(`Project with ID ${projectId} not found`);
- }
-
- // 각 매핑의 formCode에 대해 태그 데이터 조회
- const tagTypeIds = new Set<string>();
-
- for (const mapping of baseMappings) {
- try {
- // SEDP에서 태그 데이터 가져오기
- const tagData = await fetchTagDataFromSEDP(project.code, mapping.formCode);
-
- // 첫 번째 키를 테이블 이름으로 사용
- const tableName = Object.keys(tagData)[0];
- const tagEntries = tagData[tableName];
-
- if (Array.isArray(tagEntries)) {
- // 모든 태그에서 TAG_TYPE_ID 수집
- for (const entry of tagEntries) {
- if (entry.TAG_TYPE_ID && entry.TAG_TYPE_ID !== "") {
- tagTypeIds.add(entry.TAG_TYPE_ID);
- }
- }
- }
- } catch (error) {
- console.error(`Error fetching tag data for formCode ${mapping.formCode}:`, error);
- }
- }
-
- if (tagTypeIds.size === 0) {
- throw new Error('No valid TAG_TYPE_ID found in SEDP tag data');
- }
-
- // 수집된 TAG_TYPE_ID로 tagTypes에서 정보 조회
- const tagTypeInfo = await db.query.tagTypes.findMany({
- where: and(
- inArray(tagTypes.code, Array.from(tagTypeIds)),
- eq(tagTypes.projectId, projectId)
- )
- });
-
- if (tagTypeInfo.length === 0) {
- throw new Error('No matching tag types found for the collected TAG_TYPE_IDs');
- }
-
- // 태그 타입 설명 수집
- const tagLabels = tagTypeInfo.map(tt => tt.description);
-
- // IM 모드에 맞는 매핑 조회 - ep가 "IMEP"인 항목만
- mappings = await db.query.tagTypeClassFormMappings.findMany({
- where: and(
- inArray(tagTypeClassFormMappings.tagTypeLabel, tagLabels),
- eq(tagTypeClassFormMappings.projectId, projectId),
- eq(tagTypeClassFormMappings.ep, "IMEP")
- )
- });
-
- } else {
- // ENG 모드 또는 기본 모드일 때 - 기본 매핑 사용
- mappings = [...baseMappings];
-
- // ENG 모드에서는 ep 필드가 "IMEP"가 아닌 매핑만 필터링
- if (mode === 'ENG') {
- mappings = mappings.filter(mapping => mapping.ep !== "IMEP");
- }
- }
-
- // 매핑이 없는 경우 모드에 따라 다른 오류 메시지 사용
- if (mappings.length === 0) {
- if (mode === 'IM') {
- throw new Error('No suitable mappings found for IM mode');
- } else {
- throw new Error(`No mapping found for item code ${itemCode}`);
- }
- }
-
- // 진행 상황 보고
- if (progressCallback) progressCallback(15);
-
- // 결과 누적을 위한 변수들 초기화
- let totalProcessedCount = 0;
- let totalExcludedCount = 0;
- let totalEntriesCount = 0;
- const allErrors: string[] = [];
-
- // 각 매핑에 대해 처리
- for (let mappingIndex = 0; mappingIndex < mappings.length; mappingIndex++) {
- const mapping = mappings[mappingIndex];
-
- // Step 3: Get the project code
- const project = await db.query.projects.findFirst({
- where: eq(projects.id, mapping.projectId)
- });
-
- if (!project) {
- allErrors.push(`Project with ID ${mapping.projectId} not found`);
- continue; // 다음 매핑으로 진행
- }
-
- // IM 모드에서는 baseMappings에서 같은 formCode를 가진 매핑을 찾음
- let formCode = mapping.formCode;
- if (mode === 'IM') {
- // baseMapping에서 동일한 formCode를 가진 매핑 찾기
- const originalMapping = baseMappings.find(
- baseMapping => baseMapping.formCode === mapping.formCode
- );
-
- // 찾았으면 해당 formCode 사용, 못 찾았으면 현재 매핑의 formCode 유지
- if (originalMapping) {
- formCode = originalMapping.formCode;
- }
- }
-
- // 진행 상황 보고 - 매핑별 진행률 조정
- if (progressCallback) {
- const baseProgress = 15;
- const mappingProgress = Math.floor(15 * (mappingIndex + 1) / mappings.length);
- progressCallback(baseProgress + mappingProgress);
- }
-
- // Step 4: Find the form ID
- const form = await db.query.formsPlant.findFirst({
- where: and(
- eq(formsPlant.projectCode, projectCode),
- eq(formsPlant.packageCode, packageCode),
- eq(formsPlant.formCode, formCode)
- )
- });
-
- let formId;
-
- // If form doesn't exist, create it
- if (!form) {
- // 폼이 없는 경우 새로 생성 - 모드에 따른 필드 설정
- const insertValues: any = {
- projectCode,
- packageCode,
- formCode: formCode,
- formName: mapping.formName
- };
-
- // 모드 정보가 있으면 해당 필드 설정
- if (mode) {
- if (mode === "ENG") {
- insertValues.eng = true;
- } else if (mode === "IM") {
- insertValues.im = true;
- if (mapping.remark && mapping.remark.includes("VD_")) {
- insertValues.eng = true;
- }
- }
- }
-
- const insertResult = await db.insert(formsPlant).values(insertValues).returning({ id: formsPlant.id });
-
- if (insertResult.length === 0) {
- allErrors.push(`Failed to create form record for formCode ${formCode}`);
- continue; // 다음 매핑으로 진행
- }
-
- formId = insertResult[0].id;
- } else {
- // 폼이 이미 존재하는 경우 - 필요시 모드 필드 업데이트
- formId = form.id;
-
- if (mode) {
- let shouldUpdate = false;
- const updateValues: any = {};
-
- if (mode === "ENG" && form.eng !== true) {
- updateValues.eng = true;
- shouldUpdate = true;
- } else if (mode === "IM" && form.im !== true) {
- updateValues.im = true;
- shouldUpdate = true;
- }
-
- if (shouldUpdate) {
- await db.update(formsPlant)
- .set({
- ...updateValues,
- updatedAt: new Date()
- })
- .where(eq(formsPlant.id, formId));
-
- console.log(`Updated form ${formId} with ${mode} mode enabled`);
- }
- }
- }
-
- // 진행 상황 보고 - 매핑별 진행률 조정
- if (progressCallback) {
- const baseProgress = 30;
- const mappingProgress = Math.floor(20 * (mappingIndex + 1) / mappings.length);
- progressCallback(baseProgress + mappingProgress);
- }
-
- try {
- // Step 5: Call the external API to get tag data
- const tagData = await fetchTagDataFromSEDP(projectCode, baseMappings[0].formCode);
-
- // 진행 상황 보고
- if (progressCallback) {
- const baseProgress = 50;
- const mappingProgress = Math.floor(10 * (mappingIndex + 1) / mappings.length);
- progressCallback(baseProgress + mappingProgress);
- }
-
- // Step 6: Process the data and insert into the tags table
- let processedCount = 0;
- let excludedCount = 0;
-
- // Get the first key from the response as the table name
- const tableName = Object.keys(tagData)[0];
- const tagEntries = tagData[tableName];
-
- if (!Array.isArray(tagEntries) || tagEntries.length === 0) {
- allErrors.push(`No tag data found in the API response for formCode ${baseMappings[0].formCode}`);
- continue; // 다음 매핑으로 진행
- }
-
- const entriesCount = tagEntries.length;
- totalEntriesCount += entriesCount;
-
- // formEntries를 위한 데이터 수집
- const newTagsForFormEntry: Array<{
- TAG_IDX: string; // 변경: TAG_NO → TAG_IDX
- TAG_NO?: string; // TAG_NO도 함께 저장 (편집 가능한 필드)
- TAG_DESC: string | null;
- status: string;
- [key: string]: any;
- }> = [];
-
- const registerResponse = await fetch(
- `${SEDP_API_BASE_URL}/Register/GetByID`,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'accept': '*/*',
- 'ApiKey': apiKey,
- 'ProjectNo': projectCode
- },
- body: JSON.stringify({
- ProjectNo: projectCode,
- TYPE_ID: baseMappings[0].formCode, // 또는 mapping.formCode
- ContainDeleted: false
- })
- }
- )
-
- if (!registerResponse.ok) {
- allErrors.push(`Failed to fetch register details for ${baseMappings[0].formCode}`)
- continue
- }
-
- const registerDetail: Register = await registerResponse.json()
-
- // ✅ MAP_ATT에서 허용된 ATT_ID 목록 추출
- const allowedAttIds = new Set<string>()
- if (Array.isArray(registerDetail.MAP_ATT)) {
- for (const mapAttr of registerDetail.MAP_ATT) {
- if (mapAttr.ATT_ID) {
- allowedAttIds.add(mapAttr.ATT_ID)
- }
- }
- }
-
-
- // Process each tag entry
- for (let i = 0; i < tagEntries.length; i++) {
- try {
- const entry = tagEntries[i];
-
- // TAG_IDX가 없는 경우 제외 (변경: TAG_NO → TAG_IDX 체크)
- if (!entry.TAG_IDX) {
- excludedCount++;
- totalExcludedCount++;
-
- // 주기적으로 진행 상황 보고 (건너뛰어도 진행률은 업데이트)
- if (progressCallback && (i % 10 === 0 || i === tagEntries.length - 1)) {
- const baseProgress = 60;
- const entryProgress = Math.floor(30 * ((mappingIndex * entriesCount + i) / (mappings.length * entriesCount)));
- progressCallback(baseProgress + entryProgress);
- }
-
- continue; // 이 항목은 건너뜀
- }
-
- const attributes: Record<string, string> = {}
- if (Array.isArray(entry.ATTRIBUTES)) {
- for (const attr of entry.ATTRIBUTES) {
- // MAP_ATT에 정의된 ATT_ID만 포함
- if (attr.ATT_ID && allowedAttIds.has(attr.ATT_ID)) {
- if (attr.VALUE !== null && attr.VALUE !== undefined) {
- attributes[attr.ATT_ID] = String(attr.VALUE)
- }
- }
- }
- }
-
-
- // TAG_TYPE_ID가 null이거나 빈 문자열인 경우 제외
- if (entry.TAG_TYPE_ID === null || entry.TAG_TYPE_ID === "") {
- excludedCount++;
- totalExcludedCount++;
-
- // 주기적으로 진행 상황 보고 (건너뛰어도 진행률은 업데이트)
- if (progressCallback && (i % 10 === 0 || i === tagEntries.length - 1)) {
- const baseProgress = 60;
- const entryProgress = Math.floor(30 * ((mappingIndex * entriesCount + i) / (mappings.length * entriesCount)));
- progressCallback(baseProgress + entryProgress);
- }
-
- continue; // 이 항목은 건너뜀
- }
-
- // Get tag type description
- const tagType = await db.query.tagTypes.findFirst({
- where: and(
- eq(tagTypes.code, entry.TAG_TYPE_ID),
- eq(tagTypes.projectId, mapping.projectId)
- )
- });
-
- // Get tag class label
- const tagClass = await db.query.tagClasses.findFirst({
- where: and(
- eq(tagClasses.code, entry.CLS_ID),
- eq(tagClasses.projectId, mapping.projectId)
- )
- });
-
- // Insert or update the tag - tagIdx 필드 추가
- await db.insert(tagsPlant).values({
- projectCode,
- packageCode,
- formId: formId,
- tagIdx: entry.TAG_IDX,
- tagNo: entry.TAG_NO || entry.TAG_IDX,
- tagType: tagType?.description || entry.TAG_TYPE_ID,
- tagClassId: tagClass?.id,
- class: tagClass?.label || entry.CLS_ID,
- description: entry.TAG_DESC,
- attributes: attributes, // JSONB로 저장
- }).onConflictDoUpdate({
- target: [tagsPlant.projectCode, tagsPlant.packageCode, tagsPlant.tagIdx],
- set: {
- formId: formId,
- tagNo: entry.TAG_NO || entry.TAG_IDX,
- tagType: tagType?.description || entry.TAG_TYPE_ID,
- class: tagClass?.label || entry.CLS_ID,
- description: entry.TAG_DESC,
- attributes: attributes, // JSONB 업데이트
- updatedAt: new Date()
- }
- })
- // formEntries용 데이터 수집
- const tagDataForFormEntry = {
- TAG_IDX: entry.TAG_IDX, // 변경: TAG_NO → TAG_IDX
- TAG_NO: entry.TAG_NO || entry.TAG_IDX, // TAG_NO도 함께 저장
- TAG_DESC: entry.TAG_DESC || null,
- status: "From S-EDP", // SEDP에서 가져온 데이터임을 표시
- source: "S-EDP" // 태그 출처 (불변) - S-EDP에서 가져옴
- };
-
- // ATTRIBUTES가 있으면 추가 (SHI 필드들)
- if (Array.isArray(entry.ATTRIBUTES)) {
- for (const attr of entry.ATTRIBUTES) {
- if (attr.ATT_ID && attr.VALUE !== null && attr.VALUE !== undefined) {
- tagDataForFormEntry[attr.ATT_ID] = attr.VALUE;
- }
- }
- }
-
- newTagsForFormEntry.push(tagDataForFormEntry);
-
- processedCount++;
- totalProcessedCount++;
-
- // 주기적으로 진행 상황 보고
- if (progressCallback && (i % 10 === 0 || i === tagEntries.length - 1)) {
- const baseProgress = 60;
- const entryProgress = Math.floor(30 * ((mappingIndex * entriesCount + i) / (mappings.length * entriesCount)));
- progressCallback(baseProgress + entryProgress);
- }
- } catch (error: any) {
- console.error(`Error processing tag entry:`, error);
- allErrors.push(error.message || 'Unknown error');
- }
- }
-
- // Step 7: formEntries 업데이트 - TAG_IDX 기준으로 변경
- if (newTagsForFormEntry.length > 0) {
- try {
- // 기존 formEntry 가져오기
- const existingEntry = await db.query.formEntriesPlant.findFirst({
- where: and(
- eq(formEntriesPlant.formCode, formCode),
- eq(formEntriesPlant.projectCode, projectCode),
- eq(formEntriesPlant.packageCode, packageCode)
- )
- });
-
- if (existingEntry && existingEntry.id) {
- // 기존 formEntry가 있는 경우
- let existingData: Array<{
- TAG_IDX?: string; // 추가: TAG_IDX 필드
- TAG_NO?: string;
- TAG_DESC?: string;
- status?: string;
- [key: string]: any;
- }> = [];
-
- if (Array.isArray(existingEntry.data)) {
- existingData = existingEntry.data;
- }
-
- // 기존 TAG_IDX들 추출 (변경: TAG_NO → TAG_IDX)
- const existingTagIdxs = new Set(
- existingData
- .map(item => item.TAG_IDX)
- .filter(tagIdx => tagIdx !== undefined && tagIdx !== null)
- );
-
- // 중복되지 않은 새 태그들만 필터링 (변경: TAG_NO → TAG_IDX)
- const newUniqueTagsData = newTagsForFormEntry.filter(
- tagData => !existingTagIdxs.has(tagData.TAG_IDX)
- );
-
- // 기존 태그들의 status와 ATTRIBUTES 업데이트 (변경: TAG_NO → TAG_IDX)
- const updatedExistingData = existingData.map(existingItem => {
- const newTagData = newTagsForFormEntry.find(
- newItem => newItem.TAG_IDX === existingItem.TAG_IDX
- );
-
- if (newTagData) {
- // 기존 태그가 있으면 SEDP 데이터로 업데이트
- return {
- ...existingItem,
- ...newTagData,
- TAG_IDX: existingItem.TAG_IDX // TAG_IDX는 유지
- };
- }
-
- return existingItem;
- });
-
- const finalData = [...updatedExistingData, ...newUniqueTagsData];
-
- await db
- .update(formEntriesPlant)
- .set({
- data: finalData,
- updatedAt: new Date()
- })
- .where(eq(formEntriesPlant.id, existingEntry.id));
-
- console.log(`[IMPORT SEDP] Updated formEntry with ${newUniqueTagsData.length} new tags, updated ${updatedExistingData.length - newUniqueTagsData.length} existing tags for form ${formCode}`);
- } else {
- // formEntry가 없는 경우 새로 생성
- await db.insert(formEntriesPlant).values({
- formCode: formCode,
- projectCode,
- packageCode,
- data: newTagsForFormEntry,
- createdAt: new Date(),
- updatedAt: new Date(),
- });
-
- console.log(`[IMPORT SEDP] Created new formEntry with ${newTagsForFormEntry.length} tags for form ${formCode}`);
- }
-
- // 캐시 무효화
- revalidateTag(`form-data-${formCode}-${packageId}`);
- } catch (formEntryError) {
- console.error(`[IMPORT SEDP] Error updating formEntry for form ${formCode}:`, formEntryError);
- allErrors.push(`Error updating formEntry for form ${formCode}: ${formEntryError}`);
- }
- }
-
- } catch (error: any) {
- console.error(`Error processing mapping for formCode ${formCode}:`, error);
- allErrors.push(`Error with formCode ${formCode}: ${error.message || 'Unknown error'}`);
- }
- }
-
- // 모든 매핑 처리 완료 - 진행률 100%
- if (progressCallback) {
- progressCallback(100);
- }
-
- // 최종 결과 반환
- return {
- processedCount: totalProcessedCount,
- excludedCount: totalExcludedCount,
- totalEntries: totalEntriesCount,
- errors: allErrors.length > 0 ? allErrors : undefined
- };
- } catch (error: any) {
- console.error("Tag import error:", error);
- throw error;
- }
-}
-
-/**
- * SEDP API에서 태그 데이터 가져오기
- *
- * @param projectCode 프로젝트 코드
- * @param formCode 양식 코드
- * @returns API 응답 데이터
- */
-async function fetchTagDataFromSEDP(projectCode: string, formCode: string): Promise<any> {
- try {
- // Get the token
- const apiKey = await getSEDPToken();
-
- // Define the API base URL
- const SEDP_API_BASE_URL = process.env.SEDP_API_BASE_URL || 'http://sedpwebapi.ship.samsung.co.kr/api';
-
- // Make the API call
- const response = await fetch(
- `${SEDP_API_BASE_URL}/Data/GetPubData`,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'accept': '*/*',
- 'ApiKey': apiKey,
- 'ProjectNo': projectCode
- },
- body: JSON.stringify({
- ProjectNo: projectCode,
- REG_TYPE_ID: formCode,
- ContainDeleted: false
- })
- }
- );
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`SEDP API request failed: ${response.status} ${response.statusText} - ${errorText}`);
- }
-
- const data = await response.json();
- return data;
- } catch (error: any) {
- console.error('Error calling SEDP API:', error);
- throw new Error(`Failed to fetch data from SEDP API: ${error.message || 'Unknown error'}`);
- }
-} \ No newline at end of file
diff --git a/lib/sedp/sync-form.ts b/lib/sedp/sync-form.ts
index a6d473ad..904d27ba 100644
--- a/lib/sedp/sync-form.ts
+++ b/lib/sedp/sync-form.ts
@@ -94,7 +94,7 @@ interface Register {
SEQ: number;
CMPLX_YN: boolean;
CMPL_SETT: any | null;
- MAP_ATT: MapAttribute2[];
+ MAP_ATT: any[];
MAP_CLS_ID: string[];
MAP_OPER: any | null;
LNK_ATT: LinkAttribute[];
@@ -157,13 +157,6 @@ interface MapAttribute {
INOUT: string | null;
}
-interface MapAttribute2 {
- ATT_ID: string;
- VALUE: string;
- IS_PARA: boolean;
- OPER: string | null;
-}
-
interface Attribute {
PROJ_NO: string;
ATT_ID: string;