diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-03 16:02:12 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-03 16:02:12 +0900 |
| commit | aeaa24a239cf29f7bc98363339ccdbd51a4015f0 (patch) | |
| tree | 30d91c2b54d92d0ed6a9da108ab4e67bc730d35a | |
| parent | 8688794b0cae0a6bb15d4c1f40a5b2c71e87acb4 (diff) | |
(김준회) dolce: B4 일괄 업로드 파싱 로직 오류 수정
| -rw-r--r-- | lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx b/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx index 52252e14..44f9c801 100644 --- a/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx +++ b/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx @@ -31,7 +31,6 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select" -import { ScrollArea } from "@/components/ui/scroll-area" import { Badge } from "@/components/ui/badge" import { Upload, @@ -48,40 +47,34 @@ import { bulkUploadB4Documents } from "../enhanced-document-service" // 파일명 파싱 유틸리티 function parseFileName(fileName: string): { docNumber: string | null; revision: string | null } { - // 파일 확장자 제거 - const nameWithoutExt = fileName.replace(/\.[^.]+$/, "") - - // revision 패턴 찾기 (R01, r01, REV01, rev01 등) - const revisionMatch = nameWithoutExt.match(/[Rr](?:EV)?(\d+)/g) - const revision = revisionMatch ? revisionMatch[revisionMatch.length - 1].toUpperCase() : null - - // revision 제거한 나머지에서 docNumber 찾기 - let cleanedName = nameWithoutExt - if (revision) { - // revision과 그 앞의 구분자를 제거 - const revPattern = new RegExp(`[-_\\s]*${revision.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1")}.*$`, 'i') - cleanedName = cleanedName.replace(revPattern, "") + // 공백으로 단어 분리 (첫 번째는 파일명으로 무시) + const words = fileName.trim().split(/\s+/).filter(word => word.length > 0) + + if (words.length < 2) { + return { docNumber: null, revision: null } } - - // docNumber 패턴 찾기 (XX-XX-XX 형태) - // 공백이나 언더스코어를 하이픈으로 정규화 - const normalizedName = cleanedName.replace(/[\s_]+/g, '-') - - // 2~3자리 코드가 2~3개 연결된 패턴 찾기 - const docNumberPatterns = [ - /\b([A-Za-z]{2,3})-([A-Za-z]{2,3})-([A-Za-z0-9]{2,4})\b/, - /\b([A-Za-z]{2,3})\s+([A-Za-z]{2,3})\s+([A-Za-z0-9]{2,4})\b/, - ] - - let docNumber: string | null = null - for (const pattern of docNumberPatterns) { - const match = normalizedName.match(pattern) || cleanedName.match(pattern) - if (match) { - docNumber = `${match[1]}-${match[2]}-${match[3]}`.toUpperCase() - break - } + + // 마지막 단어에서 확장자와 리비전을 분리 + const lastWord = words[words.length - 1] + const lastDotIndex = lastWord.lastIndexOf('.') + + let revision: string | null = null + + if (lastDotIndex !== -1) { + // 마지막 '.' 기준으로 확장자 앞부분만 사용 + const beforeExt = lastWord.substring(0, lastDotIndex) + + // revision 패턴 찾기 (R01, r01, REV01, rev01 등) + const revisionMatch = beforeExt.match(/[Rr](?:EV)?(\d+)/) + revision = revisionMatch ? revisionMatch[0].toUpperCase() : null } - + + // 문서번호: 첫 번째(파일명)와 마지막(REV.ext)을 제외한 모든 단어들을 '-'로 연결 + const docWords = words.slice(1, -1) // 첫 번째와 마지막 제외 + const docNumber = docWords.length > 0 + ? docWords.join('-').toUpperCase() + : null + return { docNumber, revision } } @@ -113,6 +106,7 @@ export function BulkB4UploadDialog({ const [isUploading, setIsUploading] = React.useState(false) const [parsedFiles, setParsedFiles] = React.useState<ParsedFile[]>([]) const [isDragging, setIsDragging] = React.useState(false) + const [currentProjectId, setCurrentProjectId] = React.useState<string>("") const router = useRouter() // 프로젝트 ID 추출 @@ -134,19 +128,45 @@ export function BulkB4UploadDialog({ // 파일 선택 시 파싱 const handleFilesChange = (files: File[]) => { - const parsed = files.map(file => { - const { docNumber, revision } = parseFileName(file.name) - return { - file, - docNumber, - revision, - status: docNumber ? 'pending' as const : 'ignored' as const, - message: !docNumber ? 'docNumber를 찾을 수 없음' : undefined - } - }) - - setParsedFiles(parsed) - form.setValue("files", files) + const currentProject = form.watch("projectId") + + // 프로젝트가 변경되었거나 처음 선택하는 경우 + if (!currentProject || currentProject !== currentProjectId) { + setCurrentProjectId(currentProject) + const parsed = files.map(file => { + const { docNumber, revision } = parseFileName(file.name) + return { + file, + docNumber, + revision, + status: docNumber ? 'pending' as const : 'ignored' as const, + message: !docNumber ? 'docNumber를 찾을 수 없음' : undefined + } + }) + setParsedFiles(parsed) + form.setValue("files", files) + } else { + // 같은 프로젝트에서 파일 추가하는 경우 + const parsed = files.map(file => { + const { docNumber, revision } = parseFileName(file.name) + return { + file, + docNumber, + revision, + status: docNumber ? 'pending' as const : 'ignored' as const, + message: !docNumber ? 'docNumber를 찾을 수 없음' : undefined + } + }) + + // 기존 파일들과 새 파일들을 합침 (중복 파일명은 새 것으로 대체) + const existingFileNames = new Set(parsedFiles.map(pf => pf.file.name)) + const newFiles = parsed.filter(pf => !existingFileNames.has(pf.file.name)) + const combinedParsed = [...parsedFiles, ...newFiles] + const combinedFiles = [...parsedFiles.map(pf => pf.file), ...newFiles.map(pf => pf.file)] + + setParsedFiles(combinedParsed) + form.setValue("files", combinedFiles) + } } // 파일 제거 @@ -275,6 +295,7 @@ export function BulkB4UploadDialog({ form.reset() setParsedFiles([]) setIsDragging(false) + setCurrentProjectId("") } }, [open, form]) @@ -288,7 +309,10 @@ export function BulkB4UploadDialog({ <DialogTitle>B4 Document Bulk Upload</DialogTitle> <DialogDescription> Document numbers and revisions will be automatically extracted from file names. - Example: "agadfg de na oc R01.pdf" → Document Number: DE-NA-OC, Revision: R01 + Format: [filename] [DOC1] [DOC2] ... [DOCN] [REV].[ext] + Examples: + "testfile TANK ANA R01.pdf" → Document Number: TANK-ANA, Revision: R01 + "drawing ABC DEF GHI JKL R02.pdf" → Document Number: ABC-DEF-GHI-JKL, Revision: R02 </DialogDescription> </DialogHeader> @@ -378,7 +402,7 @@ export function BulkB4UploadDialog({ </div> </div> - <ScrollArea className="h-[250px] border rounded-lg p-2"> + <div className="max-h-[250px] border rounded-lg p-2 overflow-y-auto"> <div className="space-y-2"> {parsedFiles.map((pf, index) => ( <div @@ -440,7 +464,7 @@ export function BulkB4UploadDialog({ </div> ))} </div> - </ScrollArea> + </div> </div> )} |
