summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/[lng]/partners/(partners)/vendor-data-plant/[projectCode]/[packageCode]/eng/[formCode]/page.tsx2
-rw-r--r--components/vendor-data-plant/project-swicher.tsx2
-rw-r--r--components/vendor-data-plant/sidebar.tsx1
-rw-r--r--components/vendor-data-plant/vendor-data-container.tsx3
-rw-r--r--lib/forms-plant/services.ts23
-rw-r--r--lib/forms-plant/stat.ts2
-rw-r--r--lib/sedp/get-tags-plant.ts24
-rw-r--r--lib/sedp/sync-form.ts120
-rw-r--r--lib/tags-plant/service.ts17
-rw-r--r--lib/tags-plant/table/add-tag-dialog.tsx2
10 files changed, 140 insertions, 56 deletions
diff --git a/app/[lng]/partners/(partners)/vendor-data-plant/[projectCode]/[packageCode]/eng/[formCode]/page.tsx b/app/[lng]/partners/(partners)/vendor-data-plant/[projectCode]/[packageCode]/eng/[formCode]/page.tsx
index 351fbca3..620a407f 100644
--- a/app/[lng]/partners/(partners)/vendor-data-plant/[projectCode]/[packageCode]/eng/[formCode]/page.tsx
+++ b/app/[lng]/partners/(partners)/vendor-data-plant/[projectCode]/[packageCode]/eng/[formCode]/page.tsx
@@ -46,6 +46,8 @@ export default async function EngineeringFormPage({
const { formId } = await getFormId(projectCode, packageCode, formCode, mode);
const projectId = await getProjectIdByCode(projectCode)
+
+ console.log(data,"data-eng")
// 6) 예외 처리
if (!columns) {
diff --git a/components/vendor-data-plant/project-swicher.tsx b/components/vendor-data-plant/project-swicher.tsx
index 9b8f9bea..75c0752b 100644
--- a/components/vendor-data-plant/project-swicher.tsx
+++ b/components/vendor-data-plant/project-swicher.tsx
@@ -55,8 +55,6 @@ export function ProjectSwitcher({
)
- console.log(projects,"projects")
-
const displayText = selectedPackage
? `${selectedProject?.projectCode} - ${selectedPackage.packageCode}`
: selectedProject?.projectCode || "Select Package"
diff --git a/components/vendor-data-plant/sidebar.tsx b/components/vendor-data-plant/sidebar.tsx
index b746e69d..ca88abb0 100644
--- a/components/vendor-data-plant/sidebar.tsx
+++ b/components/vendor-data-plant/sidebar.tsx
@@ -46,6 +46,7 @@ export function Sidebar({
const [isLoadingEngineering, setIsLoadingEngineering] = React.useState(false)
const [isLoadingIM, setIsLoadingIM] = React.useState(false)
+
// Engineering 폼 로드
React.useEffect(() => {
if (!selectedPackageCode || !projectCode) {
diff --git a/components/vendor-data-plant/vendor-data-container.tsx b/components/vendor-data-plant/vendor-data-container.tsx
index 7ce831df..bf4c30f1 100644
--- a/components/vendor-data-plant/vendor-data-container.tsx
+++ b/components/vendor-data-plant/vendor-data-container.tsx
@@ -77,6 +77,7 @@ export function VendorDataContainer({
// 상태 관리
const [selectedProjectId, setSelectedProjectId] = React.useState(projects[0]?.projectId || 0)
+ const [selectedProjectCode, setSelectedProjectCode] = React.useState(projects[0]?.projectCode || "")
const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed)
const [selectedPackageCode, setSelectedPackageCode] = React.useState<string | null>(null)
const [selectedFormCode, setSelectedFormCode] = React.useState<string | null>(null)
@@ -94,6 +95,7 @@ export function VendorDataContainer({
const project = projects.find(p => p.projectCode === projectCode)
if (project) {
setSelectedProjectId(project.projectId)
+ setSelectedProjectCode(project.projectCode)
setSelectedPackageCode(packageCode)
}
}
@@ -207,6 +209,7 @@ export function VendorDataContainer({
<Sidebar
isCollapsed={isCollapsed}
selectedPackageCode={selectedPackageCode}
+ projectCode={selectedProjectCode}
selectedFormCode={selectedFormCode}
currentMode={currentMode}
onMasterTagListClick={handleMasterTagListClick}
diff --git a/lib/forms-plant/services.ts b/lib/forms-plant/services.ts
index 7e1976e6..3f50bd47 100644
--- a/lib/forms-plant/services.ts
+++ b/lib/forms-plant/services.ts
@@ -173,8 +173,8 @@ export async function getEditableFieldsByTag(
// 1. 해당 contractItemId의 모든 태그 조회
const tagList = await db
.select({
- tagNo: tags.tagNo,
- tagClass: tags.class
+ tagNo: tagsPlant.tagNo,
+ tagClass: tagsPlant.class
})
.from(tagsPlant)
.where(
@@ -236,6 +236,8 @@ export async function getEditableFieldsByTag(
export async function getFormData(formCode: string, projectCode: string, packageCode:string) {
try {
+ console.log(formCode,projectCode, packageCode)
+
const project = await db.query.projects.findFirst({
where: eq(projects.code, projectCode),
columns: {
@@ -544,7 +546,7 @@ export async function syncMissingTags(
// Build a dynamic OR clause to match (tagType, class) pairs from the mappings.
const orConditions = formMappings.map((m) =>
- and(eq(tags.tagType, m.tagTypeLabel), eq(tags.class, m.classLabel))
+ and(eq(tagsPlant.tagType, m.tagTypeLabel), eq(tagsPlant.class, m.classLabel))
);
// (3) Fetch all matching `tags` for the contractItemId + any of the (tagType, class) pairs.
@@ -1357,17 +1359,18 @@ async function transformDataToSEDPFormat(
let tagClassCode = "";
// Get tagClass code if TAG_NO exists
- if (row.TAG_NO && contractItemId) {
- const cacheKey = `${contractItemId}-${row.TAG_NO}`;
+ if (row.TAG_NO && projectCode) {
+ const cacheKey = `${projectCode}-${row.TAG_NO}`;
if (tagClassCodeCache.has(cacheKey)) {
tagClassCode = tagClassCodeCache.get(cacheKey)!;
} else {
try {
- const tagResult = await db.query.tags.findFirst({
+ const tagResult = await db.query.tagsPlant.findFirst({
where: and(
- eq(tags.contractItemId, contractItemId),
- eq(tags.tagNo, row.TAG_NO)
+ eq(tagsPlant.projectCode, projectCode),
+ eq(tagsPlant.packageCode, packageCode),
+ eq(tagsPlant.tagNo, row.TAG_NO)
)
});
@@ -1997,9 +2000,9 @@ export async function deleteFormDataByTags({
}
// 4. 캐시 무효화
- const cacheKey = `form-data-${formCode}-${contractItemId}`
+ const cacheKey = `form-data-${formCode}-${projectCode}`
revalidateTag(cacheKey)
- revalidateTag(`tags-${contractItemId}`)
+ revalidateTag(`tags-${projectCode}`)
// 페이지 재검증 (필요한 경우)
diff --git a/lib/forms-plant/stat.ts b/lib/forms-plant/stat.ts
index f734e782..ed497211 100644
--- a/lib/forms-plant/stat.ts
+++ b/lib/forms-plant/stat.ts
@@ -371,7 +371,7 @@ export async function getFormStatusByVendor(projectId: number, projectCode: stri
return vendorStatusList
} catch (error) {
- console.error('Error getting vendor form status:', error)
+ console.log('Error getting vendor form status:', error)
throw new Error('벤더별 Form 입력 현황 조회 중 오류가 발생했습니다.')
}
} \ No newline at end of file
diff --git a/lib/sedp/get-tags-plant.ts b/lib/sedp/get-tags-plant.ts
index d1957db4..be0e398b 100644
--- a/lib/sedp/get-tags-plant.ts
+++ b/lib/sedp/get-tags-plant.ts
@@ -210,8 +210,8 @@ export async function importTagsFromSEDP(
const form = await db.query.formsPlant.findFirst({
where: and(
eq(formsPlant.projectCode, projectCode),
- eq(formsPlant.packageCode, packageCode),
- eq(formsPlant.formCode, formCode)
+ eq(formsPlant.formCode, formCode),
+ eq(formsPlant.packageCode, packageCode)
)
});
@@ -239,8 +239,20 @@ export async function importTagsFromSEDP(
}
}
- const insertResult = await db.insert(formsPlant).values(insertValues).returning({ id: formsPlant.id });
-
+ const insertResult = await db.insert(formsPlant)
+ .values(insertValues)
+ .onConflictDoUpdate({
+ target: [formsPlant.projectCode, formsPlant.formCode],
+ set: {
+ packageCode: insertValues.packageCode,
+ formName: insertValues.formName,
+ eng: insertValues.eng ?? false,
+ im: insertValues.im ?? false,
+ updatedAt: new Date()
+ }
+ })
+ .returning({ id: formsPlant.id });
+
if (insertResult.length === 0) {
allErrors.push(`Failed to create form record for formCode ${formCode}`);
continue; // 다음 매핑으로 진행
@@ -318,6 +330,8 @@ export async function importTagsFromSEDP(
status: string;
[key: string]: any;
}> = [];
+ const SEDP_API_BASE_URL = process.env.SEDP_API_BASE_URL || 'http://sedpwebapi.ship.samsung.co.kr/api';
+ const apiKey = await getSEDPToken();
const registerResponse = await fetch(
`${SEDP_API_BASE_URL}/Register/GetByID`,
@@ -560,7 +574,7 @@ export async function importTagsFromSEDP(
}
// 캐시 무효화
- revalidateTag(`form-data-${formCode}-${packageId}`);
+ // 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}`);
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,
diff --git a/lib/tags-plant/service.ts b/lib/tags-plant/service.ts
index 02bd33be..9e9d9ebf 100644
--- a/lib/tags-plant/service.ts
+++ b/lib/tags-plant/service.ts
@@ -15,6 +15,7 @@ import { contractItems, contracts } from "@/db/schema/contract";
import { getCodeListsByID } from "../sedp/sync-object-class";
import { projects, vendors } from "@/db/schema";
import { randomBytes } from 'crypto';
+import { getSEDPToken } from "../sedp/sedp-token";
// 폼 결과를 위한 인터페이스 정의
interface CreatedOrExistingForm {
@@ -105,12 +106,15 @@ export async function createTag(
projectCode: string,
packageCode: string,
) {
+
+
if (!projectCode) {
return { error: "No selectedPackageId provided" }
}
// Validate formData
const validated = createTagSchema.safeParse(formData)
+
if (!validated.success) {
return { error: validated.error.flatten().formErrors.join(", ") }
}
@@ -121,6 +125,7 @@ export async function createTag(
try {
// 하나의 트랜잭션에서 모든 작업 수행
return await db.transaction(async (tx) => {
+
const project = await db.query.projects.findFirst({
where: eq(projects.code, projectCode),
columns: {
@@ -130,6 +135,7 @@ export async function createTag(
const projectId = project.id
+
// 2) 해당 계약 내에서 같은 tagNo를 가진 태그가 있는지 확인
const duplicateCheck = await tx
.select({ count: sql<number>`count(*)` })
@@ -153,10 +159,12 @@ export async function createTag(
projectId, // projectId 전달
validated.data.class
)
+
// ep가 "IMEP"인 것만 필터링
const formMappings = allFormMappings?.filter(mapping => mapping.ep === "IMEP") || []
+ console.log(formMappings,"formMappings")
// 폼 매핑이 없으면 로그만 남기고 진행
if (!formMappings || formMappings.length === 0) {
@@ -244,7 +252,6 @@ export async function createTag(
.values(insertValues)
.returning({ id: formsPlant.id, formCode: formsPlant.formCode, formName: formsPlant.formName })
- console.log("insertResult:", insertResult)
formId = insertResult[0].id
createdOrExistingForms.push({
id: formId,
@@ -282,7 +289,7 @@ export async function createTag(
for (const form of createdOrExistingForms) {
try {
// 기존 formEntry 가져오기
- const existingEntry = await tx.query.formEntries.findFirst({
+ const existingEntry = await tx.query.formEntriesPlant.findFirst({
where: and(
eq(formEntriesPlant.formCode, form.formCode),
eq(formEntriesPlant.projectCode, projectCode),
@@ -348,6 +355,7 @@ export async function createTag(
console.log(`[CREATE TAG] Created new formEntry with tag ${validated.data.tagNo} and tagIdx ${generatedTagIdx} for form ${form.formCode}`);
}
} catch (formEntryError) {
+ console.log(formEntryError)
console.error(`[CREATE TAG] Error updating formEntry for form ${form.formCode}:`, formEntryError);
// 개별 formEntry 에러는 로그만 남기고 전체 트랜잭션은 계속 진행
}
@@ -1612,6 +1620,9 @@ export async function getEngineeringForms(
projectCode: string,
packageCode: string
): Promise<FormInfo[]> {
+ console.log("eng 폼 조회 시작")
+ console.log(projectCode,packageCode)
+
try {
// 1. DB에서 eng=true인 폼 조회
const existingForms = await db
@@ -1628,6 +1639,8 @@ export async function getEngineeringForms(
)
)
+ console.log("existingForms",existingForms)
+
// DB에 데이터가 있으면 반환
if (existingForms.length > 0) {
return existingForms
diff --git a/lib/tags-plant/table/add-tag-dialog.tsx b/lib/tags-plant/table/add-tag-dialog.tsx
index 41731f63..de5d2bf8 100644
--- a/lib/tags-plant/table/add-tag-dialog.tsx
+++ b/lib/tags-plant/table/add-tag-dialog.tsx
@@ -345,7 +345,7 @@ export function AddTagDialog({ projectCode, packageCode }: AddTagDialogProps) {
try {
const res = await createTag(tagData, projectCode, packageCode);
if ("error" in res) {
- console.log(res.error)
+ console.log(res)
failedTags.push({ tag: row.tagNo, error: res.error });
} else {
successfulTags.push(row.tagNo);