summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bidding/actions.ts52
-rw-r--r--lib/bidding/detail/service.ts30
-rw-r--r--lib/bidding/detail/table/bidding-invitation-dialog.tsx2
-rw-r--r--lib/bidding/service.ts2
4 files changed, 80 insertions, 6 deletions
diff --git a/lib/bidding/actions.ts b/lib/bidding/actions.ts
index 3eadaace..df9d0dad 100644
--- a/lib/bidding/actions.ts
+++ b/lib/bidding/actions.ts
@@ -67,6 +67,17 @@ export async function transmitToContract(biddingId: number, userId: number) {
throw new Error("낙찰된 업체가 없습니다.")
}
+ // 일반/매각 입찰의 경우 비율 합계 100% 검증
+ const contractType = biddingData.contractType
+ if (contractType === 'general' || contractType === 'sale') {
+ const totalRatio = winnerCompaniesData.reduce((sum, company) =>
+ sum + (Number(company.awardRatio) || 0), 0)
+
+ if (totalRatio !== 100) {
+ throw new Error(`일반/매각 입찰의 경우 비율 합계가 100%여야 합니다. 현재 합계: ${totalRatio}%`)
+ }
+ }
+
for (const winnerCompany of winnerCompaniesData) {
// winnerCompany에서 직접 정보 사용
const awardRatio = (Number(winnerCompany.awardRatio) || 100) / 100
@@ -116,7 +127,7 @@ export async function transmitToContract(biddingId: number, userId: number) {
name: biddingData.title,
vendorId: winnerCompany.companyId,
linkedBidNumber: biddingData.biddingNumber,
- contractAmount: totalContractAmount || null, // 발주비율 계산된 최종 금액 사용
+ contractAmount: totalContractAmount ? totalContractAmount.toString() as any : null, // 발주비율 계산된 최종 금액 사용
startDate: biddingData.contractStartDate || null,
endDate: biddingData.contractEndDate || null,
currency: biddingData.currency || 'KRW',
@@ -154,7 +165,7 @@ export async function transmitToContract(biddingId: number, userId: number) {
weightUnit: '', // 중량 단위 제외
contractDeliveryDate: bid.proposedDeliveryDate || null,
contractUnitPrice: bid.bidUnitPrice || null,
- contractAmount: finalAmount || null,
+ contractAmount: finalAmount ? finalAmount.toString() as any : null,
contractCurrency: bid.currency || biddingData.currency || 'KRW',
})
}
@@ -221,6 +232,17 @@ export async function transmitToPO(biddingId: number) {
throw new Error("낙찰된 업체가 없습니다.")
}
+ // 일반/매각 입찰의 경우 비율 합계 100% 검증
+ const contractType = bidding.contractType
+ if (contractType === 'general' || contractType === 'sale') {
+ const totalRatio = winnerCompaniesRaw.reduce((sum, company) =>
+ sum + (Number(company.awardRatio) || 0), 0)
+
+ if (totalRatio !== 100) {
+ throw new Error(`일반/매각 입찰의 경우 비율 합계가 100%여야 합니다. 현재 합계: ${totalRatio}%`)
+ }
+ }
+
// 4. 낙찰된 업체들의 입찰 데이터 조회 (발주비율 적용)
type POItem = {
prItemId: number
@@ -339,7 +361,19 @@ export async function transmitToPO(biddingId: number) {
// 낙찰된 업체들의 상세 정보 조회 (발주비율에 따른 계산 포함)
export async function getWinnerDetails(biddingId: number) {
try {
- // 1. 낙찰된 업체들 조회
+ // 1. 입찰 정보 조회 (contractType 포함)
+ const biddingInfo = await db.select({
+ contractType: biddings.contractType,
+ })
+ .from(biddings)
+ .where(eq(biddings.id, biddingId))
+ .limit(1)
+
+ if (!biddingInfo || biddingInfo.length === 0) {
+ return { success: false, error: '입찰 정보를 찾을 수 없습니다.' }
+ }
+
+ // 2. 낙찰된 업체들 조회
const winnerCompanies = await db.select({
id: biddingCompanies.id,
companyId: biddingCompanies.companyId,
@@ -347,6 +381,7 @@ export async function getWinnerDetails(biddingId: number) {
awardRatio: biddingCompanies.awardRatio,
vendorName: vendors.vendorName,
vendorCode: vendors.vendorCode,
+ contractType: biddingInfo[0].contractType,
})
.from(biddingCompanies)
.leftJoin(vendors, eq(biddingCompanies.companyId, vendors.id))
@@ -361,6 +396,17 @@ export async function getWinnerDetails(biddingId: number) {
return { success: false, error: '낙찰된 업체가 없습니다.' }
}
+ // 일반/매각 입찰의 경우 비율 합계 100% 검증
+ const contractType = biddingInfo[0].contractType
+ if (contractType === 'general' || contractType === 'sale') {
+ const totalRatio = winnerCompanies.reduce((sum, company) =>
+ sum + (Number(company.awardRatio) || 0), 0)
+
+ if (totalRatio !== 100) {
+ return { success: false, error: `일반/매각 입찰의 경우 비율 합계가 100%여야 합니다. 현재 합계: ${totalRatio}%` }
+ }
+ }
+
// 2. 각 낙찰 업체의 입찰 품목 정보 조회
const winnerDetails = []
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts
index 9fb3d87f..645ebeac 100644
--- a/lib/bidding/detail/service.ts
+++ b/lib/bidding/detail/service.ts
@@ -1158,6 +1158,23 @@ export async function deleteAwardDocument(documentId: number, biddingId: number,
export async function awardBidding(biddingId: number, selectionReason: string, userId: string) {
try {
const userName = await getUserNameById(userId)
+
+ // 입찰 정보 조회 (contractType 포함)
+ const biddingInfo = await db
+ .select({
+ contractType: biddings.contractType,
+ status: biddings.status
+ })
+ .from(biddings)
+ .where(eq(biddings.id, biddingId))
+ .limit(1)
+
+ if (biddingInfo.length === 0) {
+ return { success: false, error: '입찰 정보를 찾을 수 없습니다.' }
+ }
+
+ const bidding = biddingInfo[0]
+
// 낙찰된 업체들 조회 (isWinner가 true인 업체들)
const awardedCompanies = await db
.select({
@@ -1170,11 +1187,22 @@ export async function awardBidding(biddingId: number, selectionReason: string, u
eq(biddingCompanies.biddingId, biddingId),
eq(biddingCompanies.isWinner, true)
))
-
+
if (awardedCompanies.length === 0) {
return { success: false, error: '낙찰된 업체가 없습니다. 먼저 발주비율을 산정해주세요.' }
}
+ // 일반/매각 입찰의 경우 비율 합계 100% 검증
+ const contractType = bidding.contractType
+ if (contractType === 'general' || contractType === 'sale') {
+ const totalRatio = awardedCompanies.reduce((sum, company) =>
+ sum + (Number(company.awardRatio) || 0), 0)
+
+ if (totalRatio !== 100) {
+ return { success: false, error: `일반/매각 입찰의 경우 비율 합계가 100%여야 합니다. 현재 합계: ${totalRatio}%` }
+ }
+ }
+
// 최종입찰가 계산 (낙찰된 업체의 견적금액 * 발주비율의 합)
let finalBidPrice = 0
for (const company of awardedCompanies) {
diff --git a/lib/bidding/detail/table/bidding-invitation-dialog.tsx b/lib/bidding/detail/table/bidding-invitation-dialog.tsx
index 48b235f9..cd79850a 100644
--- a/lib/bidding/detail/table/bidding-invitation-dialog.tsx
+++ b/lib/bidding/detail/table/bidding-invitation-dialog.tsx
@@ -666,7 +666,7 @@ export function BiddingInvitationDialog({
{isGeneratingPdfs ? (
<>
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
- 계약서 생성중... ({Math.round(pdfGenerationProgress)}%)
+ 입찰 초대중... ({Math.round(pdfGenerationProgress)}%)
</>
) : isPending ? (
<>
diff --git a/lib/bidding/service.ts b/lib/bidding/service.ts
index 89e4f80f..68efe165 100644
--- a/lib/bidding/service.ts
+++ b/lib/bidding/service.ts
@@ -420,7 +420,7 @@ export interface UpdateBiddingInput extends UpdateBiddingSchema {
}
// 자동 입찰번호 생성
-async function generateBiddingNumber(
+export async function generateBiddingNumber(
userId?: string,
tx?: any,
maxRetries: number = 5