diff options
| -rw-r--r-- | lib/general-contract-template/service.ts | 97 | ||||
| -rw-r--r-- | lib/general-contract-template/template/general-contract-template-toolbar-actions.tsx | 33 |
2 files changed, 52 insertions, 78 deletions
diff --git a/lib/general-contract-template/service.ts b/lib/general-contract-template/service.ts index 9b3eda68..37af83ce 100644 --- a/lib/general-contract-template/service.ts +++ b/lib/general-contract-template/service.ts @@ -9,7 +9,8 @@ import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { GeneralContractTemplate, generalContractTemplates, users } from "@/db/schema"; -import { deleteFile, saveFile } from "@/lib/file-stroage"; +import { deleteFile, saveFile, saveDRMFile } from "@/lib/file-stroage"; +import { decryptWithServerAction } from "@/components/drm/drmUtils"; import { selectContractTemplates, selectContractTemplatesWithUsers, @@ -223,22 +224,47 @@ export async function saveTemplateFile(templateId: number, formData: FormData) { return { error: "파일 경로가 없습니다." }; } - // 파일 저장 로직 (실제 파일 시스템에 저장) - const { writeFile, mkdir } = await import("fs/promises"); - const { join } = await import("path"); + // 파일 저장 로직 (DRM 해제 로직 적용) + const saveResult = await saveDRMFile( + file, + decryptWithServerAction, + 'general-contract-templates' + ); - const bytes = await file.arrayBuffer(); - const buffer = Buffer.from(bytes); + if (!saveResult.success) { + return { error: saveResult.error || '파일 저장에 실패했습니다.' }; + } - // 기존 파일 경로 사용 (덮어쓰기) - general-contract-templates 경로로 통일 - const uploadPath = join(process.cwd(), "public", template.filePath.replace(/^\//, "")); - - // 디렉토리 확인 및 생성 - const dirPath = uploadPath.substring(0, uploadPath.lastIndexOf('/')); - await mkdir(dirPath, { recursive: true }); + // 기존 파일 경로와 다른 경우에만 파일 경로 업데이트 + if (template.filePath !== saveResult.publicPath) { + // 기존 파일 삭제 + if (template.filePath) { + const deleted = await deleteFile(template.filePath); + if (deleted) { + console.log(`✅ 기존 파일 삭제됨: ${template.filePath}`); + } else { + console.log(`⚠️ 기존 파일 삭제 실패: ${template.filePath}`); + } + } - // 파일 저장 - await writeFile(uploadPath, buffer); + // DB에 새 파일 경로 업데이트 + await db + .update(generalContractTemplates) + .set({ + filePath: saveResult.publicPath, + fileName: file.name, + updatedAt: new Date(), + }) + .where(eq(generalContractTemplates.id, templateId)); + } else { + // 같은 경로인 경우 수정일시만 업데이트 + await db + .update(generalContractTemplates) + .set({ + updatedAt: new Date(), + }) + .where(eq(generalContractTemplates.id, templateId)); + } // 캐시 무효화 (목록/상세 모두 고려) revalidatePath(`/evcp/general-contract-template/${templateId}`); @@ -424,40 +450,19 @@ export async function updateTemplate({ let filePath: string | undefined = undefined; if (file) { - // 1) 새 파일 저장 (원본 파일명 유지 + 충돌 시 접미사) - const { mkdir, writeFile, access } = await import('fs/promises'); - const { join, extname, basename } = await import('path'); - - const ext = extname(file.name); - const base = basename(file.name, ext) - .replace(/[<>:"'|?*\\\/]/g, '_') - .replace(/[\x00-\x1f]/g, '') - .replace(/\s+/g, ' ') - .trim() - .substring(0, 200); - - const dirAbs = join(process.cwd(), 'public', 'general-contract-templates'); - await mkdir(dirAbs, { recursive: true }); - - let candidate = `${base}${ext}`; - let absPath = join(dirAbs, candidate); - let counter = 1; - while (true) { - try { - await access(absPath); - candidate = `${base} (${counter})${ext}`; - absPath = join(dirAbs, candidate); - counter += 1; - } catch { - break; - } + // 1) 새 파일 저장 (DRM 해제 로직 적용) + const saveResult = await saveDRMFile( + file, + decryptWithServerAction, + 'general-contract-templates' + ); + + if (!saveResult.success) { + return { error: saveResult.error || '파일 저장에 실패했습니다.' }; } - const bytes = await file.arrayBuffer(); - await writeFile(absPath, Buffer.from(bytes)); - - fileName = candidate; - filePath = `/general-contract-templates/${candidate}`; + fileName = file.name; + filePath = saveResult.publicPath; // 2) 기존 파일 삭제 if (prev.filePath) { diff --git a/lib/general-contract-template/template/general-contract-template-toolbar-actions.tsx b/lib/general-contract-template/template/general-contract-template-toolbar-actions.tsx index 03818109..38a83a7f 100644 --- a/lib/general-contract-template/template/general-contract-template-toolbar-actions.tsx +++ b/lib/general-contract-template/template/general-contract-template-toolbar-actions.tsx @@ -1,8 +1,7 @@ "use client" import * as React from "react" -import { useRouter } from "next/navigation" -import { Trash2, FileText } from "lucide-react" +import { Trash2 } from "lucide-react" import { toast } from "sonner" import { Button } from "@/components/ui/button" @@ -19,10 +18,7 @@ export function GeneralContractTemplateToolbarActions({ selectedRows = [], onSelectionChange }: GeneralContractTemplateToolbarActionsProps) { - const router = useRouter() - const [isModifyOpen, setIsModifyOpen] = React.useState(false) const [isDisposeOpen, setIsDisposeOpen] = React.useState(false) - const [isContractStatusOpen, setIsContractStatusOpen] = React.useState(false) // 폐기 버튼 클릭 const handleDispose = () => { @@ -34,22 +30,6 @@ export function GeneralContractTemplateToolbarActions({ setIsDisposeOpen(true) } - // 계약현황 버튼 클릭 - const handleContractStatus = () => { - if (selectedRows.length === 0) { - toast.error("확인할 문서를 선택해주세요.") - return - } - - if (selectedRows.length > 1) { - toast.error("한 번에 하나의 문서만 확인할 수 있습니다.") - return - } - - // 일반계약관리 페이지로 이동 - router.push(`/evcp/general-contracts`) - } - // 실제 폐기 처리 const handleConfirmDispose = async () => { try { @@ -76,17 +56,6 @@ export function GeneralContractTemplateToolbarActions({ {/* 신규등록: 다이얼로그 사용 */} <AddGeneralContractTemplateDialog /> - {/* 계약현황 버튼 */} - <Button - onClick={handleContractStatus} - variant="outline" - size="sm" - className="border-blue-600 text-blue-600 hover:bg-blue-50" - > - <FileText className="mr-2 h-4 w-4" /> - 계약현황 - </Button> - {/* 폐기 버튼 */} <Button onClick={handleDispose} |
