diff options
Diffstat (limited to 'lib/vendor-regular-registrations/service.ts')
| -rw-r--r-- | lib/vendor-regular-registrations/service.ts | 825 |
1 files changed, 825 insertions, 0 deletions
diff --git a/lib/vendor-regular-registrations/service.ts b/lib/vendor-regular-registrations/service.ts new file mode 100644 index 00000000..b587ec23 --- /dev/null +++ b/lib/vendor-regular-registrations/service.ts @@ -0,0 +1,825 @@ +"use server"
+import { revalidateTag, unstable_cache } from "next/cache";
+import {
+ getVendorRegularRegistrations,
+ createVendorRegularRegistration,
+ updateVendorRegularRegistration,
+ getVendorRegularRegistrationById,
+} from "./repository";
+
+import { getServerSession } from "next-auth";
+import { authOptions } from "@/app/api/auth/[...nextauth]/route";
+import { headers } from "next/headers";
+import { sendEmail } from "@/lib/mail/sendEmail";
+import {
+ vendors,
+ vendorRegularRegistrations,
+ vendorAttachments,
+ vendorInvestigations,
+ vendorInvestigationAttachments,
+ basicContract,
+ vendorPQSubmissions,
+ vendorBusinessContacts,
+ vendorAdditionalInfo
+} from "@/db/schema";
+import db from "@/db/db";
+import { inArray, eq, desc } from "drizzle-orm";
+
+// 캐싱과 에러 핸들링이 포함된 조회 함수
+export async function fetchVendorRegularRegistrations(input?: {
+ search?: string;
+ status?: string[];
+ page?: number;
+ perPage?: number;
+}) {
+ return unstable_cache(
+ async () => {
+ try {
+ const registrations = await getVendorRegularRegistrations();
+
+ let filteredData = registrations;
+
+ // 검색 필터링
+ if (input?.search) {
+ const searchLower = input.search.toLowerCase();
+ filteredData = filteredData.filter(
+ (reg) =>
+ reg.companyName.toLowerCase().includes(searchLower) ||
+ reg.businessNumber.toLowerCase().includes(searchLower) ||
+ reg.potentialCode?.toLowerCase().includes(searchLower) ||
+ reg.representative?.toLowerCase().includes(searchLower)
+ );
+ }
+
+ // 상태 필터링
+ if (input?.status && input.status.length > 0) {
+ filteredData = filteredData.filter((reg) =>
+ input.status!.includes(reg.status)
+ );
+ }
+
+ // 페이지네이션
+ const page = input?.page || 1;
+ const perPage = input?.perPage || 50;
+ const offset = (page - 1) * perPage;
+ const paginatedData = filteredData.slice(offset, offset + perPage);
+ const pageCount = Math.ceil(filteredData.length / perPage);
+
+ return {
+ success: true,
+ data: paginatedData,
+ pageCount,
+ total: filteredData.length,
+ };
+ } catch (error) {
+ console.error("Error in fetchVendorRegularRegistrations:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "정규업체 등록 목록을 가져오는 중 오류가 발생했습니다.",
+ };
+ }
+ },
+ [JSON.stringify(input || {})],
+ {
+ revalidate: 300, // 5분 캐시
+ tags: ["vendor-regular-registrations"],
+ }
+ )();
+}
+
+export async function getCurrentUserInfo() {
+ const session = await getServerSession(authOptions);
+ return {
+ userId: session?.user?.id ? String(session.user.id) : null,
+ userName: session?.user?.name || null,
+ };
+}
+
+export async function createVendorRegistration(data: {
+ vendorId: number;
+ status?: string;
+ potentialCode?: string;
+ majorItems?: Record<string, unknown>[];
+ assignedDepartment?: string;
+ assignedDepartmentCode?: string;
+ assignedUser?: string;
+ assignedUserCode?: string;
+ remarks?: string;
+}) {
+ try {
+ const majorItemsJson = data.majorItems ? JSON.stringify(data.majorItems) : undefined;
+
+ const registration = await createVendorRegularRegistration({
+ ...data,
+ majorItems: majorItemsJson,
+ });
+
+ // 캐시 무효화
+ revalidateTag("vendor-regular-registrations");
+
+ return { success: true, data: registration };
+ } catch (error) {
+ console.error("Error in createVendorRegistration:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "정규업체 등록을 생성하는 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+export async function updateVendorRegistration(
+ id: number,
+ data: Partial<{
+ status: string;
+ potentialCode: string;
+ majorItems: Record<string, unknown>[];
+ registrationRequestDate: string;
+ assignedDepartment: string;
+ assignedDepartmentCode: string;
+ assignedUser: string;
+ assignedUserCode: string;
+ remarks: string;
+ }>
+) {
+ try {
+ const updateData: Partial<{
+ status: string;
+ potentialCode: string;
+ majorItems: string;
+ registrationRequestDate: string;
+ assignedDepartment: string;
+ assignedDepartmentCode: string;
+ assignedUser: string;
+ assignedUserCode: string;
+ remarks: string;
+ }> = {};
+
+ // majorItems를 제외한 다른 필드들을 복사
+ Object.keys(data).forEach(key => {
+ if (key !== 'majorItems') {
+ updateData[key as keyof typeof updateData] = data[key as keyof typeof data] as never;
+ }
+ });
+
+ if (data.majorItems) {
+ updateData.majorItems = JSON.stringify(data.majorItems);
+ }
+
+ const registration = await updateVendorRegularRegistration(id, updateData);
+
+ // 캐시 무효화
+ revalidateTag("vendor-regular-registrations");
+
+ return { success: true, data: registration };
+ } catch (error) {
+ console.error("Error in updateVendorRegistration:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "정규업체 등록을 수정하는 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+export async function fetchVendorRegistrationById(id: number) {
+ try {
+ const registration = await getVendorRegularRegistrationById(id);
+ return { success: true, data: registration };
+ } catch (error) {
+ console.error("Error in fetchVendorRegistrationById:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "정규업체 등록 정보를 가져오는 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+
+
+export async function requestRegularRegistration(registrationId: number) {
+ try {
+ // 정규업체 등록 요청 처리
+ const now = new Date().toISOString().split('T')[0];
+
+ const registration = await updateVendorRegularRegistration(registrationId, {
+ status: "in_review",
+ registrationRequestDate: now,
+ });
+
+ // 캐시 무효화
+ revalidateTag("vendor-regular-registrations");
+
+ return { success: true, message: "정규업체 등록 요청이 완료되었습니다.", data: registration };
+ } catch (error) {
+ console.error("Error in requestRegularRegistration:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "정규업체 등록 요청 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+export async function approveRegularRegistration(registrationId: number) {
+ try {
+ // 정규업체 등록 승인 처리
+ const registration = await updateVendorRegularRegistration(registrationId, {
+ status: "approval_ready",
+ });
+
+ // 캐시 무효화
+ revalidateTag("vendor-regular-registrations");
+
+ return { success: true, message: "정규업체 등록이 승인되었습니다.", data: registration };
+ } catch (error) {
+ console.error("Error in approveRegularRegistration:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "정규업체 등록 승인 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+
+
+// 누락계약요청 이메일 발송
+export async function sendMissingContractRequestEmails(vendorIds: number[]) {
+ try {
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return { success: false, error: "로그인이 필요합니다." };
+ }
+
+ // 벤더 정보 조회
+ const vendorList = await db
+ .select({
+ id: vendors.id,
+ vendorName: vendors.vendorName,
+ email: vendors.email,
+ })
+ .from(vendors)
+ .where(inArray(vendors.id, vendorIds));
+
+ if (vendorList.length === 0) {
+ return { success: false, error: "선택된 업체를 찾을 수 없습니다." };
+ }
+
+ const headersList = await headers();
+ const host = headersList.get('host') || 'localhost:3000';
+ const protocol = process.env.NODE_ENV === 'production' ? 'https' : 'http';
+ const baseUrl = `${protocol}://${host}`;
+ const contractManagementUrl = `${baseUrl}/ko/login`; // 실제 기본계약 관리 페이지 URL로 수정 필요
+
+ let successCount = 0;
+ let errorCount = 0;
+
+ // 각 벤더에게 이메일 발송
+ await Promise.all(
+ vendorList.map(async (vendor) => {
+ if (!vendor.email) {
+ errorCount++;
+ return;
+ }
+
+ try {
+
+ await sendEmail({
+ to: vendor.email,
+ subject: "[SHI] 정규업체 등록을 위한 기본계약/서약 진행 요청",
+ template: "vendor-missing-contract-request",
+ context: {
+ vendorName: vendor.vendorName,
+ contractManagementUrl,
+ senderName: session.user.name || "구매담당자",
+ senderEmail: session.user.email || "",
+ currentYear: new Date().getFullYear(),
+ },
+ });
+ successCount++;
+ } catch (error) {
+ console.error(`Failed to send email to ${vendor.vendorName}:`, error);
+ errorCount++;
+ }
+ })
+ );
+
+ if (errorCount > 0) {
+ return {
+ success: false,
+ error: `${successCount}개 업체에 발송 성공, ${errorCount}개 업체 발송 실패`,
+ };
+ }
+
+ return {
+ success: true,
+ message: `${successCount}개 업체에 누락계약요청 이메일을 발송했습니다.`,
+ };
+ } catch (error) {
+ console.error("Error sending missing contract request emails:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "이메일 발송 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+// 추가정보요청 이메일 발송
+export async function sendAdditionalInfoRequestEmails(vendorIds: number[]) {
+ try {
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return { success: false, error: "로그인이 필요합니다." };
+ }
+
+ // 벤더 정보 조회
+ const vendorList = await db
+ .select({
+ id: vendors.id,
+ vendorName: vendors.vendorName,
+ email: vendors.email,
+ })
+ .from(vendors)
+ .where(inArray(vendors.id, vendorIds));
+
+ if (vendorList.length === 0) {
+ return { success: false, error: "선택된 업체를 찾을 수 없습니다." };
+ }
+
+ const headersList = await headers();
+ const host = headersList.get('host') || 'localhost:3000';
+ const protocol = process.env.NODE_ENV === 'production' ? 'https' : 'http';
+ const baseUrl = `${protocol}://${host}`;
+ const vendorInfoUrl = `${baseUrl}/ko/login`; // 실제 업체정보 관리 페이지 URL로 수정 필요
+
+ let successCount = 0;
+ let errorCount = 0;
+
+ // 각 벤더에게 이메일 발송
+ await Promise.all(
+ vendorList.map(async (vendor) => {
+ if (!vendor.email) {
+ errorCount++;
+ return;
+ }
+
+ try {
+ await sendEmail({
+ to: vendor.email,
+ subject: "[SHI] 정규업체 등록을 위한 추가정보 입력 요청",
+ template: "vendor-regular-registration-request",
+ context: {
+ vendorName: vendor.vendorName,
+ vendorInfoUrl,
+ senderName: session.user.name || "구매담당자",
+ senderEmail: session.user.email || "",
+ currentYear: new Date().getFullYear(),
+ },
+ });
+ successCount++;
+ } catch (error) {
+ console.error(`Failed to send email to ${vendor.vendorName}:`, error);
+ errorCount++;
+ }
+ })
+ );
+
+ if (errorCount > 0) {
+ return {
+ success: false,
+ error: `${successCount}개 업체에 발송 성공, ${errorCount}개 업체 발송 실패`,
+ };
+ }
+
+ return {
+ success: true,
+ message: `${successCount}개 업체에 추가정보요청 이메일을 발송했습니다.`,
+ };
+ } catch (error) {
+ console.error("Error sending additional info request emails:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "이메일 발송 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+// 법무검토 Skip 기능
+export async function skipLegalReview(vendorIds: number[], skipReason: string) {
+ try {
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return { success: false, error: "로그인이 필요합니다." };
+ }
+
+ let successCount = 0;
+ let errorCount = 0;
+
+ for (const vendorId of vendorIds) {
+ try {
+ // 해당 벤더의 registration 찾기 또는 생성
+ const vendorList = await db
+ .select({ id: vendors.id })
+ .from(vendors)
+ .where(eq(vendors.id, vendorId));
+
+ if (vendorList.length === 0) {
+ errorCount++;
+ continue;
+ }
+
+ // registration 조회
+ const existingRegistrations = await db
+ .select()
+ .from(vendorRegularRegistrations)
+ .where(eq(vendorRegularRegistrations.vendorId, vendorId));
+
+ let registrationId;
+ if (existingRegistrations.length === 0) {
+ // 새로 생성
+ const newRegistration = await createVendorRegularRegistration({
+ vendorId: vendorId,
+ status: "cp_finished", // CP완료로 변경
+ remarks: `법무검토 Skip: ${skipReason}`,
+ });
+ registrationId = newRegistration.id;
+ } else {
+ // 기존 registration 업데이트
+ registrationId = existingRegistrations[0].id;
+ const currentRemarks = existingRegistrations[0].remarks || "";
+ const newRemarks = currentRemarks
+ ? `${currentRemarks}\n법무검토 Skip: ${skipReason}`
+ : `법무검토 Skip: ${skipReason}`;
+
+ await updateVendorRegularRegistration(registrationId, {
+ status: "cp_finished", // CP완료로 변경
+ remarks: newRemarks,
+ });
+ }
+
+ successCount++;
+ } catch (error) {
+ console.error(`Failed to skip legal review for vendor ${vendorId}:`, error);
+ errorCount++;
+ }
+ }
+
+ if (errorCount > 0) {
+ return {
+ success: false,
+ error: `${successCount}개 업체 처리 성공, ${errorCount}개 업체 처리 실패`,
+ };
+ }
+
+ return {
+ success: true,
+ message: `${successCount}개 업체의 법무검토를 Skip 처리했습니다.`,
+ };
+ } catch (error) {
+ console.error("Error skipping legal review:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "법무검토 Skip 처리 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+// 안전적격성평가 Skip 기능
+export async function skipSafetyQualification(vendorIds: number[], skipReason: string) {
+ try {
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return { success: false, error: "로그인이 필요합니다." };
+ }
+
+ let successCount = 0;
+ let errorCount = 0;
+
+ for (const vendorId of vendorIds) {
+ try {
+ // 해당 벤더의 registration 찾기 또는 생성
+ const vendorList = await db
+ .select({ id: vendors.id })
+ .from(vendors)
+ .where(eq(vendors.id, vendorId));
+
+ if (vendorList.length === 0) {
+ errorCount++;
+ continue;
+ }
+
+ // registration 조회
+ const existingRegistrations = await db
+ .select()
+ .from(vendorRegularRegistrations)
+ .where(eq(vendorRegularRegistrations.vendorId, vendorId));
+
+ let registrationId;
+ if (existingRegistrations.length === 0) {
+ // 새로 생성
+ const newRegistration = await createVendorRegularRegistration({
+ vendorId: vendorId,
+ status: "audit_pass",
+ remarks: `안전적격성평가 Skip: ${skipReason}`,
+ });
+ registrationId = newRegistration.id;
+ } else {
+ // 기존 registration 업데이트
+ registrationId = existingRegistrations[0].id;
+ const currentRemarks = existingRegistrations[0].remarks || "";
+ const newRemarks = currentRemarks
+ ? `${currentRemarks}\n안전적격성평가 Skip: ${skipReason}`
+ : `안전적격성평가 Skip: ${skipReason}`;
+
+ await updateVendorRegularRegistration(registrationId, {
+ remarks: newRemarks,
+ });
+ }
+
+ // 안전적격성평가 상태를 완료로 처리 (계약 동의 현황은 이제 실시간으로 조회하므로 별도 처리 불필요)
+ // updateContractAgreement 함수는 제거되었으므로 계약 동의 현황은 basic_contract와 vendor_pq_submissions에서 실시간으로 조회됩니다.
+
+ successCount++;
+ } catch (error) {
+ console.error(`Failed to skip safety qualification for vendor ${vendorId}:`, error);
+ errorCount++;
+ }
+ }
+
+ if (errorCount > 0) {
+ return {
+ success: false,
+ error: `${successCount}개 업체 처리 성공, ${errorCount}개 업체 처리 실패`,
+ };
+ }
+
+ return {
+ success: true,
+ message: `${successCount}개 업체의 안전적격성평가를 Skip 처리했습니다.`,
+ };
+ } catch (error) {
+ console.error("Error skipping safety qualification:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "안전적격성평가 Skip 처리 중 오류가 발생했습니다.",
+ };
+ }
+}
+
+// 벤더용 현황 조회 함수들
+export async function fetchVendorRegistrationStatus(vendorId: number) {
+ return unstable_cache(
+ async () => {
+ try {
+ // 벤더 기본 정보
+ const vendor = await db
+ .select()
+ .from(vendors)
+ .where(eq(vendors.id, vendorId))
+ .limit(1)
+
+ if (!vendor[0]) {
+ return {
+ success: false,
+ error: "벤더 정보를 찾을 수 없습니다.",
+ }
+ }
+
+ // 정규업체 등록 정보
+ const registration = await db
+ .select()
+ .from(vendorRegularRegistrations)
+ .where(eq(vendorRegularRegistrations.vendorId, vendorId))
+ .limit(1)
+
+ // 벤더 첨부파일 조회
+ const vendorFiles = await db
+ .select()
+ .from(vendorAttachments)
+ .where(eq(vendorAttachments.vendorId, vendorId))
+
+ // 실사 결과 조회 (vendor_investigation_attachments)
+ const investigationFiles = await db
+ .select({
+ attachmentId: vendorInvestigationAttachments.id,
+ createdAt: vendorInvestigationAttachments.createdAt,
+ })
+ .from(vendorInvestigationAttachments)
+ .innerJoin(vendorInvestigations, eq(vendorInvestigationAttachments.investigationId, vendorInvestigations.id))
+ .where(eq(vendorInvestigations.vendorId, vendorId))
+
+ // PQ 제출 정보
+ const pqSubmission = await db
+ .select()
+ .from(vendorPQSubmissions)
+ .where(eq(vendorPQSubmissions.vendorId, vendorId))
+ .orderBy(desc(vendorPQSubmissions.createdAt))
+ .limit(1)
+
+ // 기본계약 정보
+ const contractInfo = await db
+ .select()
+ .from(basicContract)
+ .where(eq(basicContract.vendorId, vendorId))
+ .limit(1)
+
+ // 업무담당자 정보
+ const businessContacts = await db
+ .select()
+ .from(vendorBusinessContacts)
+ .where(eq(vendorBusinessContacts.vendorId, vendorId))
+
+ // 추가정보
+ const additionalInfo = await db
+ .select()
+ .from(vendorAdditionalInfo)
+ .where(eq(vendorAdditionalInfo.vendorId, vendorId))
+ .limit(1)
+
+ // 문서 제출 현황 계산
+ const documentStatus = {
+ businessRegistration: vendorFiles.some(f => f.attachmentType === "BUSINESS_REGISTRATION"),
+ creditEvaluation: vendorFiles.some(f => f.attachmentType === "CREDIT_EVALUATION"),
+ bankCopy: vendorFiles.some(f => f.attachmentType === "BANK_COPY"),
+ auditResult: investigationFiles.length > 0, // DocumentStatusDialog에서 사용하는 키
+ cpDocument: !!contractInfo[0]?.status && contractInfo[0].status === "completed",
+ gtc: !!contractInfo[0]?.status && contractInfo[0].status === "completed",
+ standardSubcontract: !!contractInfo[0]?.status && contractInfo[0].status === "completed",
+ safetyHealth: !!contractInfo[0]?.status && contractInfo[0].status === "completed",
+ ethics: !!contractInfo[0]?.status && contractInfo[0].status === "completed",
+ domesticCredit: !!contractInfo[0]?.status && contractInfo[0].status === "completed",
+ safetyQualification: investigationFiles.length > 0,
+ }
+
+ // 미완성 항목 계산
+ const missingDocuments = Object.entries(documentStatus)
+ .filter(([, value]) => !value)
+ .map(([key]) => key)
+
+ const requiredContactTypes = ["sales", "design", "delivery", "quality", "tax_invoice"]
+ const existingContactTypes = businessContacts.map(contact => contact.contactType)
+ const missingContactTypes = requiredContactTypes.filter(type => !existingContactTypes.includes(type))
+
+ return {
+ success: true,
+ data: {
+ vendor: vendor[0],
+ registration: registration[0] || null,
+ documentStatus,
+ missingDocuments,
+ businessContacts,
+ missingContactTypes,
+ additionalInfo: additionalInfo[0] || null,
+ pqSubmission: pqSubmission[0] || null,
+ auditPassed: investigationFiles.length > 0,
+ contractInfo: contractInfo[0] || null,
+ incompleteItemsCount: {
+ documents: missingDocuments.length,
+ contacts: missingContactTypes.length,
+ additionalInfo: !additionalInfo[0] ? 1 : 0,
+ }
+ }
+ }
+ } catch (error) {
+ console.error("Error in fetchVendorRegistrationStatus:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "현황 조회 중 오류가 발생했습니다.",
+ }
+ }
+ },
+ [`vendor-registration-status-${vendorId}`],
+ {
+ revalidate: 300, // 5분 캐시
+ tags: ["vendor-registration-status", `vendor-${vendorId}`],
+ }
+ )()
+}
+
+// 서명/직인 업로드 (임시 - 실제로는 파일 업로드 로직 필요)
+export async function uploadVendorSignature(vendorId: number, signatureData: {
+ type: "signature" | "seal"
+ signerName?: string
+ imageFile: string // base64 or file path
+}) {
+ try {
+ // TODO: 실제 파일 업로드 및 저장 로직 구현
+ console.log("Signature upload for vendor:", vendorId, signatureData)
+
+ // 캐시 무효화
+ revalidateTag(`vendor-registration-status`)
+ revalidateTag(`vendor-${vendorId}`)
+
+ return {
+ success: true,
+ message: "서명/직인이 등록되었습니다.",
+ }
+ } catch (error) {
+ console.error("Error uploading signature:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "서명/직인 등록 중 오류가 발생했습니다.",
+ }
+ }
+}
+
+// 업무담당자 정보 저장
+export async function saveVendorBusinessContacts(
+ vendorId: number,
+ contacts: Array<{
+ contactType: "sales" | "design" | "delivery" | "quality" | "tax_invoice"
+ contactName: string
+ position: string
+ department: string
+ responsibility: string
+ email: string
+ }>
+) {
+ try {
+ // 기존 데이터 삭제
+ await db
+ .delete(vendorBusinessContacts)
+ .where(eq(vendorBusinessContacts.vendorId, vendorId))
+
+ // 새 데이터 삽입
+ if (contacts.length > 0) {
+ await db
+ .insert(vendorBusinessContacts)
+ .values(contacts.map(contact => ({
+ ...contact,
+ vendorId,
+ })))
+ }
+
+ // 캐시 무효화
+ revalidateTag("vendor-registration-status")
+ revalidateTag(`vendor-${vendorId}`)
+
+ return {
+ success: true,
+ message: "업무담당자 정보가 저장되었습니다.",
+ }
+ } catch (error) {
+ console.error("Error saving business contacts:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "업무담당자 정보 저장 중 오류가 발생했습니다.",
+ }
+ }
+}
+
+// 추가정보 저장
+export async function saveVendorAdditionalInfo(
+ vendorId: number,
+ info: {
+ businessType?: string
+ industryType?: string
+ companySize?: string
+ revenue?: string
+ factoryEstablishedDate?: string
+ preferredContractTerms?: string
+ }
+) {
+ try {
+ const existing = await db
+ .select()
+ .from(vendorAdditionalInfo)
+ .where(eq(vendorAdditionalInfo.vendorId, vendorId))
+ .limit(1)
+
+ if (existing[0]) {
+ // 업데이트
+ await db
+ .update(vendorAdditionalInfo)
+ .set({
+ ...info,
+ factoryEstablishedDate: info.factoryEstablishedDate || null,
+ revenue: info.revenue || null,
+ updatedAt: new Date(),
+ })
+ .where(eq(vendorAdditionalInfo.vendorId, vendorId))
+ } else {
+ // 신규 삽입
+ await db
+ .insert(vendorAdditionalInfo)
+ .values({
+ ...info,
+ vendorId,
+ factoryEstablishedDate: info.factoryEstablishedDate || null,
+ revenue: info.revenue || null,
+ })
+ }
+
+ // 캐시 무효화
+ revalidateTag("vendor-registration-status")
+ revalidateTag(`vendor-${vendorId}`)
+
+ return {
+ success: true,
+ message: "추가정보가 저장되었습니다.",
+ }
+ } catch (error) {
+ console.error("Error saving additional info:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "추가정보 저장 중 오류가 발생했습니다.",
+ }
+ }
+}
|
