diff options
Diffstat (limited to 'lib/evaluation')
| -rw-r--r-- | lib/evaluation/service.ts | 76 |
1 files changed, 71 insertions, 5 deletions
diff --git a/lib/evaluation/service.ts b/lib/evaluation/service.ts index bbe9daa9..76811753 100644 --- a/lib/evaluation/service.ts +++ b/lib/evaluation/service.ts @@ -11,6 +11,8 @@ import { regEvalCriteriaDetails, reviewerEvaluationDetails, reviewerEvaluations, + roles, + userRoles, users, type PeriodicEvaluationView } from "@/db/schema" @@ -20,7 +22,7 @@ import { count, desc, ilike, - or, sql, eq, avg, inArray, + or, sql, eq, avg, inArray,like, type SQL } from "drizzle-orm" import { filterColumns } from "@/lib/filter-columns" @@ -431,8 +433,8 @@ export async function getReviewersForEvaluations( return [] } - // evaluation_target_reviewers와 users 테이블 조인 - const reviewers = await db + // 1. 기존 방식: evaluation_target_reviewers와 users 테이블 조인 + const designatedReviewers = await db .select({ id: users.id, name: users.name, @@ -452,12 +454,76 @@ export async function getReviewersForEvaluations( ) .orderBy(evaluationTargetReviewers.evaluationTargetId, users.name) - return reviewers + // 2. 추가: role name에 "정기평가"가 포함된 사용자들 + const roleBasedReviewers = await db + .select({ + id: users.id, + name: users.name, + email: users.email, + deptName: users.deptName, + roleName: roles.name, + }) + .from(users) + .innerJoin(userRoles, eq(users.id, userRoles.userId)) + .innerJoin(roles, eq(userRoles.roleId, roles.id)) + .where( + and( + like(roles.name, '%정기평가%'), + eq(users.isActive, true) + ) + ) + + // 3. role 기반 리뷰어들을 각 evaluationTargetId에 대해 확장 + const expandedRoleBasedReviewers: ReviewerInfo[] = [] + + for (const evaluationTargetId of evaluationTargetIds) { + for (const reviewer of roleBasedReviewers) { + expandedRoleBasedReviewers.push({ + id: reviewer.id, + name: reviewer.name, + email: reviewer.email, + deptName: reviewer.deptName, + departmentCode: 'administrator', // 고정값 + evaluationTargetId: evaluationTargetId, + evaluationTargetReviewerId: -1, // role 기반 리뷰어는 별도 ID 사용 (음수로 구분) + }) + } + } + + // 4. 중복 제거 (같은 사용자가 designated reviewer와 role-based reviewer 모두에 있을 수 있음) + const allReviewers = [...designatedReviewers, ...expandedRoleBasedReviewers] + + // evaluationTargetId + userId 조합으로 중복 제거 + const uniqueReviewers = allReviewers.reduce((acc, reviewer) => { + const key = `${reviewer.evaluationTargetId}-${reviewer.id}` + + // 이미 있는 경우 designated reviewer를 우선 (evaluationTargetReviewerId가 양수인 것) + if (acc[key]) { + if (reviewer.evaluationTargetReviewerId > 0) { + acc[key] = reviewer // designated reviewer로 교체 + } + // 이미 designated reviewer가 있으면 role-based는 무시 + } else { + acc[key] = reviewer + } + + return acc + }, {} as Record<string, ReviewerInfo>) + + return Object.values(uniqueReviewers).sort((a, b) => { + // evaluationTargetId로 먼저 정렬, 그 다음 이름으로 정렬 + if (a.evaluationTargetId !== b.evaluationTargetId) { + return a.evaluationTargetId - b.evaluationTargetId + } + return a.name.localeCompare(b.name) + }) + } catch (error) { console.error('Error fetching reviewers for evaluations:', error) throw new Error('평가자 정보를 가져오는데 실패했습니다.') } } + // ================================================================ // 2. 리뷰어 평가 요청 생성 및 알림 발송 // ================================================================ @@ -673,7 +739,7 @@ async function sendEvaluationRequestEmails( email: r?.userEmail })).filter(r => r.name), message: message || "협력업체 정기평가를 진행해 주시기 바랍니다.", - evaluationUrl: `${process.env.NEXT_PUBLIC_APP_URL}/evaluations/${group.periodicEvaluationId}/review` + evaluationUrl: `${process.env.NEXT_PUBLIC_BASE_URL}/evaluations/${group.periodicEvaluationId}/review` }, }).catch(error => { console.error(`${reviewer.userEmail}에게 이메일 발송 실패:`, error) |
