diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-12-08 03:02:42 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-12-08 03:02:42 +0000 |
| commit | c0e1cc06e0c67cb4a941889a3d63d312d1fb8fce (patch) | |
| tree | 99dc529ed88d762808dc571d4095dc880e1bef02 /lib/bidding | |
| parent | 4a8d125cf60254417d4e2ca75a967ff08cc8567e (diff) | |
(최겸) 구매 입찰계약 수정, 입찰기간수정
Diffstat (limited to 'lib/bidding')
| -rw-r--r-- | lib/bidding/detail/service.ts | 45 | ||||
| -rw-r--r-- | lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx | 8 | ||||
| -rw-r--r-- | lib/bidding/list/biddings-table-columns.tsx | 31 | ||||
| -rw-r--r-- | lib/bidding/list/export-biddings-to-excel.ts | 9 | ||||
| -rw-r--r-- | lib/bidding/receive/biddings-receive-columns.tsx | 6 | ||||
| -rw-r--r-- | lib/bidding/selection/biddings-selection-columns.tsx | 7 | ||||
| -rw-r--r-- | lib/bidding/service.ts | 39 | ||||
| -rw-r--r-- | lib/bidding/vendor/export-partners-biddings-to-excel.ts | 9 | ||||
| -rw-r--r-- | lib/bidding/vendor/partners-bidding-detail.tsx | 11 | ||||
| -rw-r--r-- | lib/bidding/vendor/partners-bidding-list-columns.tsx | 8 |
10 files changed, 116 insertions, 57 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts index 99591e3b..eec3f253 100644 --- a/lib/bidding/detail/service.ts +++ b/lib/bidding/detail/service.ts @@ -854,15 +854,14 @@ export async function registerBidding(biddingId: number, userId: string) { await db.transaction(async (tx) => { debugLog('registerBidding: Transaction started') - // 0. 입찰서 제출기간 계산 (오프셋 기반) + // 0. 입찰서 제출기간 계산 (입력값 절대 기준) const { submissionStartOffset, submissionDurationDays, submissionStartDate, submissionEndDate } = bidding let calculatedStartDate = bidding.submissionStartDate let calculatedEndDate = bidding.submissionEndDate - // 오프셋 값이 있으면 날짜 계산 if (submissionStartOffset !== null && submissionDurationDays !== null) { - // 시간 추출 (기본값: 시작 09:00, 마감 18:00) + // DB에 저장된 시간을 숫자 그대로 가져옴 (예: 10:00 저장 → 10 반환) const startTime = submissionStartDate ? { hours: submissionStartDate.getUTCHours(), minutes: submissionStartDate.getUTCMinutes() } : { hours: 9, minutes: 0 } @@ -870,22 +869,30 @@ export async function registerBidding(biddingId: number, userId: string) { ? { hours: submissionEndDate.getUTCHours(), minutes: submissionEndDate.getUTCMinutes() } : { hours: 18, minutes: 0 } - // baseDate = 현재일 날짜만 (00:00:00) - const baseDate = new Date() - baseDate.setHours(0, 0, 0, 0) - - // 시작일 = baseDate + offset일 + 시작시간 - calculatedStartDate = new Date(baseDate) - calculatedStartDate.setDate(calculatedStartDate.getDate() + submissionStartOffset) - calculatedStartDate.setHours(startTime.hours, startTime.minutes, 0, 0) - - // 마감일 = 시작일(날짜만) + duration일 + 마감시간 - calculatedEndDate = new Date(calculatedStartDate) - calculatedEndDate.setHours(0, 0, 0, 0) - calculatedEndDate.setDate(calculatedEndDate.getDate() + submissionDurationDays) - calculatedEndDate.setHours(endTime.hours, endTime.minutes, 0, 0) - - debugLog('registerBidding: Submission dates calculated', { + // 서버의 오늘 날짜(년/월/일)를 그대로 사용해 00:00 UTC 시점 생성 + const now = new Date() + const baseDate = new Date(Date.UTC( + now.getFullYear(), + now.getMonth(), + now.getDate(), + 0, 0, 0 + )) + + // 시작일 = baseDate + offset일 + 입력 시간(숫자 그대로) + const tempStartDate = new Date(baseDate) + tempStartDate.setUTCDate(tempStartDate.getUTCDate() + submissionStartOffset) + tempStartDate.setUTCHours(startTime.hours, startTime.minutes, 0, 0) + + // 마감일 = 시작일 날짜만 기준 + duration일 + 입력 마감 시간 + const tempEndDate = new Date(tempStartDate) + tempEndDate.setUTCHours(0, 0, 0, 0) + tempEndDate.setUTCDate(tempEndDate.getUTCDate() + submissionDurationDays) + tempEndDate.setUTCHours(endTime.hours, endTime.minutes, 0, 0) + + calculatedStartDate = tempStartDate + calculatedEndDate = tempEndDate + + debugLog('registerBidding: Submission dates calculated (Input Value Based)', { baseDate: baseDate.toISOString(), calculatedStartDate: calculatedStartDate.toISOString(), calculatedEndDate: calculatedEndDate.toISOString(), diff --git a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx index d3df141a..e934a5fe 100644 --- a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx +++ b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx @@ -154,8 +154,12 @@ export function BiddingDetailVendorToolbarActions({ title: "성공", description: '차수증가가 완료되었습니다.', }) - router.push(`/evcp/bid`) - onSuccess() + if (result.biddingId) { + router.push(`/evcp/bid/${result.biddingId}/info`) + } else { + router.push(`/evcp/bid`) + } + // onSuccess() } else { toast({ title: "오류", diff --git a/lib/bidding/list/biddings-table-columns.tsx b/lib/bidding/list/biddings-table-columns.tsx index 62d4dbe7..602bcbb9 100644 --- a/lib/bidding/list/biddings-table-columns.tsx +++ b/lib/bidding/list/biddings-table-columns.tsx @@ -257,21 +257,40 @@ export function getBiddingsColumns({ setRowAction }: GetColumnsProps): ColumnDef id: "submissionPeriod", header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="입찰서제출기간" />, cell: ({ row }) => { + const status = row.original.status + + // 입찰생성 또는 결재진행중 상태일 때는 특별 메시지 표시 + if (status === 'bidding_generated') { + return ( + <div className="text-xs text-orange-600 font-medium"> + 입찰 등록중입니다 + </div> + ) + } + + if (status === 'approval_pending') { + return ( + <div className="text-xs text-blue-600 font-medium"> + 결재 진행중입니다 + </div> + ) + } + const startDate = row.original.submissionStartDate const endDate = row.original.submissionEndDate - + if (!startDate || !endDate) return <span className="text-muted-foreground">-</span> - + const startObj = new Date(startDate) const endObj = new Date(endDate) - // UI 표시용 KST 변환 - const formatKst = (d: Date) => new Date(d.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') - + // 입력값 기반: 저장된 UTC 값 그대로 표시 (타임존 가감 없음) + const formatValue = (d: Date) => d.toISOString().slice(0, 16).replace('T', ' ') + return ( <div className="text-xs"> <div> - {formatKst(startObj)} ~ {formatKst(endObj)} + {formatValue(startObj)} ~ {formatValue(endObj)} </div> </div> ) diff --git a/lib/bidding/list/export-biddings-to-excel.ts b/lib/bidding/list/export-biddings-to-excel.ts index 8b13e38d..64d98399 100644 --- a/lib/bidding/list/export-biddings-to-excel.ts +++ b/lib/bidding/list/export-biddings-to-excel.ts @@ -83,13 +83,10 @@ export async function exportBiddingsToExcel( const startObj = new Date(startDate) const endObj = new Date(endDate) - // KST 변환 (UTC+9) - const formatKst = (d: Date) => { - const kstDate = new Date(d.getTime() + 9 * 60 * 60 * 1000) - return kstDate.toISOString().slice(0, 16).replace('T', ' ') - } + // 입력값 기반: 저장된 UTC 값을 그대로 표시 (타임존 가감 없음) + const formatValue = (d: Date) => d.toISOString().slice(0, 16).replace('T', ' ') - value = `${formatKst(startObj)} ~ ${formatKst(endObj)}` + value = `${formatValue(startObj)} ~ ${formatValue(endObj)}` } break diff --git a/lib/bidding/receive/biddings-receive-columns.tsx b/lib/bidding/receive/biddings-receive-columns.tsx index f2e2df17..6847d9d5 100644 --- a/lib/bidding/receive/biddings-receive-columns.tsx +++ b/lib/bidding/receive/biddings-receive-columns.tsx @@ -199,13 +199,13 @@ export function getBiddingsReceiveColumns({ setRowAction, onParticipantClick }: const startObj = new Date(startDate) const endObj = new Date(endDate) - // UI 표시용 KST 변환 - const formatKst = (d: Date) => new Date(d.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') + // 입력값 기반: 저장된 UTC 값 그대로 표시 (타임존 가감 없음) + const formatValue = (d: Date) => d.toISOString().slice(0, 16).replace('T', ' ') return ( <div className="text-xs"> <div> - {formatKst(startObj)} ~ {formatKst(endObj)} + {formatValue(startObj)} ~ {formatValue(endObj)} </div> </div> ) diff --git a/lib/bidding/selection/biddings-selection-columns.tsx b/lib/bidding/selection/biddings-selection-columns.tsx index 87c489e3..030fc05b 100644 --- a/lib/bidding/selection/biddings-selection-columns.tsx +++ b/lib/bidding/selection/biddings-selection-columns.tsx @@ -177,14 +177,13 @@ export function getBiddingsSelectionColumns({ setRowAction }: GetColumnsProps): const startObj = new Date(startDate)
const endObj = new Date(endDate)
- // 비교로직만 유지, 색상표기/마감뱃지 제거
- // UI 표시용 KST 변환
- const formatKst = (d: Date) => new Date(d.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ')
+ // 입력값 기반: 저장된 UTC 값 그대로 표시 (타임존 가감 없음)
+ const formatValue = (d: Date) => d.toISOString().slice(0, 16).replace('T', ' ')
return (
<div className="text-xs">
<div>
- {formatKst(startObj)} ~ {formatKst(endObj)}
+ {formatValue(startObj)} ~ {formatValue(endObj)}
</div>
</div>
)
diff --git a/lib/bidding/service.ts b/lib/bidding/service.ts index 71ee01ab..ed20ad0c 100644 --- a/lib/bidding/service.ts +++ b/lib/bidding/service.ts @@ -3006,6 +3006,7 @@ export async function increaseRoundOrRebid(biddingId: number, userId: string | u // 구매조직 purchasingOrganization: existingBidding.purchasingOrganization, + plant: existingBidding.plant, // 담당자 정보 복제 bidPicId: existingBidding.bidPicId, @@ -3323,7 +3324,6 @@ export async function increaseRoundOrRebid(biddingId: number, userId: string | u revalidatePath('/evcp/bid-receive') revalidatePath('/evcp/bid') revalidatePath(`/bid-receive/${biddingId}`) // 기존 입찰 페이지도 갱신 - revalidatePath(`/bid-receive/${newBidding.id}`) return { success: true, @@ -4139,6 +4139,41 @@ export async function getBiddingSelectionItemsAndPrices(biddingId: number) { */ export async function checkAndSaveChemicalSubstancesForBidding(biddingId: number) { try { + const [biddingInfo] = await db + .select({ + id: biddings.id, + ANFNR: biddings.ANFNR, + plant: biddings.plant, + }) + .from(biddings) + .where(eq(biddings.id, biddingId)) + .limit(1) + + if (!biddingInfo) { + return { + success: false, + message: '입찰 정보를 찾을 수 없습니다.', + results: [] + } + } + + if (!biddingInfo.ANFNR) { + return { + success: true, + message: 'SAP PR 연동 입찰이 아니므로 화학물질 검사를 건너뜁니다.', + results: [] + } + } + + const biddingWerks = biddingInfo.plant?.trim() + if (!biddingWerks) { + return { + success: false, + message: '입찰의 플랜트(WERKS) 정보가 없어 화학물질 검사를 진행할 수 없습니다.', + results: [] + } + } + // 입찰의 모든 참여업체 조회 (벤더 코드 있는 것만) const biddingCompaniesList = await db .select({ @@ -4222,7 +4257,7 @@ export async function checkAndSaveChemicalSubstancesForBidding(biddingId: number try { const checkResult = await checkChemicalSubstance({ bukrs: 'H100', // 회사코드는 H100 고정 - werks: 'PM11', // WERKS는 PM11 고정 + werks: biddingWerks, lifnr: biddingCompany.vendors!.vendorCode!, matnr: materialNumber }) diff --git a/lib/bidding/vendor/export-partners-biddings-to-excel.ts b/lib/bidding/vendor/export-partners-biddings-to-excel.ts index 9e99eeec..e1d985fe 100644 --- a/lib/bidding/vendor/export-partners-biddings-to-excel.ts +++ b/lib/bidding/vendor/export-partners-biddings-to-excel.ts @@ -124,13 +124,10 @@ export async function exportPartnersBiddingsToExcel( const startObj = new Date(startDate) const endObj = new Date(endDate) - // KST 변환 (UTC+9) - const formatKst = (d: Date) => { - const kstDate = new Date(d.getTime() + 9 * 60 * 60 * 1000) - return kstDate.toISOString().slice(0, 16).replace('T', ' ') - } + // 입력값 기반: 저장된 UTC 값을 그대로 표시 (타임존 가감 없음) + const formatValue = (d: Date) => d.toISOString().slice(0, 16).replace('T', ' ') - value = `${formatKst(startObj)} ~ ${formatKst(endObj)}` + value = `${formatValue(startObj)} ~ ${formatValue(endObj)}` } break diff --git a/lib/bidding/vendor/partners-bidding-detail.tsx b/lib/bidding/vendor/partners-bidding-detail.tsx index 087648ab..bf33cef5 100644 --- a/lib/bidding/vendor/partners-bidding-detail.tsx +++ b/lib/bidding/vendor/partners-bidding-detail.tsx @@ -868,7 +868,8 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD const timeLeft = deadline.getTime() - now.getTime() const daysLeft = Math.floor(timeLeft / (1000 * 60 * 60 * 24)) const hoursLeft = Math.floor((timeLeft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) - const kstDeadline = new Date(deadline.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') + // 입력값 기반: 저장된 UTC 값을 그대로 표시 + const displayDeadline = deadline.toISOString().slice(0, 16).replace('T', ' ') return ( <div className={`p-3 rounded-lg border-2 ${ @@ -883,7 +884,7 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD <Calendar className="w-5 h-5" /> <span className="font-medium">제출 마감일:</span> <span className="text-lg font-semibold"> - {kstDeadline} + {displayDeadline} </span> </div> {isExpired ? ( @@ -920,9 +921,9 @@ export function PartnersBiddingDetail({ biddingId, companyId }: PartnersBiddingD <span className="font-medium">입찰서 제출기간:</span> {(() => { const start = new Date(biddingDetail.submissionStartDate!) const end = new Date(biddingDetail.submissionEndDate!) - const kstStart = new Date(start.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') - const kstEnd = new Date(end.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') - return `${kstStart} ~ ${kstEnd}` + const displayStart = start.toISOString().slice(0, 16).replace('T', ' ') + const displayEnd = end.toISOString().slice(0, 16).replace('T', ' ') + return `${displayStart} ~ ${displayEnd}` })()} </div> )} diff --git a/lib/bidding/vendor/partners-bidding-list-columns.tsx b/lib/bidding/vendor/partners-bidding-list-columns.tsx index 6276d1b7..09c3caad 100644 --- a/lib/bidding/vendor/partners-bidding-list-columns.tsx +++ b/lib/bidding/vendor/partners-bidding-list-columns.tsx @@ -352,14 +352,14 @@ export function getPartnersBiddingListColumns({ setRowAction }: PartnersBiddingL const startObj = new Date(startDate) const endObj = new Date(endDate) - // UI 표시용 KST 변환 - const formatKst = (d: Date) => new Date(d.getTime() + 9 * 60 * 60 * 1000).toISOString().slice(0, 16).replace('T', ' ') + // 입력값 기반: 저장된 UTC 값 그대로 표시 (타임존 가감 없음) + const formatValue = (d: Date) => d.toISOString().slice(0, 16).replace('T', ' ') return ( <div className="text-sm"> - <div>{formatKst(startObj)}</div> + <div>{formatValue(startObj)}</div> <div className="text-muted-foreground">~</div> - <div>{formatKst(endObj)}</div> + <div>{formatValue(endObj)}</div> </div> ) }, |
