fix: 风险重复问题
1. runRiskDetection开头清理重复PENDING记录(同employeeId:type只保留最新) 2. onboardingRisks过滤掉已被contractRisks覆盖的员工,避免同一员工出现'未签合同'+'入职手续未完成'两条重复待办
This commit is contained in:
@@ -508,6 +508,29 @@ export async function detectRetirementRisks(orgId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function runRiskDetection(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<string>()
|
||||||
|
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),避免已处理的风险被重新创建
|
// 非月度风险去重:检查所有状态(含 RESOLVED/IGNORED),避免已处理的风险被重新创建
|
||||||
// 按 employeeId:type 归并,不依赖 actionUrl(actionUrl 可能因天数变化而不同)
|
// 按 employeeId:type 归并,不依赖 actionUrl(actionUrl 可能因天数变化而不同)
|
||||||
const existingRisks = await prisma.riskItem.findMany({
|
const existingRisks = await prisma.riskItem.findMany({
|
||||||
@@ -538,8 +561,12 @@ export async function runRiskDetection(orgId: string) {
|
|||||||
const specialStatusRisks = await detectSpecialStatusRisks(orgId)
|
const specialStatusRisks = await detectSpecialStatusRisks(orgId)
|
||||||
const retirementRisks = await detectRetirementRisks(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)
|
.map(r => r.employeeId)
|
||||||
.filter(Boolean) as string[]
|
.filter(Boolean) as string[]
|
||||||
const employees = allEmployeeIds.length > 0
|
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]))
|
const empMap = new Map(employees.map(e => [e.id, e]))
|
||||||
|
|
||||||
// 月度任务用 monthlyKeys 去重,其他任务用 existingKeys 去重
|
// 月度任务用 monthlyKeys 去重,其他任务用 existingKeys 去重
|
||||||
const nonMonthlyRisks = [...contractRisks, ...terminationRisks, ...onboardingRisks, ...specialStatusRisks, ...retirementRisks]
|
const nonMonthlyRisks = [...contractRisks, ...terminationRisks, ...filteredOnboardingRisks, ...specialStatusRisks, ...retirementRisks]
|
||||||
const toCreate = [
|
const toCreate = [
|
||||||
...nonMonthlyRisks.filter((r) => !existingKeys.has(`${r.employeeId}:${r.type}`)),
|
...nonMonthlyRisks.filter((r) => !existingKeys.has(`${r.employeeId}:${r.type}`)),
|
||||||
...monthlyTasks.filter((r) => !monthlyKeys.has(`${r.employeeId}:${r.title}`)),
|
...monthlyTasks.filter((r) => !monthlyKeys.has(`${r.employeeId}:${r.title}`)),
|
||||||
|
|||||||
Reference in New Issue
Block a user