"use client" import * as React from "react" import { type Table } from "@tanstack/react-table" import { Download, ClipboardCheck, X, Send, RefreshCw } from "lucide-react" import { toast } from "sonner" import { useSession } from "next-auth/react" import { exportTableToExcel } from "@/lib/export" import { Button } from "@/components/ui/button" import { PQSubmission } from "./vendors-table-columns" import { cancelInvestigationAction, sendInvestigationResultsAction, getFactoryLocationAnswer, getQMManagers } from "@/lib/pq/service" import { SiteVisitDialog } from "./site-visit-dialog" import type { SiteVisitRequestFormValues } from "./site-visit-dialog" import { RequestInvestigationDialog } from "./request-investigation-dialog" import { CancelInvestigationDialog, ReRequestInvestigationDialog } from "./cancel-investigation-dialog" import { SendResultsDialog } from "./send-results-dialog" import { ApprovalPreviewDialog } from "@/components/approval/ApprovalPreviewDialog" import { requestPQInvestigationWithApproval, reRequestPQInvestigationWithApproval } from "@/lib/vendor-investigation/approval-actions" import type { ApprovalLineItem } from "@/components/knox/approval/ApprovalLineSelector" import { debugLog, debugError, debugSuccess } from "@/lib/debug-utils" interface VendorsTableToolbarActionsProps { table: Table } interface InvestigationInitialData { investigationMethod?: "PURCHASE_SELF_EVAL" | "DOCUMENT_EVAL" | "PRODUCT_INSPECTION" | "SITE_VISIT_EVAL"; qmManagerId?: number; forecastedAt?: Date; createdAt?: Date; investigationAddress?: string; investigationNotes?: string; } export function VendorsTableToolbarActions({ table }: VendorsTableToolbarActionsProps) { const selectedRows = table.getFilteredSelectedRowModel().rows const [isLoading, setIsLoading] = React.useState(false) const { data: session } = useSession() // Dialog 상태 관리 const [isRequestDialogOpen, setIsRequestDialogOpen] = React.useState(false) const [isCancelDialogOpen, setIsCancelDialogOpen] = React.useState(false) const [isSendResultsDialogOpen, setIsSendResultsDialogOpen] = React.useState(false) const [isReRequestDialogOpen, setIsReRequestDialogOpen] = React.useState(false) const [isReinspectionDialogOpen, setIsReinspectionDialogOpen] = React.useState(false) const [isApprovalDialogOpen, setIsApprovalDialogOpen] = React.useState(false) const [isReRequestApprovalDialogOpen, setIsReRequestApprovalDialogOpen] = React.useState(false) // 초기 데이터 상태 const [dialogInitialData, setDialogInitialData] = React.useState(undefined) // 실사 의뢰 임시 데이터 (결재 다이얼로그로 전달) const [investigationFormData, setInvestigationFormData] = React.useState<{ qmManagerId: number; qmManagerName: string; qmManagerEmail?: string; forecastedAt: Date; investigationAddress: string; investigationNotes?: string; } | null>(null) // 실사 재의뢰 임시 데이터 const [reRequestData, setReRequestData] = React.useState<{ investigationIds: number[]; vendorNames: string; } | null>(null) // 결재 템플릿 변수 const [approvalVariables, setApprovalVariables] = React.useState>({}) const [reRequestApprovalVariables, setReRequestApprovalVariables] = React.useState>({}) // 실사 의뢰 대화상자 열기 핸들러 // 실사 의뢰 대화상자 열기 핸들러 const handleOpenRequestDialog = async () => { setIsLoading(true); const initialData: InvestigationInitialData = {}; try { // 선택된 행이 정확히 1개인 경우에만 초기값 설정 if (selectedRows.length === 1) { const row = selectedRows[0].original; // 승인된 PQ이고 아직 실사가 없는 경우 if (row.status === "APPROVED" && !row.investigation) { // Factory Location 정보 가져오기 const locationResponse = await getFactoryLocationAnswer( row.vendorId, row.projectId ); // 기본 주소 설정 - Factory Location 응답 또는 fallback let defaultAddress = ""; if (locationResponse.success && locationResponse.factoryLocation) { defaultAddress = locationResponse.factoryLocation; } else { // Factory Location을 찾지 못한 경우 fallback defaultAddress = row.taxId ? `${row.vendorName} 사업장 (${row.taxId})` : `${row.vendorName} 사업장`; } // 이미 같은 회사에 대한 다른 실사가 있는지 확인 const existingInvestigations = table.getFilteredRowModel().rows .map(r => r.original) .filter(r => r.vendorId === row.vendorId && r.investigation !== null ); // 같은 업체의 이전 실사 기록이 있다면 참고하되, 주소는 Factory Location 사용 if (existingInvestigations.length > 0) { // 날짜 기준으로 정렬하여 가장 최근 것을 가져옴 const latestInvestigation = existingInvestigations.sort((a, b) => { const dateA = a.investigation?.createdAt || new Date(0); const dateB = b.investigation?.createdAt || new Date(0); return (dateB as Date).getTime() - (dateA as Date).getTime(); })[0].investigation; if (latestInvestigation) { initialData.investigationMethod = latestInvestigation.investigationMethod || undefined; initialData.qmManagerId = latestInvestigation.qmManagerId || undefined; initialData.investigationAddress = defaultAddress; // Factory Location 사용 // 날짜는 미래로 설정 const futureDate = new Date(); futureDate.setDate(futureDate.getDate() + 14); // 기본값으로 2주 후 initialData.forecastedAt = futureDate; } } else { // 기본값 설정 initialData.investigationMethod = undefined; const futureDate = new Date(); futureDate.setDate(futureDate.getDate() + 14); // 기본값으로 2주 후 initialData.forecastedAt = futureDate; initialData.investigationAddress = defaultAddress; // Factory Location 사용 } } // 실사가 이미 있고 수정하는 경우 // else if (row.investigation) { // initialData.investigationMethod = row.investigation.investigationMethod || undefined; // initialData.qmManagerId = row.investigation.qmManagerId !== null ? // row.investigation.qmManagerId : undefined; // initialData.forecastedAt = row.investigation.forecastedAt || new Date(); // initialData.investigationAddress = row.investigation.investigationAddress || ""; // initialData.investigationNotes = row.investigation.investigationNotes || ""; // } } } catch (error) { console.error("초기 데이터 로드 중 오류:", error); toast.error("초기 데이터 로드 중 오류가 발생했습니다."); } finally { setIsLoading(false); // 초기 데이터 설정 및 대화상자 열기 setDialogInitialData(Object.keys(initialData).length > 0 ? initialData : undefined); setIsRequestDialogOpen(true); } }; // 실사 의뢰 요청 처리 - Step 1: RequestInvestigationDialog에서 정보 입력 후 const handleRequestInvestigation = async (formData: { qmManagerId: number, forecastedAt: Date, investigationAddress: string, investigationNotes?: string }) => { try { // 승인된 PQ 제출만 필터링 (미실사 PQ 제외) const approvedPQs = selectedRows.filter(row => row.original.status === "APPROVED" && !row.original.investigation && row.original.type !== "NON_INSPECTION" ) if (approvedPQs.length === 0) { if (hasNonInspectionPQ) { toast.error("미실사 PQ는 실사 의뢰할 수 없습니다. 미실사 PQ를 제외하고 선택해주세요.") } else { toast.error("실사를 의뢰할 수 있는 업체가 없습니다. 승인된 PQ 제출만 실사 의뢰가 가능합니다.") } return } // QM 담당자 이름 및 이메일 조회 const qmManagersResult = await getQMManagers() const qmManager = qmManagersResult.success ? qmManagersResult.data.find(m => m.id === formData.qmManagerId) : null const qmManagerName = qmManager?.name || `QM담당자 #${formData.qmManagerId}` const qmManagerEmail = qmManager?.email || undefined // 협력사 이름 목록 생성 const vendorNames = approvedPQs .map(row => row.original.vendorName) .join(', ') // 실사 폼 데이터 저장 (이메일 추가) setInvestigationFormData({ qmManagerId: formData.qmManagerId, qmManagerName, qmManagerEmail, forecastedAt: formData.forecastedAt, investigationAddress: formData.investigationAddress, investigationNotes: formData.investigationNotes, }) // 결재 템플릿 변수 생성 const requestedAt = new Date() const { mapPQInvestigationToTemplateVariables } = await import('@/lib/vendor-investigation/handlers') const variables = await mapPQInvestigationToTemplateVariables({ vendorNames, qmManagerName, qmManagerEmail, forecastedAt: formData.forecastedAt, investigationAddress: formData.investigationAddress, investigationNotes: formData.investigationNotes, requestedAt, }) setApprovalVariables(variables) // RequestInvestigationDialog 닫고 ApprovalPreviewDialog 열기 setIsRequestDialogOpen(false) setIsApprovalDialogOpen(true) } catch (error) { console.error("결재 준비 중 오류 발생:", error) toast.error("결재 준비 중 오류가 발생했습니다.") } } // 실사 의뢰 결재 요청 처리 - Step 2: ApprovalPreviewDialog에서 결재선 선택 후 const handleApprovalSubmit = async (approvers: ApprovalLineItem[]) => { debugLog('[InvestigationApproval] 실사 의뢰 결재 요청 시작', { approversCount: approvers.length, hasSession: !!session?.user, hasFormData: !!investigationFormData, }); if (!session?.user || !investigationFormData) { debugError('[InvestigationApproval] 세션 또는 폼 데이터 없음'); throw new Error('세션 정보가 없습니다.'); } // 승인된 PQ 제출만 필터링 const approvedPQs = selectedRows.filter(row => row.original.status === "APPROVED" && !row.original.investigation && row.original.type !== "NON_INSPECTION" ) debugLog('[InvestigationApproval] 승인된 PQ 건수', { count: approvedPQs.length, }); // 협력사 이름 목록 const vendorNames = approvedPQs .map(row => row.original.vendorName) .join(', ') // 결재선에서 EP ID 추출 (상신자 제외) const approverEpIds = approvers .filter((line) => line.seq !== "0" && line.epId) .map((line) => line.epId!) debugLog('[InvestigationApproval] 결재선 추출 완료', { approverEpIds, }); // 결재 워크플로우 시작 const result = await requestPQInvestigationWithApproval({ pqSubmissionIds: approvedPQs.map(row => row.original.id), vendorNames, qmManagerId: investigationFormData.qmManagerId, qmManagerName: investigationFormData.qmManagerName, qmManagerEmail: investigationFormData.qmManagerEmail, forecastedAt: investigationFormData.forecastedAt, investigationAddress: investigationFormData.investigationAddress, investigationNotes: investigationFormData.investigationNotes, currentUser: { id: Number(session.user.id), epId: session.user.epId || null, email: session.user.email || undefined, }, approvers: approverEpIds, }) debugSuccess('[InvestigationApproval] 결재 요청 성공', { approvalId: result.approvalId, pendingActionId: result.pendingActionId, }); if (result.status === 'pending_approval') { // 성공 시에만 상태 초기화 및 페이지 리로드 setInvestigationFormData(null) setDialogInitialData(undefined) window.location.reload() } } const handleCloseRequestDialog = () => { setIsRequestDialogOpen(false); setDialogInitialData(undefined); }; // 실사 의뢰 취소 처리 const handleCancelInvestigation = async () => { setIsLoading(true) try { // 실사가 계획됨 상태인 PQ만 필터링 const plannedInvestigations = selectedRows.filter(row => row.original.investigation && row.original.investigation.investigationStatus === "PLANNED" ) if (plannedInvestigations.length === 0) { toast.error("취소할 수 있는 실사 의뢰가 없습니다. 계획 상태의 실사만 취소할 수 있습니다.") return } // 서버 액션 호출 const result = await cancelInvestigationAction( plannedInvestigations.map(row => row.original.investigation!.id) ) if (result.success) { toast.success(`${result.count}개 업체에 대한 실사 의뢰가 취소되었습니다.`) window.location.reload() } else { toast.error(result.error || "실사 취소 처리 중 오류가 발생했습니다.") } } catch (error) { console.error("실사 의뢰 취소 중 오류 발생:", error) toast.error("실사 의뢰 취소 중 오류가 발생했습니다.") } finally { setIsLoading(false) setIsCancelDialogOpen(false) } } // 실사 재의뢰 처리 - Step 1: 확인 다이얼로그에서 확인 후 const handleReRequestInvestigation = async (reason?: string) => { try { // 취소된 실사만 필터링 const canceledInvestigations = selectedRows.filter(row => row.original.investigation && row.original.investigation.investigationStatus === "CANCELED" ) if (canceledInvestigations.length === 0) { toast.error("재의뢰할 수 있는 실사가 없습니다. 취소 상태의 실사만 재의뢰할 수 있습니다.") return } // 협력사 이름 목록 생성 const vendorNames = canceledInvestigations .map(row => row.original.vendorName) .join(', ') // 재의뢰 데이터 저장 const investigationIds = canceledInvestigations.map(row => row.original.investigation!.id) setReRequestData({ investigationIds, vendorNames, }) // 결재 템플릿 변수 생성 const reRequestedAt = new Date() const { mapPQReRequestToTemplateVariables } = await import('@/lib/vendor-investigation/handlers') const variables = await mapPQReRequestToTemplateVariables({ vendorNames, investigationCount: investigationIds.length, reRequestedAt, reason, }) setReRequestApprovalVariables(variables) // ReRequestInvestigationDialog 닫고 ApprovalPreviewDialog 열기 setIsReRequestDialogOpen(false) setIsReRequestApprovalDialogOpen(true) } catch (error) { console.error("재의뢰 결재 준비 중 오류 발생:", error) toast.error("재의뢰 결재 준비 중 오류가 발생했습니다.") } } // 실사 재의뢰 결재 요청 처리 - Step 2: ApprovalPreviewDialog에서 결재선 선택 후 const handleReRequestApprovalSubmit = async (approvers: ApprovalLineItem[]) => { debugLog('[ReRequestApproval] 실사 재의뢰 결재 요청 시작', { approversCount: approvers.length, hasSession: !!session?.user, hasReRequestData: !!reRequestData, }); if (!session?.user || !reRequestData) { debugError('[ReRequestApproval] 세션 또는 재의뢰 데이터 없음'); throw new Error('세션 정보가 없습니다.'); } debugLog('[ReRequestApproval] 재의뢰 대상', { investigationIds: reRequestData.investigationIds, vendorNames: reRequestData.vendorNames, }); // 결재선에서 EP ID 추출 (상신자 제외) const approverEpIds = approvers .filter((line) => line.seq !== "0" && line.epId) .map((line) => line.epId!) debugLog('[ReRequestApproval] 결재선 추출 완료', { approverEpIds, }); // 결재 워크플로우 시작 const result = await reRequestPQInvestigationWithApproval({ investigationIds: reRequestData.investigationIds, vendorNames: reRequestData.vendorNames, currentUser: { id: Number(session.user.id), epId: session.user.epId || null, email: session.user.email || undefined, }, approvers: approverEpIds, }) debugSuccess('[ReRequestApproval] 재의뢰 결재 요청 성공', { approvalId: result.approvalId, pendingActionId: result.pendingActionId, }); if (result.status === 'pending_approval') { // 성공 시에만 상태 초기화 및 페이지 리로드 setReRequestData(null) window.location.reload() } } // 재실사 요청 처리 const handleRequestReinspection = async ( data: SiteVisitRequestFormValues, attachments?: File[] ) => { try { // 보완-재실사 대상 실사만 필터링 const supplementReinspectInvestigations = selectedRows.filter(row => row.original.investigation && row.original.investigation.evaluationResult === "SUPPLEMENT_REINSPECT" ); if (supplementReinspectInvestigations.length === 0) { toast.error("보완-재실사 대상 실사가 없습니다."); return; } // 첫 번째 대상 실사로 재실사 요청 생성 const targetRow = supplementReinspectInvestigations[0].original; const targetInvestigation = targetRow.investigation!; const { requestSupplementReinspectionAction } = await import('@/lib/vendor-investigation/service'); // SiteVisitRequestFormValues를 requestSupplementReinspectionAction 형식으로 변환 // shiAttendees는 그대로 전달 (새로운 형식: {checked, attendees}) const result = await requestSupplementReinspectionAction({ investigationId: targetInvestigation.id, siteVisitData: { inspectionDuration: data.inspectionDuration, requestedStartDate: data.requestedStartDate, requestedEndDate: data.requestedEndDate, shiAttendees: data.shiAttendees || {}, vendorRequests: data.vendorRequests || {}, additionalRequests: data.additionalRequests || "", }, }); if (result.success) { toast.success("재실사 요청이 생성되었습니다."); setIsReinspectionDialogOpen(false); window.location.reload(); } else { toast.error(result.error || "재실사 요청 생성 중 오류가 발생했습니다."); } } catch (error) { console.error("재실사 요청 오류:", error); toast.error("재실사 요청 중 오류가 발생했습니다."); } }; // 실사 결과 발송 처리 const handleSendInvestigationResults = async (data: { purchaseComment?: string }) => { try { setIsLoading(true) // 완료된 실사 중 승인된 결과 또는 보완된 결과만 필터링 const approvedInvestigations = selectedRows.filter(row => { const investigation = row.original.investigation return investigation && (investigation.investigationStatus === "COMPLETED" || investigation.investigationStatus === "SUPPLEMENT_REQUIRED" || investigation.evaluationResult === "REJECTED") }) if (approvedInvestigations.length === 0) { toast.error("발송할 실사 결과가 없습니다. 완료되고 승인된 실사만 결과를 발송할 수 있습니다.") return } // 서버 액션 호출 const result = await sendInvestigationResultsAction({ investigationIds: approvedInvestigations.map(row => row.original.investigation!.id), purchaseComment: data.purchaseComment, }) if (result.success) { toast.success(result.message || `${result.data?.successCount || 0}개 업체에 대한 실사 결과가 발송되었습니다.`) window.location.reload() } else { toast.error(result.error || "실사 결과 발송 처리 중 오류가 발생했습니다.") } } catch (error) { console.error("실사 결과 발송 중 오류 발생:", error) toast.error("실사 결과 발송 중 오류가 발생했습니다.") } finally { setIsLoading(false) setIsSendResultsDialogOpen(false) } } // 승인된 업체 수 확인 (미실사 PQ 제외) const approvedPQsCount = selectedRows.filter(row => row.original.status === "APPROVED" && !row.original.investigation && row.original.type !== "NON_INSPECTION" ).length // 계획 상태 실사 수 확인 const plannedInvestigationsCount = selectedRows.filter(row => row.original.investigation && row.original.investigation.investigationStatus === "PLANNED" ).length // 완료된 실사 수 확인 (승인된 결과만) const completedInvestigationsCount = selectedRows.filter(row => row.original.investigation && row.original.investigation.investigationStatus === "COMPLETED" && row.original.investigation.evaluationResult === "APPROVED" ).length // 취소된 실사 수 확인 const canceledInvestigationsCount = selectedRows.filter(row => row.original.investigation && row.original.investigation.investigationStatus === "CANCELED" ).length // 재실사 요청 대상 수 확인 (보완-재실사 결과만) const reinspectInvestigationsCount = selectedRows.filter(row => row.original.investigation && row.original.investigation.evaluationResult === "SUPPLEMENT_REINSPECT" ).length // 재실사 요청 가능 여부 확인 (방문실사평가 또는 제품검사평가만 가능) const canRequestReinspection = selectedRows.some(row => { const investigation = row.original.investigation if (!investigation) return false if (investigation.evaluationResult !== "SUPPLEMENT_REINSPECT") return false const method = investigation.investigationMethod // 서류평가 또는 구매자체평가는 재방문실사 불가 return method === "SITE_VISIT_EVAL" || method === "PRODUCT_INSPECTION" }) // 미실사 PQ가 선택되었는지 확인 const hasNonInspectionPQ = selectedRows.some(row => row.original.type === "NON_INSPECTION" ) // 실사 방법 라벨 변환 함수 const getInvestigationMethodLabel = (method: string): string => { switch (method) { case "PURCHASE_SELF_EVAL": return "구매자체평가" case "DOCUMENT_EVAL": return "서류평가" case "PRODUCT_INSPECTION": return "제품검사평가" case "SITE_VISIT_EVAL": return "방문실사평가" default: return method } } // 실사 결과 발송용 데이터 준비 const auditResults = selectedRows .filter(row => row.original.investigation && (row.original.investigation.investigationStatus === "COMPLETED" || row.original.investigation.investigationStatus === "SUPPLEMENT_REQUIRED") && ( (row.original.investigation.evaluationResult === "APPROVED" || row.original.investigation.evaluationResult === "SUPPLEMENT" || row.original.investigation.evaluationResult === "SUPPLEMENT_REINSPECT" || row.original.investigation.evaluationResult === "SUPPLEMENT_DOCUMENT")) ) .map(row => { const investigation = row.original.investigation! const pqSubmission = row.original // pqItems를 상세하게 포맷팅 (itemCode-itemName 형태로 모든 항목 표시) const formatAuditItem = (pqItems: any): string => { if (!pqItems) return pqSubmission.projectName || "N/A"; try { // 이미 파싱된 객체 배열인 경우 if (Array.isArray(pqItems)) { return pqItems.map(item => { if (typeof item === 'string') return item; if (typeof item === 'object') { const code = item.itemCode || item.code || ""; const name = item.itemName || item.name || ""; if (code && name) return `${code}-${name}`; return name || code || String(item); } return String(item); }).join(', '); } // JSON 문자열인 경우 if (typeof pqItems === 'string') { try { const parsed = JSON.parse(pqItems); if (Array.isArray(parsed)) { return parsed.map(item => { if (typeof item === 'string') return item; if (typeof item === 'object') { const code = item.itemCode || item.code || ""; const name = item.itemName || item.name || ""; if (code && name) return `${code}-${name}`; return name || code || String(item); } return String(item); }).join(', '); } return String(parsed); } catch { return String(pqItems); } } // 기타 경우 return String(pqItems); } catch { return pqSubmission.projectName || "N/A"; } }; return { id: investigation.id, vendorCode: row.original.vendorCode || "N/A", vendorName: row.original.vendorName || "N/A", vendorEmail: row.original.email || "N/A", vendorContactPerson: (row.original as any).representativeName || row.original.vendorName || "N/A", pqNumber: pqSubmission.pqNumber || "N/A", auditItem: formatAuditItem(pqSubmission.pqItems), auditFactoryAddress: investigation.investigationAddress || "N/A", auditMethod: getInvestigationMethodLabel(investigation.investigationMethod || ""), auditResult: investigation.evaluationResult === "APPROVED" ? "Pass(승인)" : investigation.evaluationResult === "SUPPLEMENT" ? "Pass(조건부승인)" : investigation.evaluationResult === "REJECTED" ? "Fail(미승인)" : "N/A", additionalNotes: investigation.investigationNotes || undefined, investigationNotes: investigation.investigationNotes || undefined, } }) return ( <>
{/* 실사 의뢰 버튼 */} {/* 실사 의뢰 취소 버튼 */} {/* 실사 재의뢰 버튼 */} {/* 재실사 요청 버튼 */} {/* 실사 결과 발송 버튼 */} {/** Export 버튼 */}
{/* 실사 의뢰 Dialog */} {/* 실사 취소 Dialog */} setIsCancelDialogOpen(false)} onConfirm={handleCancelInvestigation} selectedCount={plannedInvestigationsCount} /> {/* 실사 재의뢰 Dialog */} setIsReRequestDialogOpen(false)} onConfirm={handleReRequestInvestigation} selectedCount={canceledInvestigationsCount} /> {/* 결과 발송 Dialog */} setIsSendResultsDialogOpen(false)} onConfirm={handleSendInvestigationResults} selectedCount={completedInvestigationsCount} auditResults={auditResults} /> {/* 재방문실사 요청 Dialog */} {(() => { // 보완-재실사 대상 실사 찾기 const supplementReinspectInvestigations = selectedRows.filter(row => row.original.investigation && row.original.investigation.evaluationResult === "SUPPLEMENT_REINSPECT" ); if (supplementReinspectInvestigations.length === 0) { return null; } const targetRow = supplementReinspectInvestigations[0].original; const targetInvestigation = targetRow.investigation!; return ( setIsReinspectionDialogOpen(false)} onSubmit={handleRequestReinspection} investigation={{ id: targetInvestigation.id, investigationMethod: targetInvestigation.investigationMethod || undefined, investigationAddress: targetInvestigation.investigationAddress || undefined, investigationNotes: targetInvestigation.investigationNotes || undefined, vendorName: targetRow.vendorName, vendorCode: targetRow.vendorCode, projectName: targetRow.projectName || undefined, projectCode: targetRow.projectCode || undefined, pqItems: targetRow.pqItems || null, }} isReinspection={true} /> ); })()} {/* 결재 미리보기 Dialog - 실사 의뢰 */} {session?.user && investigationFormData && ( { setIsApprovalDialogOpen(open) if (!open) { // 다이얼로그가 닫히면 실사 폼 데이터도 초기화 setInvestigationFormData(null) } }} templateName="Vendor 실사의뢰" variables={approvalVariables} title={`Vendor 실사의뢰 - ${selectedRows.filter(row => row.original.status === "APPROVED" && !row.original.investigation && row.original.type !== "NON_INSPECTION" ).map(row => row.original.vendorName).join(', ')}`} description={`${approvedPQsCount}개 업체에 대한 실사 의뢰`} currentUser={{ id: Number(session.user.id), epId: session.user.epId || null, name: session.user.name || null, email: session.user.email || '', }} onSubmit={handleApprovalSubmit} /> )} {/* 결재 미리보기 Dialog - 실사 재의뢰 */} {session?.user && reRequestData && ( { setIsReRequestApprovalDialogOpen(open) if (!open) { // 다이얼로그가 닫히면 재의뢰 데이터도 초기화 setReRequestData(null) } }} templateName="Vendor 실사 재의뢰" variables={reRequestApprovalVariables} title={`Vendor 실사 재의뢰 - ${reRequestData.vendorNames}`} description={`${reRequestData.investigationIds.length}개 업체에 대한 실사 재의뢰`} currentUser={{ id: Number(session.user.id), epId: session.user.epId || null, name: session.user.name || null, email: session.user.email || '', }} onSubmit={handleReRequestApprovalSubmit} /> )} ) }