summaryrefslogtreecommitdiff
path: root/lib/bidding/approval-actions.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-11-26 09:55:47 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-11-26 09:55:47 +0000
commit93cc002186d3816d991925e57d44e0586dba2e75 (patch)
treeb749eb37f638d18f4f089aa5e132a81cfdf5c2fd /lib/bidding/approval-actions.ts
parent530775fb70ea24471b122e1c308cca3a0cd591b1 (diff)
(최겸) 구매 입찰 수정 v2
Diffstat (limited to 'lib/bidding/approval-actions.ts')
-rw-r--r--lib/bidding/approval-actions.ts53
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/bidding/approval-actions.ts b/lib/bidding/approval-actions.ts
index 06f5c206..dd88164d 100644
--- a/lib/bidding/approval-actions.ts
+++ b/lib/bidding/approval-actions.ts
@@ -479,11 +479,47 @@ export async function requestBiddingClosureWithApproval(data: {
* ```
*/
/**
+ * 낙찰할 업체 정보 조회 헬퍼 함수
+ */
+export async function getAwardedCompaniesForApproval(biddingId: number) {
+ const { default: db } = await import('@/db/db');
+ const { biddingCompanies, vendors } = await import('@/db/schema');
+ const { eq, and } = await import('drizzle-orm');
+
+ const awardedCompanies = await db
+ .select({
+ companyId: biddingCompanies.companyId,
+ companyName: vendors.vendorName,
+ finalQuoteAmount: biddingCompanies.finalQuoteAmount,
+ awardRatio: biddingCompanies.awardRatio
+ })
+ .from(biddingCompanies)
+ .leftJoin(vendors, eq(biddingCompanies.companyId, vendors.id))
+ .where(and(
+ eq(biddingCompanies.biddingId, biddingId),
+ eq(biddingCompanies.isWinner, true)
+ ));
+
+ return awardedCompanies.map(company => ({
+ companyId: company.companyId,
+ companyName: company.companyName || '',
+ finalQuoteAmount: parseFloat(company.finalQuoteAmount?.toString() || '0'),
+ awardRatio: parseFloat(company.awardRatio?.toString() || '0')
+ }));
+}
+
+/**
* 낙찰 결재를 위한 공통 데이터 준비 헬퍼 함수
*/
export async function prepareBiddingAwardApprovalData(data: {
biddingId: number;
selectionReason: string;
+ awardedCompanies?: Array<{
+ companyId: number;
+ companyName: string | null;
+ finalQuoteAmount: number;
+ awardRatio: number;
+ }>;
}) {
// 1. 입찰 정보 조회 (템플릿 변수용)
debugLog('[BiddingAwardApproval] 입찰 정보 조회 시작');
@@ -510,6 +546,14 @@ export async function prepareBiddingAwardApprovalData(data: {
title: biddingInfo[0].title,
});
+ // 낙찰할 업체 정보 조회 (파라미터로 제공되지 않은 경우)
+ const awardedCompanies = data.awardedCompanies || await getAwardedCompaniesForApproval(data.biddingId);
+
+ if (awardedCompanies.length === 0) {
+ debugError('[BiddingAwardApproval] 낙찰된 업체가 없습니다.');
+ throw new Error('낙찰된 업체가 없습니다. 먼저 발주비율을 산정해주세요.');
+ }
+
// 2. 템플릿 변수 매핑
debugLog('[BiddingAwardApproval] 템플릿 변수 매핑 시작');
const requestedAt = new Date();
@@ -518,6 +562,7 @@ export async function prepareBiddingAwardApprovalData(data: {
biddingId: data.biddingId,
selectionReason: data.selectionReason,
requestedAt,
+ awardedCompanies, // 낙찰 업체 정보 전달
});
debugLog('[BiddingAwardApproval] 템플릿 변수 매핑 완료', {
variableKeys: Object.keys(variables),
@@ -532,6 +577,12 @@ export async function prepareBiddingAwardApprovalData(data: {
export async function requestBiddingAwardWithApproval(data: {
biddingId: number;
selectionReason: string;
+ awardedCompanies: Array<{
+ companyId: number;
+ companyName: string | null;
+ finalQuoteAmount: number;
+ awardRatio: number;
+ }>;
currentUser: { id: number; epId: string | null; email?: string };
approvers?: string[]; // Knox EP ID 배열 (결재선)
}) {
@@ -577,6 +628,7 @@ export async function requestBiddingAwardWithApproval(data: {
const { bidding, variables } = await prepareBiddingAwardApprovalData({
biddingId: data.biddingId,
selectionReason: data.selectionReason,
+ awardedCompanies: data.awardedCompanies,
});
// 4. 결재 워크플로우 시작 (Saga 패턴)
@@ -589,6 +641,7 @@ export async function requestBiddingAwardWithApproval(data: {
{
biddingId: data.biddingId,
selectionReason: data.selectionReason,
+ awardedCompanies: data.awardedCompanies, // ✅ 결재 상신 시점의 낙찰 대상 정보
currentUserId: data.currentUser.id, // ✅ 결재 승인 후 핸들러 실행 시 필요
},