summaryrefslogtreecommitdiff
path: root/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx')
-rw-r--r--lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx224
1 files changed, 185 insertions, 39 deletions
diff --git a/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx b/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
index 575582cf..8f945bbd 100644
--- a/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
+++ b/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
@@ -18,9 +18,10 @@ import {
DialogTitle,
} from "@/components/ui/dialog"
import { Badge } from "@/components/ui/badge"
-import { prepareFinalApprovalAction, quickFinalApprovalAction, resendContractsAction, updateLegalReviewStatusFromSSLVW } from "../service"
+import { prepareFinalApprovalAction, quickFinalApprovalAction, resendContractsAction, updateLegalReviewStatusFromSSLVW, updateComplianceReviewStatusFromCPVW, requestComplianceInquiryAction } from "../service"
import { BasicContractSignDialog } from "../vendor-table/basic-contract-sign-dialog"
import { SSLVWPurInqReqDialog } from "@/components/common/legal/sslvw-pur-inq-req-dialog"
+import { CPVWWabQustListViewDialog } from "@/components/common/legal/cpvw-wab-qust-list-view-dialog"
import { prepareRedFlagResolutionApproval, requestRedFlagResolution } from "@/lib/compliance/red-flag-resolution"
import { useRouter } from "next/navigation"
import { useSession } from "next-auth/react"
@@ -35,6 +36,7 @@ interface RedFlagResolutionState {
interface BasicContractDetailTableToolbarActionsProps {
table: Table<BasicContractView>
gtcData?: Record<number, { gtcDocumentId: number | null; hasComments: boolean }>
+ agreementCommentData?: Record<number, { hasComments: boolean; commentCount: number }>
redFlagData?: Record<number, boolean>
redFlagResolutionData?: Record<number, RedFlagResolutionState>
isComplianceTemplate?: boolean
@@ -43,6 +45,7 @@ interface BasicContractDetailTableToolbarActionsProps {
export function BasicContractDetailTableToolbarActions({
table,
gtcData = {},
+ agreementCommentData = {},
redFlagData = {},
redFlagResolutionData = {},
isComplianceTemplate = false
@@ -81,24 +84,26 @@ export function BasicContractDetailTableToolbarActions({
if (contract.completedAt !== null || !contract.signedFilePath) {
return false;
}
- if (contract.legalReviewRequestedAt && !contract.legalReviewCompletedAt) {
- return false;
- }
+ // ⚠️ 법무/준법문의 완료 여부는 SSLVW/CPVW 상태 및 완료 시간에 의존하므로,
+ // 여기서는 legalReviewCompletedAt / complianceReviewCompletedAt 기반으로
+ // 최종 승인 버튼을 막지 않습니다. (상태/시간은 UI 참고용으로만 사용)
return true;
});
- // 법무검토 요청 가능 여부
- // 1. 협의 완료됨 (negotiationCompletedAt 있음) OR
- // 2. 협의 없음 (코멘트 없음, hasComments: false)
+ // 법무검토 요청 가능 여부 (준법서약 템플릿이 아닐 때만)
+ // 1. 협력업체 서명 완료 (vendorSignedAt 있음)
+ // 2. 협의 완료됨 (negotiationCompletedAt 있음) OR
+ // 3. 협의 없음 (코멘트 없음, hasComments: false)
// 협의 중 (negotiationCompletedAt 없고 코멘트 있음)은 불가
- const canRequestLegalReview = hasSelectedRows && selectedRows.some(row => {
+ const canRequestLegalReview = !isComplianceTemplate && hasSelectedRows && selectedRows.some(row => {
const contract = row.original;
- // 이미 법무검토 요청된 계약서는 제외
- if (contract.legalReviewRequestedAt) {
- return false;
- }
- // 이미 최종승인 완료된 계약서는 제외
- if (contract.completedAt) {
+
+ // 필수 조건 확인: 최종승인 미완료, 법무검토 미요청, 협력업체 서명 완료
+ if (
+ contract.legalReviewRequestedAt ||
+ contract.completedAt ||
+ !contract.vendorSignedAt
+ ) {
return false;
}
@@ -123,6 +128,48 @@ export function BasicContractDetailTableToolbarActions({
return false;
});
+ // 준법문의 버튼 활성화 가능 여부
+ // 1. 협력업체 서명 완료 (vendorSignedAt 있음)
+ // 2. 협의 완료됨 (negotiationCompletedAt 있음) OR 협의 없음 (코멘트 없음)
+ // 3. 레드플래그 해소됨 (redFlagResolutionData에서 resolved 상태)
+ // 4. 이미 준법문의 요청되지 않음 (complianceReviewRequestedAt 없음)
+ const canRequestComplianceInquiry = hasSelectedRows && selectedRows.some(row => {
+ const contract = row.original;
+
+ // 필수 조건 확인: 준법서약 템플릿, 최종승인 미완료, 협력업체 서명 완료, 준법문의 미요청
+ if (
+ !isComplianceTemplate ||
+ contract.completedAt ||
+ !contract.vendorSignedAt ||
+ contract.complianceReviewRequestedAt
+ ) {
+ return false;
+ }
+
+ // 협의 완료 확인
+ // 협의 완료된 경우 → 가능
+ if (contract.negotiationCompletedAt) {
+ // 협의 완료됨, 레드플래그만 확인하면 됨
+ } else {
+ // 협의 완료되지 않은 경우: 코멘트가 없으면 협의 없음으로 간주하여 가능
+ const commentData = agreementCommentData[contract.id];
+ if (commentData && commentData.hasComments) {
+ // 코멘트가 있으면 협의 중이므로 불가
+ return false;
+ }
+ // 코멘트가 없으면 협의 없음으로 간주하여 가능
+ }
+
+ // 레드플래그 해소 확인
+ const resolution = redFlagResolutionData[contract.id];
+ // 레드플래그가 있는 경우, 해소되어야 함
+ if (redFlagData[contract.id] === true && !resolution?.resolved) {
+ return false;
+ }
+
+ return true;
+ });
+
// 필터링된 계약서들 계산
const resendContracts = selectedRows.map(row => row.original)
@@ -394,6 +441,47 @@ export function BasicContractDetailTableToolbarActions({
}
}
+ // CPVW 데이터 선택 확인 핸들러
+ const handleCPVWConfirm = async (selectedCPVWData: any[]) => {
+ if (!selectedCPVWData || selectedCPVWData.length === 0) {
+ toast.error("선택된 데이터가 없습니다.")
+ return
+ }
+
+ if (selectedRows.length !== 1) {
+ toast.error("계약서 한 건을 선택해주세요.")
+ return
+ }
+
+ try {
+ setLoading(true)
+
+ // 선택된 계약서 ID들 추출
+ const selectedContractIds = selectedRows.map(row => row.original.id)
+
+ // 서버 액션 호출
+ const result = await updateComplianceReviewStatusFromCPVW(selectedCPVWData, selectedContractIds)
+
+ if (result.success) {
+ toast.success(result.message)
+ router.refresh()
+ table.toggleAllPageRowsSelected(false)
+ } else {
+ toast.error(result.message)
+ }
+
+ if (result.errors && result.errors.length > 0) {
+ toast.warning(`일부 처리 실패: ${result.errors.join(', ')}`)
+ }
+
+ } catch (error) {
+ console.error('CPVW 확인 처리 실패:', error)
+ toast.error('준법문의 상태 업데이트 중 오류가 발생했습니다.')
+ } finally {
+ setLoading(false)
+ }
+ }
+
// 빠른 승인 (서명 없이)
const confirmQuickApproval = async () => {
setLoading(true)
@@ -541,9 +629,26 @@ export function BasicContractDetailTableToolbarActions({
const complianceInquiryUrl = 'http://60.101.207.55/Inquiry/Write/InquiryWrite.aspx'
// 법무검토 요청 / 준법문의
- const handleRequestLegalReview = () => {
+ const handleRequestLegalReview = async () => {
if (isComplianceTemplate) {
- window.open(complianceInquiryUrl, '_blank', 'noopener,noreferrer')
+ // 준법문의: 요청일 기록 후 외부 URL 열기
+ const selectedContractIds = selectedRows.map(row => row.original.id)
+ try {
+ setLoading(true)
+ const result = await requestComplianceInquiryAction(selectedContractIds)
+ if (result.success) {
+ toast.success(result.message)
+ router.refresh()
+ window.open(complianceInquiryUrl, '_blank', 'noopener,noreferrer')
+ } else {
+ toast.error(result.message)
+ }
+ } catch (error) {
+ console.error('준법문의 요청 처리 실패:', error)
+ toast.error('준법문의 요청 중 오류가 발생했습니다.')
+ } finally {
+ setLoading(false)
+ }
return
}
setLegalReviewDialog(true)
@@ -617,31 +722,72 @@ export function BasicContractDetailTableToolbarActions({
</span>
</Button>
- {/* 법무검토 버튼 (SSLVW 데이터 조회) */}
- <SSLVWPurInqReqDialog
- onConfirm={handleSSLVWConfirm}
- requireSingleSelection
- triggerDisabled={selectedRows.length !== 1 || loading}
- triggerTitle={
- selectedRows.length !== 1
- ? "계약서 한 건을 선택해주세요"
- : undefined
- }
- />
+ {/* 법무검토 버튼 (SSLVW 데이터 조회) - 준법서약 템플릿이 아닐 때만 표시 */}
+ {!isComplianceTemplate && (
+ <SSLVWPurInqReqDialog
+ onConfirm={handleSSLVWConfirm}
+ requireSingleSelection
+ triggerDisabled={selectedRows.length !== 1 || loading}
+ triggerTitle={
+ selectedRows.length !== 1
+ ? "계약서 한 건을 선택해주세요"
+ : undefined
+ }
+ />
+ )}
+
+ {/* 준법문의 요청 데이터 조회 버튼 (준법서약 템플릿만) */}
+ {isComplianceTemplate && (
+ <CPVWWabQustListViewDialog
+ onConfirm={handleCPVWConfirm}
+ requireSingleSelection
+ triggerDisabled={selectedRows.length !== 1 || loading}
+ triggerTitle={
+ selectedRows.length !== 1
+ ? "계약서 한 건을 선택해주세요"
+ : undefined
+ }
+ />
+ )}
{/* 법무검토 요청 / 준법문의 버튼 */}
- <Button
- variant="outline"
- size="sm"
- onClick={handleRequestLegalReview}
- className="gap-2"
- title={isComplianceTemplate ? "준법문의 링크로 이동" : "법무검토 요청 링크 선택"}
- >
- <FileText className="size-4" aria-hidden="true" />
- <span className="hidden sm:inline">
- {isComplianceTemplate ? "준법문의" : "법무검토 요청"}
- </span>
- </Button>
+ {isComplianceTemplate ? (
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={handleRequestLegalReview}
+ className="gap-2"
+ disabled={!canRequestComplianceInquiry || loading}
+ title={
+ !canRequestComplianceInquiry
+ ? "협력업체 서명 완료, 협의 완료, 레드플래그 해소가 필요합니다"
+ : "준법문의 링크로 이동"
+ }
+ >
+ <FileText className="size-4" aria-hidden="true" />
+ <span className="hidden sm:inline">
+ 준법문의
+ </span>
+ </Button>
+ ) : (
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={handleRequestLegalReview}
+ className="gap-2"
+ disabled={!canRequestLegalReview || loading}
+ title={
+ !canRequestLegalReview
+ ? "협력업체 서명 완료 및 협의 완료가 필요합니다"
+ : "법무검토 요청 링크 선택"
+ }
+ >
+ <FileText className="size-4" aria-hidden="true" />
+ <span className="hidden sm:inline">
+ 법무검토 요청
+ </span>
+ </Button>
+ )}
{/* 최종승인 버튼 */}
<Button