summaryrefslogtreecommitdiff
path: root/lib/bidding/detail/bidding-actions.ts
blob: 4140ec721e1cf810681b963ef3859e7888b1d222 (plain)
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 : '응찰 포기에 실패했습니다.'
    }
  }
}