diff --git a/backend/src/services/risk.service.ts b/backend/src/services/risk.service.ts index 19e9a5e..1c11c98 100644 --- a/backend/src/services/risk.service.ts +++ b/backend/src/services/risk.service.ts @@ -508,6 +508,29 @@ export async function detectRetirementRisks(orgId: string) { } export async function runRiskDetection(orgId: string) { + // 清理重复 PENDING 风险:同一 employeeId:type 只保留最新一条 PENDING + const pendingRisks = await prisma.riskItem.findMany({ + where: { orgId, status: 'PENDING', employeeId: { not: null } }, + select: { id: true, employeeId: true, type: true, createdAt: true }, + orderBy: { createdAt: 'desc' }, + }) + const seenKeys = new Set() + const duplicateIds: string[] = [] + for (const r of pendingRisks) { + const key = `${r.employeeId}:${r.type}` + if (seenKeys.has(key)) { + duplicateIds.push(r.id) + } else { + seenKeys.add(key) + } + } + if (duplicateIds.length > 0) { + await prisma.riskItem.updateMany({ + where: { id: { in: duplicateIds } }, + data: { status: 'RESOLVED', resolvedAt: new Date() }, + }) + } + // 非月度风险去重:检查所有状态(含 RESOLVED/IGNORED),避免已处理的风险被重新创建 // 按 employeeId:type 归并,不依赖 actionUrl(actionUrl 可能因天数变化而不同) const existingRisks = await prisma.riskItem.findMany({ @@ -538,8 +561,12 @@ export async function runRiskDetection(orgId: string) { const specialStatusRisks = await detectSpecialStatusRisks(orgId) const retirementRisks = await detectRetirementRisks(orgId) + // 去重:contractRisks 已覆盖"未签合同",onboardingRisks 中相同员工不再重复生成 + const contractEmployeeIds = new Set(contractRisks.map(r => r.employeeId)) + const filteredOnboardingRisks = onboardingRisks.filter(r => !contractEmployeeIds.has(r.employeeId)) + // 获取所有相关员工数据用于风险量化 - const allEmployeeIds = [...contractRisks, ...terminationRisks, ...onboardingRisks, ...specialStatusRisks, ...retirementRisks] + const allEmployeeIds = [...contractRisks, ...terminationRisks, ...filteredOnboardingRisks, ...specialStatusRisks, ...retirementRisks] .map(r => r.employeeId) .filter(Boolean) as string[] const employees = allEmployeeIds.length > 0 @@ -548,7 +575,7 @@ export async function runRiskDetection(orgId: string) { const empMap = new Map(employees.map(e => [e.id, e])) // 月度任务用 monthlyKeys 去重,其他任务用 existingKeys 去重 - const nonMonthlyRisks = [...contractRisks, ...terminationRisks, ...onboardingRisks, ...specialStatusRisks, ...retirementRisks] + const nonMonthlyRisks = [...contractRisks, ...terminationRisks, ...filteredOnboardingRisks, ...specialStatusRisks, ...retirementRisks] const toCreate = [ ...nonMonthlyRisks.filter((r) => !existingKeys.has(`${r.employeeId}:${r.type}`)), ...monthlyTasks.filter((r) => !monthlyKeys.has(`${r.employeeId}:${r.title}`)),