import type { Bug, BugLog, BugStatus } from './bug'; import { canBugTransition } from './bug'; export interface BugTransitionOptions { now?: Date; resolution?: string; } export interface BugWorkflowResult { ok: boolean; patch?: Partial; message?: string; } function makeBugLog( action: BugLog['action'], operator: string, nowIso: string, from?: string, to?: string, remark?: string, ): BugLog { return { id: `log-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, action, fromValue: from, toValue: to, operator, remark, createdAt: nowIso, }; } export function applyBugTransition( bug: Bug, to: BugStatus, operator: string, options: BugTransitionOptions = {}, ): BugWorkflowResult { if (!canBugTransition(bug.status, to)) { return { ok: false, message: `不允许从「${bug.status}」流转到「${to}」` }; } const nowIso = (options.now ?? new Date()).toISOString(); const patch: Partial = { status: to }; if (to === 'fixed') patch.resolvedAt = nowIso; if (to === 'closed') patch.closedAt = nowIso; if (options.resolution?.trim()) patch.resolution = options.resolution.trim(); const log = makeBugLog( to === 'fixed' ? 'resolve' : 'status_change', operator, nowIso, bug.status, to, options.resolution, ); patch.logs = [...(bug.logs || []), log]; return { ok: true, patch }; }