summaryrefslogtreecommitdiff
path: root/lib/rfq-last/vendor/rfq-vendor-table.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rfq-last/vendor/rfq-vendor-table.tsx')
-rw-r--r--lib/rfq-last/vendor/rfq-vendor-table.tsx234
1 files changed, 227 insertions, 7 deletions
diff --git a/lib/rfq-last/vendor/rfq-vendor-table.tsx b/lib/rfq-last/vendor/rfq-vendor-table.tsx
index 29aa5f09..fc98785d 100644
--- a/lib/rfq-last/vendor/rfq-vendor-table.tsx
+++ b/lib/rfq-last/vendor/rfq-vendor-table.tsx
@@ -58,6 +58,11 @@ import { AddVendorDialog } from "./add-vendor-dialog";
import { BatchUpdateConditionsDialog } from "./batch-update-conditions-dialog";
import { SendRfqDialog } from "./send-rfq-dialog";
import { CancelVendorResponseDialog } from "./cancel-vendor-response-dialog";
+import { ApprovalPreviewDialog } from "@/lib/approval/client";
+import { requestRfqSendWithApproval } from "../approval-actions";
+import { mapRfqSendToTemplateVariables } from "../approval-handlers";
+import { useSession } from "next-auth/react";
+import { ApplicationReasonDialog } from "./application-reason-dialog";
import {
getRfqSendData,
@@ -293,6 +298,22 @@ export function RfqVendorTable({
vendorName: string;
} | null>(null);
const [isCancelDialogOpen, setIsCancelDialogOpen] = React.useState(false);
+
+ // 결재 관련 상태
+ const [showApplicationReasonDialog, setShowApplicationReasonDialog] = React.useState(false);
+ const [showApprovalPreview, setShowApprovalPreview] = React.useState(false);
+ const [approvalPreviewData, setApprovalPreviewData] = React.useState<{
+ vendors: any[];
+ attachments: any[];
+ attachmentIds: number[];
+ message?: string;
+ generatedPdfs?: any[];
+ hasToSendEmail?: boolean;
+ templateVariables?: Record<string, string>;
+ applicationReason?: string;
+ } | null>(null);
+
+ const { data: session } = useSession();
// AVL 연동 핸들러
const handleAvlIntegration = React.useCallback(() => {
@@ -419,6 +440,57 @@ export function RfqVendorTable({
return;
}
+ const hasAttachments = rfqSendData.attachments && rfqSendData.attachments.length > 0;
+
+ // 🔹 첨부파일이 있는 경우: 결재 프로세스 시작
+ if (hasAttachments) {
+ // Knox EP ID 확인
+ if (!session?.user?.epId) {
+ toast.error("Knox EP ID가 없습니다. 시스템 관리자에게 문의하세요.");
+ setIsLoadingSendData(false);
+ return;
+ }
+
+ // 첨부파일 정보 변환
+ const attachmentsForApproval = rfqSendData.attachments.map((att: any) => ({
+ fileName: att.fileName,
+ fileSize: att.fileSize,
+ }));
+
+ // 결재 데이터 임시 저장 (신청사유 입력 전)
+ setApprovalPreviewData({
+ vendors: vendorEmailInfos.map(v => ({
+ vendorId: v.vendorId,
+ vendorName: v.vendorName,
+ vendorCode: v.vendorCode,
+ vendorCountry: v.vendorCountry,
+ selectedMainEmail: v.primaryEmail || v.vendorEmail || '',
+ additionalEmails: [],
+ customEmails: [],
+ currency: v.currency,
+ contractRequirements: {
+ ndaYn: v.ndaYn || false,
+ generalGtcYn: v.generalGtcYn || false,
+ projectGtcYn: v.projectGtcYn || false,
+ agreementYn: v.agreementYn || false,
+ },
+ isResend: v.sendVersion ? v.sendVersion > 0 : false,
+ sendVersion: v.sendVersion,
+ })),
+ attachments: attachmentsForApproval,
+ attachmentIds: rfqSendData.attachments.map((att: any) => att.id),
+ message: undefined,
+ generatedPdfs: undefined,
+ hasToSendEmail: true,
+ });
+
+ // 신청사유 입력 다이얼로그 먼저 열기
+ setShowApplicationReasonDialog(true);
+ setIsLoadingSendData(false);
+ return;
+ }
+
+ // 🔹 첨부파일이 없는 경우: 기존 로직 (바로 발송)
// 다이얼로그 데이터 설정
setSendDialogData({
rfqInfo: rfqSendData.rfqInfo,
@@ -450,7 +522,82 @@ export function RfqVendorTable({
} finally {
setIsLoadingSendData(false);
}
- }, [selectedRows, rfqId]);
+ }, [selectedRows, rfqId, session]);
+
+ // 신청사유 입력 완료 핸들러
+ const handleApplicationReasonConfirm = React.useCallback(async (reason: string) => {
+ if (!approvalPreviewData) {
+ toast.error("결재 데이터가 없습니다.");
+ return;
+ }
+
+ try {
+ // 템플릿 변수 생성 (신청사유 포함)
+ const templateVariables = await mapRfqSendToTemplateVariables({
+ attachments: approvalPreviewData.attachments,
+ vendorNames: approvalPreviewData.vendors.map(v => v.vendorName),
+ applicationReason: reason,
+ });
+
+ // 결재 미리보기 데이터 업데이트
+ setApprovalPreviewData({
+ ...approvalPreviewData,
+ templateVariables,
+ applicationReason: reason,
+ });
+
+ // 신청사유 다이얼로그 닫고 결재 미리보기 열기
+ setShowApplicationReasonDialog(false);
+ setShowApprovalPreview(true);
+ } catch (error) {
+ console.error("템플릿 변수 생성 실패:", error);
+ toast.error("결재 문서 생성에 실패했습니다.");
+ }
+ }, [approvalPreviewData]);
+
+ // 결재 미리보기 확인 핸들러
+ const handleApprovalConfirm = React.useCallback(async (approvalData: {
+ approvers: string[];
+ title: string;
+ description?: string;
+ }) => {
+ if (!approvalPreviewData || !session?.user) {
+ toast.error("결재 데이터가 없습니다.");
+ return;
+ }
+
+ try {
+ const result = await requestRfqSendWithApproval({
+ rfqId,
+ rfqCode,
+ vendors: approvalPreviewData.vendors,
+ attachmentIds: approvalPreviewData.attachmentIds,
+ attachments: approvalPreviewData.attachments,
+ message: approvalPreviewData.message,
+ generatedPdfs: approvalPreviewData.generatedPdfs,
+ hasToSendEmail: approvalPreviewData.hasToSendEmail,
+ applicationReason: approvalPreviewData.applicationReason || '',
+ currentUser: {
+ id: Number(session.user.id),
+ epId: session.user.epId || null,
+ name: session.user.name || undefined,
+ email: session.user.email || undefined,
+ },
+ approvers: approvalData.approvers,
+ });
+
+ if (result.success) {
+ toast.success(result.message);
+ setShowApprovalPreview(false);
+ setApprovalPreviewData(null);
+ setSelectedRows([]);
+ router.refresh();
+ }
+ } catch (error) {
+ console.error("결재 상신 실패:", error);
+ toast.error(error instanceof Error ? error.message : "결재 상신에 실패했습니다.");
+ }
+ }, [approvalPreviewData, session, rfqId, rfqCode, router]);
// RFQ 발송 핸들러
const handleSendRfq = React.useCallback(async (data: {
@@ -589,6 +736,53 @@ export function RfqVendorTable({
return;
}
+ const hasAttachments = rfqSendData.attachments && rfqSendData.attachments.length > 0;
+
+ // 🔹 첨부파일이 있는 경우: 결재 프로세스
+ if (hasAttachments) {
+ if (!session?.user?.epId) {
+ toast.error("Knox EP ID가 없습니다. 시스템 관리자에게 문의하세요.");
+ setIsLoadingSendData(false);
+ return;
+ }
+
+ const attachmentsForApproval = rfqSendData.attachments.map((att: any) => ({
+ fileName: att.fileName,
+ fileSize: att.fileSize,
+ }));
+
+ setApprovalPreviewData({
+ vendors: vendorEmailInfos.map(v => ({
+ vendorId: v.vendorId,
+ vendorName: v.vendorName,
+ vendorCode: v.vendorCode,
+ vendorCountry: v.vendorCountry,
+ selectedMainEmail: v.primaryEmail || v.vendorEmail || '',
+ additionalEmails: [],
+ customEmails: [],
+ currency: v.currency,
+ contractRequirements: {
+ ndaYn: v.ndaYn || false,
+ generalGtcYn: v.generalGtcYn || false,
+ projectGtcYn: v.projectGtcYn || false,
+ agreementYn: v.agreementYn || false,
+ },
+ isResend: v.sendVersion ? v.sendVersion > 0 : false,
+ sendVersion: v.sendVersion,
+ })),
+ attachments: attachmentsForApproval,
+ attachmentIds: rfqSendData.attachments.map((att: any) => att.id),
+ message: undefined,
+ generatedPdfs: undefined,
+ hasToSendEmail: true,
+ });
+
+ setShowApplicationReasonDialog(true);
+ setIsLoadingSendData(false);
+ return;
+ }
+
+ // 🔹 첨부파일이 없는 경우: 기존 로직
setSendDialogData({
rfqInfo: rfqSendData.rfqInfo,
attachments: rfqSendData.attachments || [],
@@ -1843,16 +2037,11 @@ export function RfqVendorTable({
/>
)}
- {/* AVL 벤더 연동 다이얼로그 */}
+ {/* AVL 벤더 조회 다이얼로그 */}
<AvlVendorDialog
open={isAvlDialogOpen}
onOpenChange={setIsAvlDialogOpen}
rfqId={rfqId}
- rfqCode={rfqCode}
- onSuccess={() => {
- setIsAvlDialogOpen(false);
- router.refresh();
- }}
/>
{/* 연동제 정보 다이얼로그 */}
@@ -1888,6 +2077,37 @@ export function RfqVendorTable({
toast.success("RFQ 취소가 완료되었습니다.");
}}
/>
+
+ {/* 신청사유 입력 다이얼로그 */}
+ {approvalPreviewData && (
+ <ApplicationReasonDialog
+ open={showApplicationReasonDialog}
+ onOpenChange={setShowApplicationReasonDialog}
+ onConfirm={handleApplicationReasonConfirm}
+ vendorCount={approvalPreviewData.vendors.length}
+ attachmentCount={approvalPreviewData.attachmentIds.length}
+ />
+ )}
+
+ {/* 결재 미리보기 다이얼로그 */}
+ {approvalPreviewData && session?.user?.epId && approvalPreviewData.templateVariables && (
+ <ApprovalPreviewDialog
+ open={showApprovalPreview}
+ onOpenChange={setShowApprovalPreview}
+ templateName="암호화해제 신청"
+ variables={approvalPreviewData.templateVariables}
+ title={`암호화해제 신청 - ${rfqCode || 'RFQ'}`}
+ currentUser={{
+ id: Number(session.user.id),
+ epId: session.user.epId,
+ name: session.user.name || undefined,
+ email: session.user.email || undefined,
+ }}
+ onConfirm={handleApprovalConfirm}
+ allowTitleEdit={false}
+ allowDescriptionEdit={false}
+ />
+ )}
</>
);
} \ No newline at end of file