summaryrefslogtreecommitdiff
path: root/lib/rfq-last/contract-actions.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rfq-last/contract-actions.ts')
-rw-r--r--lib/rfq-last/contract-actions.ts297
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