From f4b1a770184e8647e0b3042a52a1bcc6f9cf00ce Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Wed, 12 Nov 2025 17:49:57 +0900
Subject: (김준회) SWP: 파일 업로드시 Stage 검증 추가, DOC_CLASS 관리 단순화
 (코드 제거), DOC_CLASS 추가시 검증(A-Z0-9) 처리
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/swp/table/swp-table-toolbar.tsx | 81 ++++++++++++++++++++++++++++++++++---
 1 file changed, 75 insertions(+), 6 deletions(-)

(limited to 'lib/swp/table/swp-table-toolbar.tsx')

diff --git a/lib/swp/table/swp-table-toolbar.tsx b/lib/swp/table/swp-table-toolbar.tsx
index add69666..013b4a13 100644
--- a/lib/swp/table/swp-table-toolbar.tsx
+++ b/lib/swp/table/swp-table-toolbar.tsx
@@ -19,6 +19,8 @@ import {
   validateFileName 
 } from "./swp-upload-validation-dialog";
 import { SwpUploadedFilesDialog } from "./swp-uploaded-files-dialog";
+import { getProjectDocumentClassStages } from "@/lib/docu-list-rule/document-class/service";
+import type { DocumentListItem } from "@/lib/swp/document-service";
 
 interface SwpTableFilters {
   docNo?: string;
@@ -38,7 +40,7 @@ interface SwpTableToolbarProps {
   vendorCode?: string;
   droppedFiles?: File[];
   onFilesProcessed?: () => void;
-  documents?: Array<{ OWN_DOC_NO: string | null }>; // 업로드 권한 검증용 문서 목록 (OWN_DOC_NO 기준)
+  documents?: DocumentListItem[]; // 업로드 권한 검증 + DOC_TYPE 확인용 문서 목록
   userId?: string; // 파일 취소 시 필요
 }
 
@@ -80,6 +82,10 @@ export function SwpTableToolbar({
   }>>([]);
   const [showValidationDialog, setShowValidationDialog] = useState(false);
 
+  // Document Class-Stage 매핑 (프로젝트별)
+  const [documentClassStages, setDocumentClassStages] = useState<Record<string, string[]>>({});
+  const [isLoadingDocClassStages, setIsLoadingDocClassStages] = useState(false);
+
   /**
    * 업로드 가능한 문서번호 목록 추출 (OWN_DOC_NO 기준)
    */
@@ -89,11 +95,62 @@ export function SwpTableToolbar({
       .filter((ownDocNo): ownDocNo is string => ownDocNo !== null && ownDocNo !== undefined);
   }, [documents]);
 
+  /**
+   * 문서번호 → DOC_TYPE 매핑 (Stage 검증용)
+   */
+  const docNoToDocTypeMap = useMemo(() => {
+    const map: Record<string, string> = {};
+    for (const doc of documents) {
+      if (doc.OWN_DOC_NO && doc.DOC_TYPE) {
+        map[doc.OWN_DOC_NO] = doc.DOC_TYPE;
+      }
+    }
+    return map;
+  }, [documents]);
+
   /**
    * 벤더 모드 여부 (벤더 코드가 있으면 벤더 모드)
    */
   const isVendorMode = !!vendorCode;
 
+  /**
+   * 프로젝트 변경 시 Document Class-Stage 매핑 로드
+   */
+  useEffect(() => {
+    if (!projNo) {
+      setDocumentClassStages({});
+      return;
+    }
+
+    let isCancelled = false;
+
+    const loadDocumentClassStages = async () => {
+      try {
+        setIsLoadingDocClassStages(true);
+        const stages = await getProjectDocumentClassStages(projNo);
+        if (!isCancelled) {
+          setDocumentClassStages(stages);
+          console.log(`[SwpTableToolbar] Document Class-Stage 매핑 로드 완료:`, stages);
+        }
+      } catch (error) {
+        if (!isCancelled) {
+          console.error('[SwpTableToolbar] Document Class-Stage 매핑 로드 실패:', error);
+          setDocumentClassStages({});
+        }
+      } finally {
+        if (!isCancelled) {
+          setIsLoadingDocClassStages(false);
+        }
+      }
+    };
+
+    loadDocumentClassStages();
+
+    return () => {
+      isCancelled = true;
+    };
+  }, [projNo]);
+
   /**
    * 드롭된 파일 처리 - useEffect로 감지하여 자동 검증
    */
@@ -120,9 +177,15 @@ export function SwpTableToolbar({
         return;
       }
 
-      // 파일명 검증 (문서번호 권한 포함)
+      // 파일명 검증 (문서번호 권한 + Stage 검증 포함)
       const results = droppedFiles.map((file) => {
-        const validation = validateFileName(file.name, availableDocNos, isVendorMode);
+        const validation = validateFileName(
+          file.name,
+          availableDocNos,
+          isVendorMode,
+          docNoToDocTypeMap,
+          documentClassStages
+        );
         return {
           file,
           valid: validation.valid,
@@ -135,7 +198,7 @@ export function SwpTableToolbar({
       setShowValidationDialog(true);
       onFilesProcessed?.();
     }
-  }, [droppedFiles, projNo, vendorCode, toast, onFilesProcessed, availableDocNos, isVendorMode]);
+  }, [droppedFiles, projNo, vendorCode, toast, onFilesProcessed, availableDocNos, isVendorMode, docNoToDocTypeMap, documentClassStages]);
 
   /**
    * 파일 업로드 핸들러
@@ -171,9 +234,15 @@ export function SwpTableToolbar({
       return;
     }
 
-    // 각 파일의 파일명 검증 (문서번호 권한 포함)
+    // 각 파일의 파일명 검증 (문서번호 권한 + Stage 검증 포함)
     const results = Array.from(selectedFiles).map((file) => {
-      const validation = validateFileName(file.name, availableDocNos, isVendorMode);
+      const validation = validateFileName(
+        file.name,
+        availableDocNos,
+        isVendorMode,
+        docNoToDocTypeMap,
+        documentClassStages
+      );
       return {
         file,
         valid: validation.valid,
-- 
cgit v1.2.3

