summaryrefslogtreecommitdiff
path: root/lib/compliance/red-flag-resolution.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compliance/red-flag-resolution.ts')
-rw-r--r--lib/compliance/red-flag-resolution.ts64
1 files changed, 41 insertions, 23 deletions
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<A
throw new Error("구매기획 담당자의 EP ID가 설정되지 않았습니다.")
}
- const contractSummaries = await fetchContractsWithFlags(uniqueContractIds)
- if (contractSummaries.length === 0) {
- throw new Error("선택한 계약서에 RED FLAG가 존재하지 않습니다.")
- }
-
- const validContractIds = contractSummaries.map((contract) => contract.contractId)
-
- // 중복 해소요청 방지 (진행 중인 결재가 있는지 확인)
+ // 준법 응답 및 중복 해소요청 여부를 먼저 확인 (Heavy query 전에 선행)
const responses = await db
.select({
basicContractId: complianceResponses.basicContractId,
@@ -68,33 +61,41 @@ export async function requestRedFlagResolution(contractIds: number[]): Promise<A
redFlagResolutionApprovalId: complianceResponses.redFlagResolutionApprovalId,
})
.from(complianceResponses)
- .where(inArray(complianceResponses.basicContractId, validContractIds))
-
- const missingResponses = validContractIds.filter(
- (contractId) => !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<ContractS
return withFlags.filter((contract) => contract.triggeredFlags.length > 0)
}
+async function fetchContractVendorSummaries(
+ contractIds: number[]
+): Promise<Array<{ contractId: number; vendorName: string | null }>> {
+ 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 }