Files
gridpilot.gg/core/racing/domain/value-objects/SeasonStatus.ts
2026-01-16 16:46:57 +01:00

136 lines
2.9 KiB
TypeScript

/**
* Domain Value Object: SeasonStatus
*
* Represents the status of a season with strict lifecycle rules.
*/
import type { ValueObject } from '@core/shared/domain/ValueObject';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
export type SeasonStatusValue = 'planned' | 'active' | 'completed' | 'archived' | 'cancelled';
export interface SeasonStatusProps {
value: SeasonStatusValue;
}
export class SeasonStatus implements ValueObject<SeasonStatusProps> {
readonly value: SeasonStatusValue;
private constructor(value: SeasonStatusValue) {
this.value = value;
}
static create(value: SeasonStatusValue): SeasonStatus {
if (!value) {
throw new RacingDomainValidationError('Season status is required');
}
return new SeasonStatus(value);
}
/**
* Check if season can be activated
*/
canActivate(): boolean {
return this.value === 'planned';
}
/**
* Check if season can be completed
*/
canComplete(): boolean {
return this.value === 'active';
}
/**
* Check if season can be archived
*/
canArchive(): boolean {
return this.value === 'completed';
}
/**
* Check if season can be cancelled
*/
canCancel(): boolean {
return this.value === 'planned' || this.value === 'active';
}
/**
* Check if season is in a terminal state
*/
isTerminal(): boolean {
return this.value === 'completed' || this.value === 'archived' || this.value === 'cancelled';
}
/**
* Check if season is active
*/
isActive(): boolean {
return this.value === 'active';
}
/**
* Check if season is completed
*/
isCompleted(): boolean {
return this.value === 'completed';
}
/**
* Check if season is planned
*/
isPlanned(): boolean {
return this.value === 'planned';
}
/**
* Check if season is archived
*/
isArchived(): boolean {
return this.value === 'archived';
}
/**
* Check if season is cancelled
*/
isCancelled(): boolean {
return this.value === 'cancelled';
}
/**
* Validate transition from current status to target status
*/
canTransitionTo(target: SeasonStatusValue): { valid: boolean; error?: string } {
const current = this.value;
// Define allowed transitions
const allowedTransitions: Record<SeasonStatusValue, SeasonStatusValue[]> = {
planned: ['active', 'cancelled'],
active: ['completed', 'cancelled'],
completed: ['archived'],
archived: [],
cancelled: [],
};
if (!allowedTransitions[current].includes(target)) {
return {
valid: false,
error: `Cannot transition from ${current} to ${target}`
};
}
return { valid: true };
}
get props(): SeasonStatusProps {
return { value: this.value };
}
equals(other: ValueObject<SeasonStatusProps>): boolean {
return this.value === other.props.value;
}
toString(): SeasonStatusValue {
return this.value;
}
}