From 79822c5fb48ae7cb1e510fc6c74d55941c502788 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 24 Nov 2025 10:49:28 +0000 Subject: (임수민) 준법 Red Flag 결재 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/compliance/red-flag-resolution.ts | 64 ++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/compliance/red-flag-resolution.ts b/lib/compliance/red-flag-resolution.ts index 423f5a46..af69dbf4 100644 --- a/lib/compliance/red-flag-resolution.ts +++ b/lib/compliance/red-flag-resolution.ts @@ -53,14 +53,7 @@ export async function requestRedFlagResolution(contractIds: number[]): Promise contract.contractId) - - // 중복 해소요청 방지 (진행 중인 결재가 있는지 확인) + // 준법 응답 및 중복 해소요청 여부를 먼저 확인 (Heavy query 전에 선행) const responses = await db .select({ basicContractId: complianceResponses.basicContractId, @@ -68,33 +61,41 @@ export async function requestRedFlagResolution(contractIds: number[]): Promise !responses.some((response) => response.basicContractId === contractId) - ) - - if (missingResponses.length > 0) { - throw new Error("준법 응답 정보를 찾을 수 없는 계약서가 포함되어 있습니다.") - } + .where(inArray(complianceResponses.basicContractId, uniqueContractIds)) const blockedContracts = responses .filter((response) => response.redFlagResolutionApprovalId && !response.redFlagResolvedAt) .map((response) => response.basicContractId) if (blockedContracts.length > 0) { - const blockedSummaries = contractSummaries - .filter((contract) => blockedContracts.includes(contract.contractId)) - .map((contract) => contract.vendorName ?? `계약 ${contract.contractId}`) + const blockedSummaries = await fetchContractVendorSummaries(blockedContracts) + const blockedNames = blockedSummaries.map( + (contract) => contract.vendorName ?? `계약 ${contract.contractId}` + ) const preview = - blockedSummaries.length > 2 - ? `${blockedSummaries.slice(0, 2).join(", ")} 외 ${blockedSummaries.length - 2}건` - : blockedSummaries.join(", ") + blockedNames.length > 2 + ? `${blockedNames.slice(0, 2).join(", ")} 외 ${blockedNames.length - 2}건` + : blockedNames.join(", ") throw new Error(`이미 해소요청이 진행 중인 계약서가 있습니다: ${preview}`) } + const contractSummaries = await fetchContractsWithFlags(uniqueContractIds) + if (contractSummaries.length === 0) { + throw new Error("선택한 계약서에 RED FLAG가 존재하지 않습니다.") + } + + const validContractIds = contractSummaries.map((contract) => contract.contractId) + + const missingResponses = validContractIds.filter( + (contractId) => !responses.some((response) => response.basicContractId === contractId) + ) + + if (missingResponses.length > 0) { + throw new Error("준법 응답 정보를 찾을 수 없는 계약서가 포함되어 있습니다.") + } + const now = new Date() const variables = await buildTemplateVariables(contractSummaries, { requesterName: currentUser.name || currentUser.email || "요청자", @@ -230,6 +231,23 @@ async function fetchContractsWithFlags(contractIds: number[]): Promise contract.triggeredFlags.length > 0) } +async function fetchContractVendorSummaries( + contractIds: number[] +): Promise> { + if (contractIds.length === 0) { + return [] + } + + return db + .select({ + contractId: basicContract.id, + vendorName: vendors.vendorName, + }) + .from(basicContract) + .leftJoin(vendors, eq(basicContract.vendorId, vendors.id)) + .where(inArray(basicContract.id, contractIds)) +} + async function buildTemplateVariables( contracts: ContractSummary[], meta: { requesterName: string; requestedAt: Date } -- cgit v1.2.3