From d79f56ae5a9e5f72781f78fe0399018cfac44081 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 24 Nov 2025 05:00:38 +0000 Subject: (최겸) 기술영업 결재 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/techsales-rfq/approval-actions.ts | 23 +++++++++++++++++++++ lib/techsales-rfq/approval-handlers.ts | 12 ++++++++--- lib/techsales-rfq/service.ts | 24 +++++++++------------- .../table/detail-table/rfq-detail-table.tsx | 1 + 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/techsales-rfq/approval-actions.ts b/lib/techsales-rfq/approval-actions.ts index 175bca1d..335be760 100644 --- a/lib/techsales-rfq/approval-actions.ts +++ b/lib/techsales-rfq/approval-actions.ts @@ -8,11 +8,13 @@ import { ApprovalSubmissionSaga } from '@/lib/approval'; import { mapTechSalesRfqSendToTemplateVariables } from './approval-handlers'; +import { revalidatePath, revalidateTag } from 'next/cache'; interface TechSalesRfqSendApprovalData { // RFQ 기본 정보 rfqId: number; rfqCode?: string; + rfqType: "SHIP" | "TOP" | "HULL"; // 발송 데이터 vendorIds: number[]; @@ -133,6 +135,10 @@ export async function requestTechSalesRfqSendWithApproval(data: TechSalesRfqSend console.log('[TechSales RFQ Approval] ✅ Approval submitted successfully'); console.log('[TechSales RFQ Approval] Approval ID:', result.approvalId); console.log('[TechSales RFQ Approval] Pending Action ID:', result.pendingActionId); + revalidateTag("techSalesRfqs"); + revalidateTag("techSalesVendorQuotations"); + revalidateTag(`techSalesRfq-${data.rfqId}`); + revalidatePath(getTechSalesRevalidationPath(data.rfqType || "SHIP")); return { success: true, @@ -150,6 +156,21 @@ export async function requestTechSalesRfqSendWithApproval(data: TechSalesRfqSend } } +/** + * RFQ 타입에 따른 캐시 무효화 경로 반환 + */ +function getTechSalesRevalidationPath(rfqType: "SHIP" | "TOP" | "HULL"): string { + switch (rfqType) { + case "SHIP": + return "/evcp/budgetary-tech-sales-ship"; + case "TOP": + return "/evcp/budgetary-tech-sales-top"; + case "HULL": + return "/evcp/budgetary-tech-sales-hull"; + default: + return "/evcp/budgetary-tech-sales-ship"; + } +} /** * 기술영업 RFQ 재발송 결재 상신 * @@ -203,6 +224,7 @@ export async function requestRfqResendWithDrmApproval(data: { epId: data.currentUser.epId, }, }; + console.log('approvalPayload', approvalPayload); // Saga로 결재 상신 const saga = new ApprovalSubmissionSaga( @@ -216,6 +238,7 @@ export async function requestRfqResendWithDrmApproval(data: { approvers: data.approvers, currentUser: { id: data.currentUser.id, + name: data.currentUser.name, epId: data.currentUser.epId, email: data.currentUser.email, }, diff --git a/lib/techsales-rfq/approval-handlers.ts b/lib/techsales-rfq/approval-handlers.ts index 0d4629e4..979096b7 100644 --- a/lib/techsales-rfq/approval-handlers.ts +++ b/lib/techsales-rfq/approval-handlers.ts @@ -54,10 +54,14 @@ export async function sendTechSalesRfqWithApprovalInternal(payload: { for (const attachment of drmAttachments) { try { - // DRM 파일 다운로드 - const fileResponse = await fetch(attachment.filePath); + // DRM 파일 다운로드 - 상대 경로를 절대 URL로 변환 + let fileUrl = attachment.filePath; + const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || process.env.NEXT_PUBLIC_URL; + fileUrl = `${baseUrl}${fileUrl}`; + console.log(`[TechSales RFQ Approval Handler] Fetching file from: ${fileUrl}`); + const fileResponse = await fetch(fileUrl); if (!fileResponse.ok) { - console.error(`[TechSales RFQ Approval Handler] Failed to fetch file: ${attachment.filePath}`); + console.error(`[TechSales RFQ Approval Handler] Failed to fetch file: ${fileUrl} (status: ${fileResponse.status})`); continue; } @@ -103,6 +107,7 @@ export async function sendTechSalesRfqWithApprovalInternal(payload: { rfqId: payload.rfqId, vendorIds: payload.vendorIds, selectedContacts: payload.selectedContacts, + currentUser: payload.currentUser, }); console.log('[TechSales RFQ Approval Handler] ✅ RFQ sent successfully after DRM decryption'); @@ -224,6 +229,7 @@ export async function resendTechSalesRfqWithDrmInternal(payload: { const sendResult = await sendTechSalesRfqToVendors({ rfqId: payload.rfqId, vendorIds: vendorIds, + currentUser: payload.currentUser, }); console.log('[TechSales RFQ Resend Handler] ✅ RFQ resent successfully after DRM decryption'); diff --git a/lib/techsales-rfq/service.ts b/lib/techsales-rfq/service.ts index ed3472b1..6f2d7914 100644 --- a/lib/techsales-rfq/service.ts +++ b/lib/techsales-rfq/service.ts @@ -551,19 +551,15 @@ export async function sendTechSalesRfqToVendors(input: { contactEmail: string; contactName: string; }>; + currentUser: { + id: string | number; + name?: string | null; + email?: string | null; + epId?: string | null; + }; }) { unstable_noStore(); try { - // 인증 확인 - const session = await getServerSession(authOptions); - - if (!session?.user) { - return { - success: false, - message: "인증이 필요합니다", - }; - } - // RFQ 정보 조회 const rfq = await db.query.techSalesRfqs.findFirst({ where: eq(techSalesRfqs.id, input.rfqId), @@ -611,7 +607,7 @@ export async function sendTechSalesRfqToVendors(input: { // 현재 사용자 정보 조회 const sender = await db.query.users.findFirst({ - where: eq(users.id, Number(session.user.id)), + where: eq(users.id, Number(input.currentUser.id)), columns: { id: true, email: true, @@ -661,8 +657,8 @@ export async function sendTechSalesRfqToVendors(input: { // 1. RFQ 상태 업데이트 (최초 발송인 경우 rfqSendDate 설정) const updateData: Partial = { status: TECH_SALES_RFQ_STATUSES.RFQ_SENT, - sentBy: Number(session.user.id), - updatedBy: Number(session.user.id), + sentBy: Number(input.currentUser.id), + updatedBy: Number(input.currentUser.id), updatedAt: new Date(), }; @@ -681,7 +677,7 @@ export async function sendTechSalesRfqToVendors(input: { await tx.update(techSalesVendorQuotations) .set({ status: "Draft", - updatedBy: Number(session.user.id), + updatedBy: Number(input.currentUser.id), updatedAt: new Date(), }) .where(eq(techSalesVendorQuotations.id, quotation.id)); diff --git a/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx b/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx index db2331af..28b281f4 100644 --- a/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx +++ b/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx @@ -513,6 +513,7 @@ export function RfqDetailTables({ selectedRfq, maxHeight }: RfqDetailTablesProps const result = await requestTechSalesRfqSendWithApproval({ rfqId: selectedRfq.id, rfqCode: selectedRfq.rfqCode || undefined, + rfqType: selectedRfq.rfqType || "SHIP", vendorIds: approvalPreviewData.vendors.map(v => v.vendorId), selectedContacts: approvalPreviewData.selectedContacts, drmAttachmentIds: approvalPreviewData.drmAttachmentIds, -- cgit v1.2.3