summaryrefslogtreecommitdiff
path: root/lib/tags
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-26 09:57:24 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-26 09:57:24 +0000
commit8b23b471638a155fd1bfa3a8c853b26d9315b272 (patch)
tree47353e9dd342011cb2f1dcd24b09661707a8421b /lib/tags
parentd62368d2b68d73da895977e60a18f9b1286b0545 (diff)
(대표님) 권한관리, 문서업로드, rfq첨부, SWP문서룰 등
(최겸) 입찰
Diffstat (limited to 'lib/tags')
-rw-r--r--lib/tags/service.ts348
1 files changed, 180 insertions, 168 deletions
diff --git a/lib/tags/service.ts b/lib/tags/service.ts
index cef20209..028cde42 100644
--- a/lib/tags/service.ts
+++ b/lib/tags/service.ts
@@ -393,69 +393,89 @@ export async function createTagInForm(
formCode: string,
packageCode: string
) {
+ // 1. 초기 검증
if (!selectedPackageId) {
- return { error: "No selectedPackageId provided" }
+ console.error("[CREATE TAG] No selectedPackageId provided");
+ return {
+ success: false,
+ error: "No selectedPackageId provided"
+ };
}
- // Validate formData
- const validated = createTagSchema.safeParse(formData)
+ // 2. FormData 검증
+ const validated = createTagSchema.safeParse(formData);
if (!validated.success) {
- return { error: validated.error.flatten().formErrors.join(", ") }
+ const errorMsg = validated.error.flatten().formErrors.join(", ");
+ console.error("[CREATE TAG] Validation failed:", errorMsg);
+ return {
+ success: false,
+ error: errorMsg
+ };
}
- // React 서버 액션에서 매 요청마다 실행
- unstable_noStore()
+ // 3. 캐시 무효화 설정
+ unstable_noStore();
try {
- // 하나의 트랜잭션에서 모든 작업 수행
+ // 4. 트랜잭션 시작
return await db.transaction(async (tx) => {
- // 1) 선택된 contractItem의 contractId 가져오기
+ // 5. Contract Item 정보 조회
const contractItemResult = await tx
.select({
contractId: contractItems.contractId,
- projectId: contracts.projectId, // projectId 추가
- vendorId: contracts.vendorId // projectId 추가
+ projectId: contracts.projectId,
+ vendorId: contracts.vendorId
})
.from(contractItems)
- .innerJoin(contracts, eq(contractItems.contractId, contracts.id)) // contracts 테이블 조인
+ .innerJoin(contracts, eq(contractItems.contractId, contracts.id))
.where(eq(contractItems.id, selectedPackageId))
- .limit(1)
+ .limit(1);
if (contractItemResult.length === 0) {
- return { error: "Contract item not found" }
+ console.error("[CREATE TAG] Contract item not found");
+ return {
+ success: false,
+ error: "Contract item not found"
+ };
}
- const contractId = contractItemResult[0].contractId
- const projectId = contractItemResult[0].projectId
- const vendorId = contractItemResult[0].vendorId
+ const { contractId, projectId, vendorId } = contractItemResult[0];
- const vendor = await db.query.vendors.findFirst({
+ // 6. Vendor 정보 조회
+ const vendor = await tx.query.vendors.findFirst({
where: eq(vendors.id, vendorId)
});
-
+
if (!vendor) {
- return { error: "선택한 벤더를 찾을 수 없습니다." };
+ console.error("[CREATE TAG] Vendor not found");
+ return {
+ success: false,
+ error: "선택한 벤더를 찾을 수 없습니다."
+ };
}
- // 2) 해당 계약 내에서 같은 tagNo를 가진 태그가 있는지 확인
+ // 7. 중복 태그 확인
const duplicateCheck = await tx
.select({ count: sql<number>`count(*)` })
.from(tags)
.innerJoin(contractItems, eq(tags.contractItemId, contractItems.id))
+ .innerJoin(contracts, eq(contractItems.contractId, contracts.id))
.where(
and(
- eq(contractItems.contractId, contractId),
+ eq(contracts.projectId, projectId),
eq(tags.tagNo, validated.data.tagNo)
)
- )
+ );
if (duplicateCheck[0].count > 0) {
+ console.error(`[CREATE TAG] Duplicate tag number: ${validated.data.tagNo}`);
return {
+ success: false,
error: `태그 번호 "${validated.data.tagNo}"는 이미 이 계약 내에 존재합니다.`,
- }
+ };
}
- // 3) 먼저 기존 form 찾기
+ // 8. Form 조회
let form = await tx.query.forms.findFirst({
where: and(
eq(forms.formCode, formCode),
@@ -463,191 +483,183 @@ export async function createTagInForm(
)
});
- // 4) form이 없으면 formMappings를 통해 생성
+ // 9. Form이 없으면 생성
if (!form) {
- console.log(`[CREATE TAG IN FORM] Form ${formCode} not found, attempting to create...`);
+ console.log(`[CREATE TAG] Form ${formCode} not found, attempting to create...`);
- // 태그 타입에 따른 폼 정보 가져오기
+ // Form Mappings 조회
const allFormMappings = await getFormMappingsByTagType(
validated.data.tagType,
projectId,
validated.data.class
- )
-
-
-
-
- // ep가 "IMEP"인 것만 필터링
- const formMappings = allFormMappings?.filter(mapping => mapping.ep === "IMEP") || []
+ );
- // 현재 formCode와 일치하는 매핑 찾기
+ // IMEP 폼만 필터링
+ const formMappings = allFormMappings?.filter(mapping => mapping.ep === "IMEP") || [];
const targetFormMapping = formMappings.find(mapping => mapping.formCode === formCode);
- if (targetFormMapping) {
- console.log(`[CREATE TAG IN FORM] Found form mapping for ${formCode}, creating form...`);
-
- // form 생성
- const insertResult = await tx
- .insert(forms)
- .values({
- contractItemId: selectedPackageId,
- formCode: targetFormMapping.formCode,
- formName: targetFormMapping.formName,
- im: true,
- })
- .returning({ id: forms.id, formCode: forms.formCode, formName: forms.formName })
-
- form = {
- id: insertResult[0].id,
- formCode: insertResult[0].formCode,
- formName: insertResult[0].formName,
- contractItemId: selectedPackageId,
- im: true,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- console.log(`[CREATE TAG IN FORM] Successfully created form:`, insertResult[0]);
- } else {
- console.log(`[CREATE TAG IN FORM] No IMEP form mapping found for formCode: ${formCode}`);
- console.log(`[CREATE TAG IN FORM] Available IMEP mappings:`, formMappings.map(m => m.formCode));
+ if (!targetFormMapping) {
+ console.error(`[CREATE TAG] No IMEP form mapping found for formCode: ${formCode}`);
return {
+ success: false,
error: `Form ${formCode} not found and no IMEP mapping available for tag type ${validated.data.tagType}`
};
}
- } else {
- console.log(`[CREATE TAG IN FORM] Found existing form:`, form.id);
+
+ // Form 생성
+ const insertResult = await tx
+ .insert(forms)
+ .values({
+ contractItemId: selectedPackageId,
+ formCode: targetFormMapping.formCode,
+ formName: targetFormMapping.formName,
+ im: true,
+ })
+ .returning({ id: forms.id, formCode: forms.formCode, formName: forms.formName });
+
+ form = {
+ id: insertResult[0].id,
+ formCode: insertResult[0].formCode,
+ formName: insertResult[0].formName,
+ contractItemId: selectedPackageId,
+ im: true,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ };
- // 기존 form이 있지만 im이 false인 경우 true로 업데이트
+ console.log(`[CREATE TAG] Successfully created form:`, insertResult[0]);
+ } else {
+ // 기존 form의 im 상태 업데이트
if (form.im !== true) {
await tx
.update(forms)
.set({ im: true })
- .where(eq(forms.id, form.id))
+ .where(eq(forms.id, form.id));
- console.log(`[CREATE TAG IN FORM] Form ${form.id} updated with im: true`)
+ console.log(`[CREATE TAG] Form ${form.id} updated with im: true`);
}
}
- if (form?.id) {
- // 🆕 16진수 24자리 태그 고유 식별자 생성
- const generatedTagIdx = generateTagIdx();
- console.log(`[CREATE TAG IN FORM] Generated tagIdx: ${generatedTagIdx}`);
+ // 10. Form이 있는 경우에만 진행
+ if (!form?.id) {
+ console.error("[CREATE TAG] Failed to create or find form");
+ return {
+ success: false,
+ error: "Failed to create or find form"
+ };
+ }
- // 5) 새 Tag 생성 (tagIdx 추가)
- const [newTag] = await insertTag(tx, {
- contractItemId: selectedPackageId,
- formId: form.id,
- tagIdx: generatedTagIdx, // 🆕 생성된 16진수 24자리 추가
- tagNo: validated.data.tagNo,
- class: validated.data.class,
- tagType: validated.data.tagType,
- description: validated.data.description ?? null,
- })
+ // 11. Tag Index 생성
+ const generatedTagIdx = generateTagIdx();
+ console.log(`[CREATE TAG] Generated tagIdx: ${generatedTagIdx}`);
- // 6) 기존 formEntry 가져오기
- const entry = await tx.query.formEntries.findFirst({
- where: and(
- eq(formEntries.formCode, formCode),
- eq(formEntries.contractItemId, selectedPackageId),
- )
- });
+ // 12. 새 Tag 생성
+ const [newTag] = await insertTag(tx, {
+ contractItemId: selectedPackageId,
+ formId: form.id,
+ tagIdx: generatedTagIdx,
+ tagNo: validated.data.tagNo,
+ class: validated.data.class,
+ tagType: validated.data.tagType,
+ description: validated.data.description ?? null,
+ });
- if (entry && entry.id) {
- // 7) 기존 데이터 가져오기 (배열인지 확인) - TAG_IDX 타입 추가
- let existingData: Array<{
- TAG_IDX?: string; // 🆕 TAG_IDX 필드 추가
- TAG_NO: string;
- TAG_DESC?: string;
- status?: string;
- [key: string]: any; // 다른 필드들도 포함
- }> = [];
-
- if (Array.isArray(entry.data)) {
- existingData = entry.data;
- }
+ // 13. Tag Class 조회
+ const tagClass = await tx.query.tagClasses.findFirst({
+ where: and(
+ eq(tagClasses.projectId, projectId),
+ eq(tagClasses.label, validated.data.class)
+ )
+ });
- console.log(`[CREATE TAG IN FORM] Existing data count: ${existingData.length}`);
+ if (!tagClass) {
+ console.warn("[CREATE TAG] Tag class not found, using default");
+ }
- const tagClass = await db.query.tagClasses.findFirst({
- where: and(eq(tagClasses.projectId, projectId),eq(tagClasses.label, validated.data.class))
- });
+ // 14. FormEntry 처리
+ const entry = await tx.query.formEntries.findFirst({
+ where: and(
+ eq(formEntries.formCode, formCode),
+ eq(formEntries.contractItemId, selectedPackageId),
+ )
+ });
- // 8) 새로운 태그를 기존 데이터에 추가 (TAG_IDX 포함)
- const newTagData = {
- TAG_IDX: generatedTagIdx, // 🆕 같은 16진수 24자리 값 사용
- TAG_NO: validated.data.tagNo,
- TAG_DESC: validated.data.description ?? null,
- CLS_ID: tagClass.code,
- VNDRCD: vendor.vendorCode,
- VNDRNM_1: vendor.vendorName,
- CM3003: packageCode,
- ME5074: packageCode,
+ // 15. 새로운 태그 데이터 준비
+ const newTagData = {
+ TAG_IDX: generatedTagIdx,
+ TAG_NO: validated.data.tagNo,
+ TAG_DESC: validated.data.description ?? null,
+ CLS_ID: tagClass?.code || validated.data.class, // tagClass가 없을 경우 대비
+ VNDRCD: vendor.vendorCode,
+ VNDRNM_1: vendor.vendorName,
+ CM3003: packageCode,
+ ME5074: packageCode,
+ status: "New" // 수동으로 생성된 태그임을 표시
+ };
- status: "New" // 수동으로 생성된 태그임을 표시
- };
+ if (entry?.id) {
+ // 16. 기존 FormEntry 업데이트
+ let existingData: Array<any> = [];
+ if (Array.isArray(entry.data)) {
+ existingData = entry.data;
+ }
- const updatedData = [...existingData, newTagData];
+ console.log(`[CREATE TAG] Existing data count: ${existingData.length}`);
- console.log(`[CREATE TAG IN FORM] Updated data count: ${updatedData.length}`);
- console.log(`[CREATE TAG IN FORM] Added tag: ${validated.data.tagNo} with tagIdx: ${generatedTagIdx}, status: 수동 생성`);
+ const updatedData = [...existingData, newTagData];
- // 9) formEntries 업데이트
- await tx
- .update(formEntries)
- .set({
- data: updatedData,
- updatedAt: new Date() // 업데이트 시간도 갱신
- })
- .where(eq(formEntries.id, entry.id));
- } else {
- // 10) formEntry가 없는 경우 새로 생성 (TAG_IDX 포함)
- console.log(`[CREATE TAG IN FORM] No existing formEntry found, creating new one`);
-
- const newEntryData = [{
- TAG_IDX: generatedTagIdx, // 🆕 같은 16진수 24자리 값 사용
- TAG_NO: validated.data.tagNo,
- TAG_DESC: validated.data.description ?? null,
- status: "New" // 수동으로 생성된 태그임을 표시
- }];
+ await tx
+ .update(formEntries)
+ .set({
+ data: updatedData,
+ updatedAt: new Date()
+ })
+ .where(eq(formEntries.id, entry.id));
- await tx.insert(formEntries).values({
- formCode: formCode,
- contractItemId: selectedPackageId,
- data: newEntryData,
- createdAt: new Date(),
- updatedAt: new Date(),
- });
- }
+ console.log(`[CREATE TAG] Updated formEntry with new tag`);
+ } else {
+ // 17. 새 FormEntry 생성
+ console.log(`[CREATE TAG] Creating new formEntry`);
+
+ await tx.insert(formEntries).values({
+ formCode: formCode,
+ contractItemId: selectedPackageId,
+ data: [newTagData],
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ });
+
+ console.log(`[CREATE TAG] Created new formEntry`);
+ }
+
+ // 18. 캐시 무효화
+ revalidateTag(`tags-${selectedPackageId}`);
+ revalidateTag(`forms-${selectedPackageId}`);
+ revalidateTag(`form-data-${formCode}-${selectedPackageId}`);
+ revalidateTag("tags");
- // 12) 성공 시 반환
+ console.log(`[CREATE TAG] Successfully created tag: ${validated.data.tagNo} with tagIdx: ${generatedTagIdx}`);
+
+ // 19. 성공 응답
return {
success: true,
data: {
formId: form.id,
tagNo: validated.data.tagNo,
- tagIdx: generatedTagIdx, // 🆕 생성된 tagIdx도 반환
- formCreated: !form // form이 새로 생성되었는지 여부
+ tagIdx: generatedTagIdx,
+ formCreated: !form
}
- }
-
- console.log(`[CREATE TAG IN FORM] Successfully created tag: ${validated.data.tagNo} with tagIdx: ${generatedTagIdx}`)
- } else {
- return { error: "Failed to create or find form" };
- }
-
- // 11) 캐시 무효화 (React 서버 액션에서 캐싱 사용 시)
- revalidateTag(`tags-${selectedPackageId}`)
- revalidateTag(`forms-${selectedPackageId}`)
- revalidateTag(`form-data-${formCode}-${selectedPackageId}`) // 폼 데이터 캐시도 무효화
- revalidateTag("tags")
-
-
- })
+ };
+ });
} catch (err: any) {
- console.log("createTag in Form error:", err)
- console.error("createTag in Form error:", err)
- return { error: getErrorMessage(err) }
+ // 20. 에러 처리
+ console.error("[CREATE TAG] Transaction error:", err);
+ const errorMessage = getErrorMessage(err);
+
+ return {
+ success: false,
+ error: errorMessage
+ };
}
}