/** * Domain Value Object: RaceStatus * * Represents the status of a race with strict lifecycle rules. */ import type { ValueObject } from '@core/shared/domain/ValueObject'; import { RacingDomainValidationError } from '../errors/RacingDomainError'; export type RaceStatusValue = 'scheduled' | 'running' | 'completed' | 'cancelled'; export interface RaceStatusProps { value: RaceStatusValue; } export class RaceStatus implements ValueObject { readonly value: RaceStatusValue; private constructor(value: RaceStatusValue) { this.value = value; } static create(value: RaceStatusValue): RaceStatus { if (!value) { throw new RacingDomainValidationError('Race status is required'); } return new RaceStatus(value); } /** * Check if race can be started */ canStart(): boolean { return this.value === 'scheduled'; } /** * Check if race can be completed */ canComplete(): boolean { return this.value === 'running'; } /** * Check if race can be cancelled */ canCancel(): boolean { return this.value === 'scheduled' || this.value === 'running'; } /** * Check if race can be reopened */ canReopen(): boolean { return this.value === 'completed' || this.value === 'cancelled'; } /** * Check if race is in a terminal state */ isTerminal(): boolean { return this.value === 'completed' || this.value === 'cancelled'; } /** * Check if race is running */ isRunning(): boolean { return this.value === 'running'; } /** * Check if race is completed */ isCompleted(): boolean { return this.value === 'completed'; } /** * Check if race is scheduled */ isScheduled(): boolean { return this.value === 'scheduled'; } /** * Check if race is cancelled */ isCancelled(): boolean { return this.value === 'cancelled'; } /** * Validate transition from current status to target status */ canTransitionTo(target: RaceStatusValue): { valid: boolean; error?: string } { const current = this.value; // Define allowed transitions const allowedTransitions: Record = { scheduled: ['running', 'cancelled'], running: ['completed', 'cancelled'], completed: ['scheduled'], cancelled: ['scheduled'], }; if (!allowedTransitions[current].includes(target)) { return { valid: false, error: `Cannot transition from ${current} to ${target}` }; } return { valid: true }; } get props(): RaceStatusProps { return { value: this.value }; } equals(other: ValueObject): boolean { return this.value === other.props.value; } toString(): RaceStatusValue { return this.value; } }