diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-11 11:21:35 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-11 11:21:35 +0000 |
| commit | 47e527f5f763658600696ee58451fb666e692f5a (patch) | |
| tree | 67f159fd0cbad5e0553c7958caa3075127121e76 /lib/bidding/detail/service.ts | |
| parent | ee77f36b1ceece1236d45fba102c3ea410acebc1 (diff) | |
(최겸) 구매 입찰 세부기능 수정
Diffstat (limited to 'lib/bidding/detail/service.ts')
| -rw-r--r-- | lib/bidding/detail/service.ts | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts index d9bcb255..e22331bb 100644 --- a/lib/bidding/detail/service.ts +++ b/lib/bidding/detail/service.ts @@ -1,7 +1,7 @@ 'use server' import db from '@/db/db' -import { biddings, prItemsForBidding, biddingDocuments, biddingCompanies, vendors, companyPrItemBids, companyConditionResponses, vendorSelectionResults, BiddingListItem, biddingConditions, priceAdjustmentForms } from '@/db/schema' +import { biddings, prItemsForBidding, biddingDocuments, biddingCompanies, vendors, companyPrItemBids, companyConditionResponses, vendorSelectionResults, BiddingListItem, biddingConditions, priceAdjustmentForms, users } from '@/db/schema' import { specificationMeetings } from '@/db/schema/bidding' import { eq, and, sql, desc, ne } from 'drizzle-orm' import { revalidatePath, revalidateTag } from 'next/cache' @@ -9,6 +9,22 @@ import { unstable_cache } from "@/lib/unstable-cache"; import { sendEmail } from '@/lib/mail/sendEmail' import { saveFile } from '@/lib/file-stroage' +// 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 // user.name이 없으면 userId를 그대로 반환 + } catch (error) { + console.error('Failed to get user name:', error) + return userId // 에러 시 userId를 그대로 반환 + } +} + // 데이터 조회 함수들 export interface BiddingDetailData { bidding: Awaited<ReturnType<typeof getBiddingById>> @@ -266,6 +282,7 @@ export async function getQuotationVendors(biddingId: number): Promise<QuotationV awardRatio: vendor.awardRatio ? Number(vendor.awardRatio) : null, isBiddingParticipated: vendor.isBiddingParticipated, status: vendor.status as 'pending' | 'submitted' | 'selected' | 'rejected', + documents: [], // 빈 배열로 초기화 })) } catch (error) { console.error('Failed to get quotation vendors:', error) @@ -664,22 +681,20 @@ export async function createBiddingDetailVendor( // 협력업체 정보 저장 - biddingCompanies와 companyConditionResponses 테이블에 레코드 생성 export async function createQuotationVendor(input: any, userId: string) { try { + const userName = await getUserNameById(userId) const result = await db.transaction(async (tx) => { // 1. biddingCompanies에 레코드 생성 const biddingCompanyResult = await tx.insert(biddingCompanies).values({ biddingId: input.biddingId, companyId: input.vendorId, - quotationAmount: input.quotationAmount, - currency: input.currency, - status: input.status, - awardRatio: input.awardRatio, + finalQuoteAmount: input.quotationAmount?.toString(), + awardRatio: input.awardRatio?.toString(), isWinner: false, contactPerson: input.contactPerson, contactEmail: input.contactEmail, contactPhone: input.contactPhone, - submissionDate: new Date(), - createdBy: userId, - updatedBy: userId, + finalQuoteSubmittedAt: new Date(), + // 스키마에 createdBy, updatedBy 필드가 없으므로 제거 }).returning({ id: biddingCompanies.id }) if (biddingCompanyResult.length === 0) { @@ -728,6 +743,7 @@ export async function createQuotationVendor(input: any, userId: string) { // 협력업체 정보 업데이트 export async function updateQuotationVendor(id: number, input: any, userId: string) { try { + const userName = await getUserNameById(userId) const result = await db.transaction(async (tx) => { // 1. biddingCompanies 테이블 업데이트 const updateData: any = {} @@ -735,9 +751,9 @@ export async function updateQuotationVendor(id: number, input: any, userId: stri if (input.contactPerson !== undefined) updateData.contactPerson = input.contactPerson if (input.contactEmail !== undefined) updateData.contactEmail = input.contactEmail if (input.contactPhone !== undefined) updateData.contactPhone = input.contactPhone - if (input.awardRatio !== undefined) updateData.awardRatio = input.awardRatio - if (input.status !== undefined) updateData.status = input.status - updateData.updatedBy = userId + if (input.awardRatio !== undefined) updateData.awardRatio = input.awardRatio?.toString() + // status 필드가 스키마에 없으므로 제거 + // updatedBy 필드가 스키마에 없으므로 제거 updateData.updatedAt = new Date() if (Object.keys(updateData).length > 0) { @@ -1031,8 +1047,10 @@ export async function registerBidding(biddingId: number, userId: string) { // 캐시 무효화 revalidateTag(`bidding-${biddingId}`) + revalidateTag('bidding-detail') revalidateTag('quotation-vendors') revalidateTag('quotation-details') + revalidateTag('pr-items') revalidatePath(`/evcp/bid/${biddingId}`) return { @@ -1157,6 +1175,7 @@ export async function createRebidding(biddingId: number, userId: string) { // 업체 선정 사유 업데이트 export async function updateVendorSelectionReason(biddingId: number, selectedCompanyId: number, selectionReason: string, userId: string) { try { + const userName = await getUserNameById(userId) // vendorSelectionResults 테이블에 삽입 또는 업데이트 await db .insert(vendorSelectionResults) @@ -1164,7 +1183,7 @@ export async function updateVendorSelectionReason(biddingId: number, selectedCom biddingId, selectedCompanyId, selectionReason, - selectedBy: userId, + selectedBy: userName, selectedAt: new Date(), createdAt: new Date(), updatedAt: new Date() @@ -1174,7 +1193,7 @@ export async function updateVendorSelectionReason(biddingId: number, selectedCom set: { selectedCompanyId, selectionReason, - selectedBy: userId, + selectedBy: userName, selectedAt: new Date(), updatedAt: new Date() } @@ -1194,6 +1213,7 @@ export async function updateVendorSelectionReason(biddingId: number, selectedCom // 낙찰용 문서 업로드 export async function uploadAwardDocument(biddingId: number, file: File, userId: string) { try { + const userName = await getUserNameById(userId) const saveResult = await saveFile({ file, directory: `biddings/${biddingId}/award`, @@ -1211,10 +1231,9 @@ export async function uploadAwardDocument(biddingId: number, file: File, userId: documentType: 'other', title: '낙찰 관련 문서', description: '낙찰 관련 첨부파일', - uploadedBy: userId, + uploadedBy: userName, uploadedAt: new Date(), - createdAt: new Date(), - updatedAt: new Date() + // createdAt, updatedAt 필드가 스키마에 없으므로 제거 }).returning() return { @@ -1292,6 +1311,7 @@ export async function getAwardDocumentForDownload(documentId: number, biddingId: // 낙찰용 문서 삭제 export async function deleteAwardDocument(documentId: number, biddingId: number, userId: string) { try { + const userName = await getUserNameById(userId) // 문서 정보 조회 const documents = await db .select() @@ -1300,7 +1320,7 @@ export async function deleteAwardDocument(documentId: number, biddingId: number, eq(biddingDocuments.id, documentId), eq(biddingDocuments.biddingId, biddingId), eq(biddingDocuments.documentType, 'other'), - eq(biddingDocuments.uploadedBy, userId) + eq(biddingDocuments.uploadedBy, userName) )) .limit(1) @@ -1335,6 +1355,7 @@ export async function deleteAwardDocument(documentId: number, biddingId: number, // 낙찰 처리 (발주비율과 함께) export async function awardBidding(biddingId: number, selectionReason: string, userId: string) { try { + const userName = await getUserNameById(userId) // 낙찰된 업체들 조회 (isWinner가 true인 업체들) const awardedCompanies = await db .select({ @@ -1388,7 +1409,7 @@ export async function awardBidding(biddingId: number, selectionReason: string, u .set({ selectedCompanyId: firstAwardedCompany.companyId, selectionReason, - selectedBy: userId, + selectedBy: userName, selectedAt: new Date(), updatedAt: new Date() }) @@ -1401,7 +1422,7 @@ export async function awardBidding(biddingId: number, selectionReason: string, u biddingId, selectedCompanyId: firstAwardedCompany.companyId, selectionReason, - selectedBy: userId, + selectedBy: userName, selectedAt: new Date(), createdAt: new Date(), updatedAt: new Date() @@ -1532,6 +1553,7 @@ export async function saveBiddingDraft( userId: string ) { try { + const userName = await getUserNameById(userId) let totalAmount = 0 await db.transaction(async (tx) => { @@ -1668,7 +1690,7 @@ export interface PartnersBiddingListItem { // biddings 정보 biddingId: number biddingNumber: string - revision: number + revision: number | null projectName: string itemName: string title: string @@ -1883,6 +1905,7 @@ export async function submitPartnerResponse( userId: string ) { try { + const userName = await getUserNameById(userId) const result = await db.transaction(async (tx) => { // 0. 품목별 견적 정보 최종 저장 (본입찰 제출) - Upsert 방식 if (response.prItemQuotations && response.prItemQuotations.length > 0) { @@ -1981,7 +2004,7 @@ export async function submitPartnerResponse( const companyUpdateData: any = { respondedAt: new Date(), updatedAt: new Date(), - // updatedBy: userId, // 이 필드가 존재하지 않음 + // updatedBy: userName, // 이 필드가 존재하지 않음 } if (response.finalQuoteAmount !== undefined) { |
