diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-16 09:20:58 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-16 09:20:58 +0000 |
| commit | 6c11fccc84f4c84fa72ee01f9caad9f76f35cea2 (patch) | |
| tree | fa88d10ea7d21fe6b59ed0c1569856a73d56547a /lib/rfq-last/contract-actions.ts | |
| parent | 14e3990aba7e1ad1cdd0965cbd167c50230cbfbf (diff) | |
(대표님, 최겸) 계약, 업로드 관련, 메뉴처리, 입찰, 프리쿼트, rfqLast관련, tbeLast관련
Diffstat (limited to 'lib/rfq-last/contract-actions.ts')
| -rw-r--r-- | lib/rfq-last/contract-actions.ts | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/lib/rfq-last/contract-actions.ts b/lib/rfq-last/contract-actions.ts new file mode 100644 index 00000000..1144cf4f --- /dev/null +++ b/lib/rfq-last/contract-actions.ts @@ -0,0 +1,297 @@ +"use server"; + +import db from "@/db/db"; +import { rfqsLast, rfqLastDetails } from "@/db/schema"; +import { eq, and } from "drizzle-orm"; +import { revalidatePath } from "next/cache"; + +// ===== PO (SAP) 생성 ===== +interface CreatePOParams { + rfqId: number; + vendorId: number; + vendorName: string; + totalAmount: number; + currency: string; + selectionReason?: string; +} + +export async function createPO(params: CreatePOParams) { + try { + const userId = 1; // TODO: 실제 사용자 ID 가져오기 + + // 1. 선정된 업체 확인 + const [selectedVendor] = await db + .select() + .from(rfqLastDetails) + .where( + and( + eq(rfqLastDetails.rfqsLastId, params.rfqId), + eq(rfqLastDetails.vendorsId, params.vendorId), + eq(rfqLastDetails.isSelected, true), + eq(rfqLastDetails.isLatest, true) + ) + ); + + if (!selectedVendor) { + throw new Error("선정된 업체 정보를 찾을 수 없습니다."); + } + + // 2. SAP 연동 로직 (TODO: 실제 구현 필요) + // - SAP API 호출 + // - PO 번호 생성 + // - 아이템 정보 전송 + // - 결재 라인 설정 + + // 3. 계약 상태 업데이트 + await db.transaction(async (tx) => { + // rfqLastDetails에 계약 정보 업데이트 + await tx + .update(rfqLastDetails) + .set({ + contractStatus: "진행중", + contractCreatedAt: new Date(), + contractNo: `PO-${Date.now()}`, // TODO: 실제 PO 번호로 변경 + updatedAt: new Date(), + updatedBy: userId, + }) + .where( + and( + eq(rfqLastDetails.rfqsLastId, params.rfqId), + eq(rfqLastDetails.vendorsId, params.vendorId), + eq(rfqLastDetails.isSelected, true) + ) + ); + + // RFQ 상태 업데이트 + await tx + .update(rfqsLast) + .set({ + status: "PO 생성 완료", + updatedAt: new Date(), + }) + .where(eq(rfqsLast.id, params.rfqId)); + }); + + revalidatePath(`/rfq/${params.rfqId}`); + revalidatePath("/rfq"); + + return { + success: true, + message: "PO가 성공적으로 생성되었습니다.", + poNumber: `PO-${Date.now()}`, // TODO: 실제 PO 번호 반환 + }; + } catch (error) { + console.error("PO 생성 오류:", error); + return { + success: false, + error: error instanceof Error ? error.message : "PO 생성 중 오류가 발생했습니다." + }; + } +} + +// ===== 일반계약 생성 ===== +interface CreateGeneralContractParams { + rfqId: number; + vendorId: number; + vendorName: string; + totalAmount: number; + currency: string; + contractType?: string; + contractStartDate?: Date; + contractEndDate?: Date; + contractTerms?: string; +} + +export async function createGeneralContract(params: CreateGeneralContractParams) { + try { + const userId = 1; // TODO: 실제 사용자 ID 가져오기 + + // 1. 선정된 업체 확인 + const [selectedVendor] = await db + .select() + .from(rfqLastDetails) + .where( + and( + eq(rfqLastDetails.rfqsLastId, params.rfqId), + eq(rfqLastDetails.vendorsId, params.vendorId), + eq(rfqLastDetails.isSelected, true), + eq(rfqLastDetails.isLatest, true) + ) + ); + + if (!selectedVendor) { + throw new Error("선정된 업체 정보를 찾을 수 없습니다."); + } + + // 2. 계약 생성 로직 (TODO: 실제 구현 필요) + // - 계약서 템플릿 선택 + // - 계약 조건 설정 + // - 계약서 문서 생성 + // - 전자서명 프로세스 시작 + + // 3. 계약 상태 업데이트 + await db.transaction(async (tx) => { + // rfqLastDetails에 계약 정보 업데이트 + await tx + .update(rfqLastDetails) + .set({ + contractStatus: "진행중", + contractCreatedAt: new Date(), + contractNo: `CONTRACT-${Date.now()}`, // TODO: 실제 계약번호로 변경 + updatedAt: new Date(), + updatedBy: userId, + }) + .where( + and( + eq(rfqLastDetails.rfqsLastId, params.rfqId), + eq(rfqLastDetails.vendorsId, params.vendorId), + eq(rfqLastDetails.isSelected, true) + ) + ); + + // RFQ 상태 업데이트 + await tx + .update(rfqsLast) + .set({ + status: "일반계약 진행중", + updatedAt: new Date(), + }) + .where(eq(rfqsLast.id, params.rfqId)); + }); + + revalidatePath(`/rfq/${params.rfqId}`); + revalidatePath("/rfq"); + + return { + success: true, + message: "일반계약이 성공적으로 생성되었습니다.", + contractNumber: `CONTRACT-${Date.now()}`, // TODO: 실제 계약번호 반환 + }; + } catch (error) { + console.error("일반계약 생성 오류:", error); + return { + success: false, + error: error instanceof Error ? error.message : "일반계약 생성 중 오류가 발생했습니다." + }; + } +} + +// ===== 입찰 생성 ===== +interface CreateBiddingParams { + rfqId: number; + vendorId: number; + vendorName: string; + totalAmount: number; + currency: string; + biddingType?: string; // 공개입찰, 제한입찰 등 + biddingStartDate?: Date; + biddingEndDate?: Date; + biddingRequirements?: string; +} + +export async function createBidding(params: CreateBiddingParams) { + try { + const userId = 1; // TODO: 실제 사용자 ID 가져오기 + + // 1. 선정된 업체 확인 + const [selectedVendor] = await db + .select() + .from(rfqLastDetails) + .where( + and( + eq(rfqLastDetails.rfqsLastId, params.rfqId), + eq(rfqLastDetails.vendorsId, params.vendorId), + eq(rfqLastDetails.isSelected, true), + eq(rfqLastDetails.isLatest, true) + ) + ); + + if (!selectedVendor) { + throw new Error("선정된 업체 정보를 찾을 수 없습니다."); + } + + // 2. 입찰 생성 로직 (TODO: 실제 구현 필요) + // - 입찰 공고 생성 + // - 입찰 참가자격 설정 + // - 입찰 일정 등록 + // - 평가 기준 설정 + // - 입찰 시스템 등록 + + // 3. 입찰 상태 업데이트 + await db.transaction(async (tx) => { + // rfqLastDetails에 입찰 정보 업데이트 + await tx + .update(rfqLastDetails) + .set({ + contractStatus: "입찰진행중", + contractCreatedAt: new Date(), + contractNo: `BID-${Date.now()}`, // TODO: 실제 입찰번호로 변경 + updatedAt: new Date(), + updatedBy: userId, + }) + .where( + and( + eq(rfqLastDetails.rfqsLastId, params.rfqId), + eq(rfqLastDetails.vendorsId, params.vendorId), + eq(rfqLastDetails.isSelected, true) + ) + ); + + // RFQ 상태 업데이트 + await tx + .update(rfqsLast) + .set({ + status: "입찰 진행중", + updatedAt: new Date(), + }) + .where(eq(rfqsLast.id, params.rfqId)); + }); + + revalidatePath(`/rfq/${params.rfqId}`); + revalidatePath("/rfq"); + + return { + success: true, + message: "입찰이 성공적으로 생성되었습니다.", + biddingNumber: `BID-${Date.now()}`, // TODO: 실제 입찰번호 반환 + }; + } catch (error) { + console.error("입찰 생성 오류:", error); + return { + success: false, + error: error instanceof Error ? error.message : "입찰 생성 중 오류가 발생했습니다." + }; + } +} + +// ===== 계약 타입 확인 ===== +export async function checkContractStatus(rfqId: number) { + try { + const [detail] = await db + .select({ + contractStatus: rfqLastDetails.contractStatus, + contractNo: rfqLastDetails.contractNo, + contractCreatedAt: rfqLastDetails.contractCreatedAt, + }) + .from(rfqLastDetails) + .where( + and( + eq(rfqLastDetails.rfqsLastId, rfqId), + eq(rfqLastDetails.isSelected, true), + eq(rfqLastDetails.isLatest, true) + ) + ); + + return { + success: true, + data: detail, + hasContract: !!detail?.contractNo, + }; + } catch (error) { + console.error("계약 상태 확인 오류:", error); + return { + success: false, + error: error instanceof Error ? error.message : "계약 상태 확인 중 오류가 발생했습니다." + }; + } +}
\ No newline at end of file |
