import type { ExpertFileAssignStatus } from "src/common/dto/expert-file-assign-result.dto"; export const BLAME_REVIEW_ASSIGNED_HISTORY_TYPE = "BLAME_ASSIGNED"; export const CLAIM_REVIEW_ASSIGNED_HISTORY_TYPE = "CLAIM_ASSIGNED"; type WorkflowAssigneeRef = { assignedForReviewBy?: { actorId?: unknown; actorName?: string }; lockedBy?: { actorId?: unknown; actorName?: string }; lockedAt?: Date | string; }; type HistoryAssigneeRef = { type?: string; actor?: { actorId?: unknown }; timestamp?: Date | string; }; /** Expert who first assigned via the review assign endpoint (survives lock TTL expiry). */ export function resolvePersistentReviewAssigneeId( workflow: WorkflowAssigneeRef | undefined, history: HistoryAssigneeRef[] | undefined, assignedHistoryType: string, ): string { const fromField = workflow?.assignedForReviewBy?.actorId; if (fromField != null && String(fromField).length > 0) { return String(fromField); } const fromHistory = history?.find( (h) => h.type === assignedHistoryType, )?.actor?.actorId; if (fromHistory != null && String(fromHistory).length > 0) { return String(fromHistory); } return ""; } export function buildExpertAssignConflictForOtherReviewer( assigneeId: string, workflow?: WorkflowAssigneeRef, ): { success: false; status: ExpertFileAssignStatus; message: string; lockedBy: { actorId: string; actorName?: string; lockedAt?: string }; } { const assignee = workflow?.assignedForReviewBy ?? workflow?.lockedBy; const lockedAt = workflow?.lockedAt; return { success: false, status: "locked", message: "Request is already being answered by another expert", lockedBy: { actorId: assigneeId, actorName: assignee?.actorName, lockedAt: lockedAt ? new Date(lockedAt as Date).toISOString() : undefined, }, }; } /** Copy lock holder into `assignedForReviewBy` when persisting a TTL unlock. */ export function blameWorkflowAssigneeToPersistOnLockExpiry( workflow: WorkflowAssigneeRef | undefined, ): WorkflowAssigneeRef["assignedForReviewBy"] | undefined { if (workflow?.assignedForReviewBy) { return undefined; } return workflow?.lockedBy; } export function claimWorkflowAssigneeToPersistOnLockExpiry( workflow: WorkflowAssigneeRef | undefined, ): WorkflowAssigneeRef["assignedForReviewBy"] | undefined { return blameWorkflowAssigneeToPersistOnLockExpiry(workflow); }