diff options
Diffstat (limited to 'lib/sedp/sync-form.ts')
| -rw-r--r-- | lib/sedp/sync-form.ts | 120 |
1 files changed, 85 insertions, 35 deletions
diff --git a/lib/sedp/sync-form.ts b/lib/sedp/sync-form.ts index a6d473ad..4a3c847e 100644 --- a/lib/sedp/sync-form.ts +++ b/lib/sedp/sync-form.ts @@ -1,6 +1,6 @@ // src/lib/cron/syncTagFormMappings.ts import db from "@/db/db"; -import { projects, tagTypes, tagClasses, tagTypeClassFormMappings, formMetas, forms, contractItems, items, contracts, templateItems } from '@/db/schema'; +import { projects, tagTypes, tagClasses, tagTypeClassFormMappings, formMetas, forms, formsPlant, contractItems, items, contracts, templateItems } from '@/db/schema'; import { eq, and, inArray, ilike } from 'drizzle-orm'; import { getSEDPToken } from "./sedp-token"; @@ -38,6 +38,18 @@ interface FormRecord { updatedAt: Date; } +// FormPlantRecord 인터페이스 추가 (plant용) +interface FormPlantRecord { + projectCode: string; + packageCode: string; + formCode: string; + formName: string; + eng: boolean; + im: boolean; + createdAt: Date; + updatedAt: Date; +} + interface TemplateItem { TMPL_ID: string; NAME: string; @@ -920,6 +932,7 @@ async function getContractItemsByItemCodes(itemCodes: string[], projectId: numbe export async function saveFormMappingsAndMetas( projectId: number, projectCode: string, + projectType: string | null, // 프로젝트 타입 파라미터 추가 registers: Register[], newRegisters: newRegister[] ): Promise<number> { @@ -936,30 +949,35 @@ export async function saveFormMappingsAndMetas( const registerMap = new Map(registers.map(r => [r.TYPE_ID, r])); const attributeMap = await getAttributes(projectCode); - // getCodeLists 호출 제거 - // const codeListMap = await getCodeLists(projectCode); const uomMap = await getUOMs(projectCode); const defaultAttributes = await getDefaulTAttributes(); - // 성능 향상을 위한 코드 리스트 캐시 추가 (선택사항) const codeListCache = new Map<string, CodeList | null>(); /* ------------------------------------------------------------------ */ - /* 2. Contract‑item look‑up (SCOPES) */ + /* 2. Contract‑item look‑up (SCOPES) - ship 타입일 때만 필요 */ /* ------------------------------------------------------------------ */ - const uniqueItemCodes = [...new Set( - newRegisters - .filter(nr => nr.SCOPES && nr.SCOPES.length > 0) - .flatMap(nr => nr.SCOPES as string[]) - )]; - const itemCodeToContractItemIds = await getContractItemsByItemCodes(uniqueItemCodes, projectId); + const isShipType = projectType === 'ship'; + const isPlantType = projectType === 'plant'; + + let itemCodeToContractItemIds = new Map<string, number[]>(); + + if (isShipType) { + const uniqueItemCodes = [...new Set( + newRegisters + .filter(nr => nr.SCOPES && nr.SCOPES.length > 0) + .flatMap(nr => nr.SCOPES as string[]) + )]; + itemCodeToContractItemIds = await getContractItemsByItemCodes(uniqueItemCodes, projectId); + } /* ------------------------------------------------------------------ */ /* 3. Buffers for bulk insert */ /* ------------------------------------------------------------------ */ const mappingsToSave: TagTypeClassFormMapping[] = []; const formMetasToSave: FormMeta[] = []; - const formsToSave: FormRecord[] = []; + const formsToSave: FormRecord[] = []; // ship용 + const formsPlantToSave: FormPlantRecord[] = []; // plant용 const contractItemIdsWithForms = new Set<number>(); const templateDataByFormCode: Map<string, TemplateItem[]> = new Map(); @@ -1012,20 +1030,17 @@ export async function saveFormMappingsAndMetas( ...(uomSymbol ? { uom: uomSymbol, uomId } : {}) }; - // 수정된 부분: getCodeListById 사용 if (!defaultAttributes.includes(attId) && (attribute.VAL_TYPE === "LIST" || attribute.VAL_TYPE === "DYNAMICLIST") && attribute.CL_ID) { - // 캐시 확인 let cl = codeListCache.get(attribute.CL_ID); - // 캐시에 없으면 API 호출 if (!codeListCache.has(attribute.CL_ID)) { try { cl = await getCodeListById(projectCode, attribute.CL_ID); - codeListCache.set(attribute.CL_ID, cl); // 캐시에 저장 + codeListCache.set(attribute.CL_ID, cl); } catch (error) { console.warn(`코드 리스트 ${attribute.CL_ID} 가져오기 실패:`, error); cl = null; - codeListCache.set(attribute.CL_ID, null); // 실패도 캐시에 저장 + codeListCache.set(attribute.CL_ID, null); } } @@ -1066,24 +1081,42 @@ export async function saveFormMappingsAndMetas( }); }); - /* ---------- 4‑d. contractItem ↔ form -------------------------- */ + /* ---------- 4‑d. contractItem ↔ form (프로젝트 타입별 분기) ------ */ if (newReg.SCOPES && newReg.SCOPES.length > 0) { - for (const itemCode of newReg.SCOPES) { - const contractItemIds = itemCodeToContractItemIds.get(itemCode); - if (contractItemIds && contractItemIds.length > 0) { - contractItemIds.forEach(cId => { - contractItemIdsWithForms.add(cId); - formsToSave.push({ - contractItemId: cId, - formCode, - formName: legacy?.DESC || formCode, - eng: true, - createdAt: new Date(), - updatedAt: new Date() + for (const packageCode of newReg.SCOPES) { + if (isShipType) { + // Ship 타입: forms 테이블에 저장 (contractItemId 기반) + const contractItemIds = itemCodeToContractItemIds.get(packageCode); + if (contractItemIds && contractItemIds.length > 0) { + contractItemIds.forEach(cId => { + contractItemIdsWithForms.add(cId); + formsToSave.push({ + contractItemId: cId, + formCode, + formName: legacy?.DESC || formCode, + eng: true, + im: false, + createdAt: new Date(), + updatedAt: new Date() + }); }); + } else { + console.warn(`[Ship] packageCode ${packageCode} 의 contractItemId 없음`); + } + } else if (isPlantType) { + // Plant 타입: formsPlant 테이블에 저장 (projectCode, packageCode 기반) + formsPlantToSave.push({ + projectCode, + packageCode, + formCode, + formName: legacy?.DESC || formCode, + eng: true, + im: false, + createdAt: new Date(), + updatedAt: new Date() }); } else { - console.warn(`itemCode ${itemCode} 의 contractItemId 없음`); + console.warn(`알 수 없는 프로젝트 타입: ${projectType}`); } } } @@ -1098,7 +1131,14 @@ export async function saveFormMappingsAndMetas( if (old.length) await tx.delete(templateItems).where(inArray(templateItems.formMappingId, old.map(o => o.id))); await tx.delete(tagTypeClassFormMappings).where(eq(tagTypeClassFormMappings.projectId, projectId)); await tx.delete(formMetas).where(eq(formMetas.projectId, projectId)); - if (contractItemIdsWithForms.size) await tx.delete(forms).where(inArray(forms.contractItemId, [...contractItemIdsWithForms])); + + // 프로젝트 타입별로 기존 데이터 삭제 및 새 데이터 저장 + if (isShipType && contractItemIdsWithForms.size) { + await tx.delete(forms).where(inArray(forms.contractItemId, [...contractItemIdsWithForms])); + } + if (isPlantType) { + await tx.delete(formsPlant).where(eq(formsPlant.projectCode, projectCode)); + } const savedMappings = mappingsToSave.length ? await tx.insert(tagTypeClassFormMappings).values(mappingsToSave).onConflictDoNothing().returning({ id: tagTypeClassFormMappings.id, formCode: tagTypeClassFormMappings.formCode }) : []; totalSaved += mappingsToSave.length; @@ -1110,7 +1150,18 @@ export async function saveFormMappingsAndMetas( } if (formMetasToSave.length) { await tx.insert(formMetas).values(formMetasToSave).onConflictDoNothing(); totalSaved += formMetasToSave.length; } - if (formsToSave.length) { await tx.insert(forms).values(formsToSave).onConflictDoNothing(); totalSaved += formsToSave.length; } + + // Ship 타입: forms 테이블에 저장 + if (isShipType && formsToSave.length) { + await tx.insert(forms).values(formsToSave).onConflictDoNothing(); + totalSaved += formsToSave.length; + } + + // Plant 타입: formsPlant 테이블에 저장 + if (isPlantType && formsPlantToSave.length) { + await tx.insert(formsPlant).values(formsPlantToSave).onConflictDoNothing(); + totalSaved += formsPlantToSave.length; + } }); return totalSaved; @@ -1119,7 +1170,6 @@ export async function saveFormMappingsAndMetas( throw err; } } - // 메인 동기화 함수 export async function syncTagFormMappings() { try { @@ -1137,7 +1187,7 @@ export async function syncTagFormMappings() { const newRegisters = await getNewRegisters(project.code); // 데이터베이스에 저장 - const count = await saveFormMappingsAndMetas(project.id, project.code, registers, newRegisters); + const count = await saveFormMappingsAndMetas(project.id, project.code, project.type || null, registers, newRegisters); return { project: project.code, success: true, |
