diff options
Diffstat (limited to 'lib/basic-contract/agreement-comments')
| -rw-r--r-- | lib/basic-contract/agreement-comments/actions.ts | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/lib/basic-contract/agreement-comments/actions.ts b/lib/basic-contract/agreement-comments/actions.ts index c4ded36e..2f60c3d8 100644 --- a/lib/basic-contract/agreement-comments/actions.ts +++ b/lib/basic-contract/agreement-comments/actions.ts @@ -2,7 +2,7 @@ import { revalidateTag } from "next/cache"; import db from "@/db/db"; -import { eq, and, desc } from "drizzle-orm"; +import { eq, and, desc, inArray, sql } from "drizzle-orm"; import { agreementComments, basicContract, vendors, users } from "@/db/schema"; import { saveFile, deleteFile } from "@/lib/file-stroage"; import { sendEmail } from "@/lib/mail/sendEmail"; @@ -32,6 +32,23 @@ export interface AgreementCommentData { updatedAt: Date; } +export interface AgreementCommentSummary { + hasComments: boolean; + commentCount: number; +} + +function getContractDocumentLabel(templateName?: string | null) { + if (!templateName) return "기본계약서"; + const normalized = templateName.toLowerCase(); + if (normalized.includes('준법')) { + return "준법서약"; + } + if (normalized.includes('gtc')) { + return "GTC 기본계약서"; + } + return templateName; +} + /** * 특정 기본계약서의 모든 코멘트 조회 */ @@ -496,6 +513,55 @@ export async function checkNegotiationStatus( } /** + * 다수의 계약서에 대한 협의 코멘트 상태 조회 + */ +export async function checkAgreementCommentsForContracts( + contracts: { id: number }[] +): Promise<Record<number, AgreementCommentSummary>> { + if (!contracts || contracts.length === 0) { + return {}; + } + + try { + const contractIds = contracts.map(contract => contract.id); + + const commentCounts = await db + .select({ + contractId: agreementComments.basicContractId, + count: sql<number>`count(*)`, + }) + .from(agreementComments) + .where( + and( + inArray(agreementComments.basicContractId, contractIds), + eq(agreementComments.isDeleted, false) + ) + ) + .groupBy(agreementComments.basicContractId); + + const countsMap = new Map<number, number>(); + commentCounts.forEach(({ contractId, count }) => { + countsMap.set(contractId, Number(count || 0)); + }); + + const result: Record<number, AgreementCommentSummary> = {}; + + contractIds.forEach((contractId) => { + const count = countsMap.get(contractId) ?? 0; + result[contractId] = { + hasComments: count > 0, + commentCount: count, + }; + }); + + return result; + } catch (error) { + console.error("협의 상태 조회 실패:", error); + return {}; + } +} + +/** * 이메일 알림 발송 */ async function sendCommentNotificationEmail(params: { @@ -509,6 +575,7 @@ async function sendCommentNotificationEmail(params: { attachmentCount?: number; }) { const { comment, contract, vendor, requester, templateName, authorType, authorName, attachmentCount = 0 } = params; + const documentTypeLabel = getContractDocumentLabel(templateName); // 수신자 결정 let recipientEmail: string | undefined; @@ -536,7 +603,7 @@ async function sendCommentNotificationEmail(params: { // 이메일 발송 await sendEmail({ to: recipientEmail, - subject: `[eVCP] GTC 기본계약서 협의 코멘트 제출 - ${templateName || '기본계약서'}`, + subject: `[eVCP] ${documentTypeLabel} 협의 코멘트 제출 - ${templateName || '기본계약서'}`, template: "agreement-comment-notification", context: { language: "ko", @@ -545,6 +612,7 @@ async function sendCommentNotificationEmail(params: { authorType: authorType === 'SHI' ? '삼성중공업' : '협력업체', comment: comment.comment, templateName: templateName || '기본계약서', + documentTypeLabel, vendorName: vendor?.vendorName || '', attachmentCount, contractUrl: `${process.env.NEXT_PUBLIC_APP_URL}/evcp/basic-contract/${contract.id}`, @@ -617,18 +685,20 @@ export async function completeNegotiation( .limit(1); templateName = template?.templateName || null; } + const documentTypeLabel = getContractDocumentLabel(templateName); // 이메일 알림 발송 try { if (requester) { await sendEmail({ to: requester.email || '', - subject: `[eVCP] GTC 기본계약서 협의 완료 - ${templateName || '기본계약서'}`, + subject: `[eVCP] ${documentTypeLabel} 협의 완료 - ${templateName || '기본계약서'}`, template: "negotiation-complete-notification", context: { language: "ko", recipientName: requester.name || "담당자", templateName: templateName || '기본계약서', + documentTypeLabel, vendorName: vendor?.vendorName || '', contractUrl: `${process.env.NEXT_PUBLIC_APP_URL}/evcp/basic-contract/${contract.id}`, systemUrl: process.env.NEXT_PUBLIC_APP_URL || 'https://evcp.com', |
