summaryrefslogtreecommitdiff
path: root/lib/vendors
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendors')
-rw-r--r--lib/vendors/service.ts129
-rw-r--r--lib/vendors/table/request-pq-dialog.tsx46
2 files changed, 148 insertions, 27 deletions
diff --git a/lib/vendors/service.ts b/lib/vendors/service.ts
index 45a0e0b5..9a37f5d7 100644
--- a/lib/vendors/service.ts
+++ b/lib/vendors/service.ts
@@ -2943,32 +2943,7 @@ export async function requestBasicContractInfo({
})
.returning();
- // 3-2. 협력업체에 이메일 발송
- const subject = `[${process.env.COMPANY_NAME || '회사명'}] 기본계약서 서명 요청`;
-
- const headersList = await headers();
- const host = headersList.get('host') || 'localhost:3000';
- // 로그인 또는 서명 페이지 URL 생성
- const baseUrl = process.env.NEXT_PUBLIC_URL || `http://${host}`;
- const loginUrl = `${baseUrl}/partners/basic-contract`;
- console.log("loginUrl-basic-contract", loginUrl);
-
- // 사용자 언어 설정 (기본값은 한국어)
- const userLang = "ko";
-
- // 이메일 발송
- await sendEmail({
- to: vendor.email,
- subject,
- template: "contract-sign-request", // 이메일 템플릿 이름
- context: {
- vendorName: vendor.vendorName,
- contractId: newContract.id,
- templateName: template.templateName,
- loginUrl,
- language: userLang,
- },
- });
+ // 이메일 발송은 별도 함수(sendBasicContractEmail)에서 처리
return { vendorId: vendor.id, success: true };
} catch (err) {
@@ -3016,6 +2991,108 @@ export async function requestBasicContractInfo({
}
/**
+ * 기본계약서 이메일 발송 함수
+ * 협력업체당 하나의 이메일만 발송하며, 전달받은 템플릿 정보를 포함
+ */
+export async function sendBasicContractEmail({
+ vendorIds,
+ templateIds,
+ requestedBy
+}: {
+ vendorIds: number[];
+ templateIds: number[];
+ requestedBy: number;
+}): Promise<{ success?: boolean; error?: string }> {
+ if (!vendorIds || vendorIds.length === 0) {
+ return { error: "협력업체 ID가 제공되지 않았습니다." };
+ }
+
+ if (!templateIds || templateIds.length === 0) {
+ return { error: "템플릿 ID가 제공되지 않았습니다." };
+ }
+
+ try {
+ // 협력업체 정보 가져오기
+ const vendorList = await db
+ .select()
+ .from(vendors)
+ .where(inArray(vendors.id, vendorIds));
+
+ if (!vendorList || vendorList.length === 0) {
+ return { error: "선택한 협력업체 정보를 찾을 수 없습니다." };
+ }
+
+ // 템플릿 정보 가져오기
+ const templateList = await db
+ .select()
+ .from(basicContractTemplates)
+ .where(inArray(basicContractTemplates.id, templateIds));
+
+ if (!templateList || templateList.length === 0) {
+ return { error: "선택한 템플릿 정보를 찾을 수 없습니다." };
+ }
+
+ // 각 협력업체에 이메일 발송
+ const emailResults = await Promise.all(
+ vendorList.map(async (vendor) => {
+ if (!vendor.email) return { vendorId: vendor.id, success: true }; // 이메일이 없으면 스킵
+
+ try {
+ const subject = `기본계약서 서명 요청`;
+
+ const headersList = await headers();
+ const host = headersList.get('host') || 'localhost:3000';
+ const baseUrl = process.env.NEXT_PUBLIC_URL || `http://${host}`;
+ const loginUrl = `${baseUrl}/partners/basic-contract`;
+
+ // 사용자 언어 설정 (기본값은 한국어)
+ const userLang = "ko";
+
+ // 이메일 발송 (요청된 템플릿 정보 포함)
+ await sendEmail({
+ to: vendor.email,
+ subject,
+ template: "contract-sign-request",
+ context: {
+ vendorName: vendor.vendorName,
+ templates: templateList, // 요청된 템플릿 목록
+ templateCount: templateList.length,
+ loginUrl,
+ language: userLang,
+ },
+ });
+
+ return { vendorId: vendor.id, success: true };
+ } catch (err) {
+ console.error(`협력업체 ${vendor.id} 이메일 발송 중 오류:`, err);
+ return { vendorId: vendor.id, success: false, error: getErrorMessage(err) };
+ }
+ })
+ );
+
+ // 실패한 이메일 발송 확인
+ const failedEmails = emailResults.filter(r => !r.success);
+
+ if (failedEmails.length > 0) {
+ console.error("일부 협력업체 이메일 발송 실패:", failedEmails);
+ return {
+ success: true,
+ error: `${emailResults.length - failedEmails.length}개 협력업체 이메일 발송 성공, ${failedEmails.length}개 실패`
+ };
+ }
+
+ return { success: true };
+ } catch (error) {
+ console.error("기본계약서 이메일 발송 중 오류 발생:", error);
+ return {
+ error: error instanceof Error
+ ? error.message
+ : "기본계약서 이메일 발송 중 오류가 발생했습니다."
+ };
+ }
+}
+
+/**
* 비밀유지 계약서 첨부파일 저장 서버 액션
*/
export async function saveNdaAttachments(input: {
diff --git a/lib/vendors/table/request-pq-dialog.tsx b/lib/vendors/table/request-pq-dialog.tsx
index 767b979f..aeb0c717 100644
--- a/lib/vendors/table/request-pq-dialog.tsx
+++ b/lib/vendors/table/request-pq-dialog.tsx
@@ -39,7 +39,7 @@ import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import { Progress } from "@/components/ui/progress"
import { Vendor } from "@/db/schema/vendors"
-import { requestBasicContractInfo, requestPQVendors } from "../service"
+import { requestBasicContractInfo, requestPQVendors, sendBasicContractEmail } from "../service"
import { getProjectsWithPQList } from "@/lib/pq/service"
import type { Project } from "@/lib/pq/service"
import { useSession } from "next-auth/react"
@@ -364,6 +364,14 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro
setProgressValue((completedSteps / totalSteps) * 100)
}
}
+ //5단계: 각 협력업체들에게 기본계약서 이메일 발송
+ if (selectedTemplateIds.length > 0) {
+ setCurrentStep(`기본계약서 이메일 발송 중... (${selectedTemplateIds.length}개 템플릿)`)
+ console.log("📋 기본계약서 이메일 발송 시작", selectedTemplateIds.length, "개 템플릿")
+ await processBasicContractsEmail(selectedTemplateIds, vendors)
+ completedSteps++
+ setProgressValue((completedSteps / totalSteps) * 100)
+ }
setCurrentStep("완료!")
setProgressValue(100)
@@ -506,6 +514,7 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro
}
console.log(`✅ 기본계약 생성 완료: ${template.templateName}`)
+
} finally {
// 임시 WebViewer 정리
@@ -601,6 +610,41 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro
}
}
+ const processBasicContractsEmail = async (templateIds: number[], vendors: any[]) => {
+ if (!session?.user?.id) {
+ toast.error("인증 정보가 없습니다")
+ return
+ }
+ try {
+ const vendorIds = vendors.map(v => v.id)
+ const userId = Number(session.user.id)
+
+ // 2. 성공한 템플릿이 있으면 이메일 발송
+ if (templateIds.length > 0) {
+ const emailResult = await sendBasicContractEmail({
+ vendorIds,
+ templateIds,
+ requestedBy: userId
+ })
+
+ if (emailResult.success) {
+ toast.success(`${templateIds.length}개 템플릿에 대한 기본계약서가 생성되었고, ${vendorIds.length}개 협력업체에 이메일이 발송되었습니다`)
+ } else {
+ toast.warning(`계약서는 생성되었으나 일부 이메일 발송 실패: ${emailResult.error}`)
+ }
+ } else {
+ toast.error("기본계약서 생성에 실패했습니다")
+ }
+
+ } catch (error) {
+ console.error('기본계약서 이메일 발송 중 오류:', error)
+ toast.error(`기본계약서 이메일 발송 중 오류가 발생했습니다: ${error instanceof Error ? error.message : '알 수 없는 오류'}`)
+ }
+}
+
+
+
+
const dialogContent = (
<div className="space-y-4 py-2">
{/* 선택된 협력업체 정보 */}