1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
'use server'
import db from '@/db/db'
import { biddings, biddingCompanies, companyPrItemBids } from '@/db/schema/bidding'
import { eq, and } from 'drizzle-orm'
import { revalidateTag, revalidatePath } from 'next/cache'
import { users } from '@/db/schema'
// userId를 user.name으로 변환하는 유틸리티 함수
async function getUserNameById(userId: string): Promise<string> {
try {
const user = await db
.select({ name: users.name })
.from(users)
.where(eq(users.id, parseInt(userId)))
.limit(1)
return user[0]?.name || userId
} catch (error) {
console.error('Failed to get user name:', error)
return userId
}
}
// 응찰 포기 서버 액션 (최종제출이 아닌 경우만 가능)
export async function cancelBiddingResponse(
biddingCompanyId: number,
userId: string
) {
try {
const userName = await getUserNameById(userId)
return await db.transaction(async (tx) => {
// 1. 현재 상태 확인 (최종제출 여부)
const [company] = await tx
.select({
isFinalSubmission: biddingCompanies.isFinalSubmission,
biddingId: biddingCompanies.biddingId,
})
.from(biddingCompanies)
.where(eq(biddingCompanies.id, biddingCompanyId))
.limit(1)
if (!company) {
return {
success: false,
error: '업체 정보를 찾을 수 없습니다.'
}
}
// 최종제출한 경우 취소 불가
if (company.isFinalSubmission) {
return {
success: false,
error: '최종 제출된 응찰은 취소할 수 없습니다.'
}
}
// 2. 응찰 데이터 초기화
await tx
.update(biddingCompanies)
.set({
finalQuoteAmount: null,
finalQuoteSubmittedAt: null,
isFinalSubmission: false,
invitationStatus: 'bidding_cancelled', // 응찰 포기 상태
updatedAt: new Date()
})
.where(eq(biddingCompanies.id, biddingCompanyId))
// 3. 품목별 견적 삭제 (본입찰 데이터)
await tx
.delete(companyPrItemBids)
.where(
and(
eq(companyPrItemBids.biddingCompanyId, biddingCompanyId),
eq(companyPrItemBids.isPreQuote, false)
)
)
// 캐시 무효화
revalidateTag(`bidding-${company.biddingId}`)
revalidateTag('quotation-vendors')
revalidateTag('quotation-details')
revalidatePath(`/partners/bid/${company.biddingId}`)
return {
success: true,
message: '응찰이 포기되었습니다.'
}
})
} catch (error) {
console.error('Failed to cancel bidding response:', error)
return {
success: false,
error: error instanceof Error ? error.message : '응찰 포기에 실패했습니다.'
}
}
}
|