diff options
Diffstat (limited to 'lib/tbe-last/service.ts')
| -rw-r--r-- | lib/tbe-last/service.ts | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/lib/tbe-last/service.ts b/lib/tbe-last/service.ts index d9046524..32d5a5f5 100644 --- a/lib/tbe-last/service.ts +++ b/lib/tbe-last/service.ts @@ -11,6 +11,10 @@ import { filterColumns } from "@/lib/filter-columns"; import { GetTBELastSchema } from "./validations"; import { getServerSession } from "next-auth" import { authOptions } from "@/app/api/auth/[...nextauth]/route" +import path from "path" +import fs from "fs/promises" +import { sendEmail } from "../mail/sendEmail"; + // ========================================== // 1. TBE 세션 목록 조회 // ========================================== @@ -415,4 +419,132 @@ function mapReviewStatus(status: string | null): string { } return status ? (statusMap[status] || status) : "미검토" +} + + +interface DocumentInfo { + documentId: number + documentReviewId: number + documentName: string + filePath: string + documentType: string + documentSource: string + reviewStatus?: string +} + +interface SessionInfo { + sessionId: number + sessionTitle: string + buyerName: string + vendorName: string +} + +interface SendDocumentsEmailParams { + to: string[] + cc?: string[] + documents: DocumentInfo[] + comments?: string + sessionInfo: SessionInfo +} + +export async function sendDocumentsEmail({ + to, + cc, + documents, + comments, + sessionInfo +}: SendDocumentsEmailParams) { + try { + // 사용자 인증 확인 + const session = await getServerSession(authOptions) + if (!session?.user) { + return { success: false, error: "인증이 필요합니다" } + } + + + // 첨부 파일 준비 + const attachments = await Promise.all( + documents.map(async (doc) => { + try { + // 실제 파일 경로 구성 (프로젝트 구조에 맞게 조정 필요) + + const isDev = process.env.NODE_ENV === 'development'; + + const filePath = isDev ? path.join(process.cwd(), 'public', doc.filePath) + :path.join(`${process.env.NAS_PATH}`, doc.filePath) + + // 파일 존재 확인 + await fs.access(filePath) + + // 파일 읽기 + const content = await fs.readFile(filePath) + + return { + filename: doc.documentName, + content: content, + encoding: 'base64' + } + } catch (error) { + console.error(`Failed to attach file: ${doc.documentName}`, error) + // 파일을 찾을 수 없는 경우 건너뛰기 + return null + } + }) + ) + + // null 값 필터링 + const validAttachments = attachments.filter(att => att !== null) + + // 이메일 전송 + const result = await sendEmail({ + to: to.join(", "), + cc: cc?.join(", "), + template: "document-share", // 템플릿 이름 + context: { + senderName: session.user.name || "TBE User", + senderEmail: session.user.email, + sessionTitle: sessionInfo.sessionTitle, + sessionId: sessionInfo.sessionId, + buyerName: sessionInfo.buyerName, + vendorName: sessionInfo.vendorName, + documentCount: documents.length, + documents: documents.map(doc => ({ + name: doc.documentName, + type: doc.documentType, + source: doc.documentSource, + reviewStatus: doc.reviewStatus || "미검토", + reviewStatusClass: getReviewStatusClass(doc.reviewStatus), + })), + comments: comments || "", + hasComments: !!comments, + language: "ko", // 한국어로 설정 + year: new Date().getFullYear(), + }, + attachments: validAttachments as any + }) + + return { success: true, data: result } + } catch (error) { + console.error("Failed to send documents email:", error) + return { + success: false, + error: error instanceof Error ? error.message : "Failed to send email" + } + } +} + +// 리뷰 상태에 따른 CSS 클래스 반환 +function getReviewStatusClass(status?: string): string { + switch (status) { + case "승인": + return "approved" + case "반려": + return "rejected" + case "보류": + return "pending" + case "검토중": + return "reviewing" + default: + return "unreviewed" + } }
\ No newline at end of file |
