Files
gridpilot.gg/packages/racing/domain/entities/Season.ts
2025-12-11 13:50:38 +01:00

101 lines
2.5 KiB
TypeScript

export type SeasonStatus = 'planned' | 'active' | 'completed';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import type { IEntity } from '@gridpilot/shared/domain';
export class Season implements IEntity<string> {
readonly id: string;
readonly leagueId: string;
readonly gameId: string;
readonly name: string;
readonly year?: number;
readonly order?: number;
readonly status: SeasonStatus;
readonly startDate?: Date;
readonly endDate?: Date;
private constructor(props: {
id: string;
leagueId: string;
gameId: string;
name: string;
year?: number;
order?: number;
status: SeasonStatus;
startDate?: Date;
endDate?: Date;
}) {
this.id = props.id;
this.leagueId = props.leagueId;
this.gameId = props.gameId;
this.name = props.name;
this.year = props.year;
this.order = props.order;
this.status = props.status;
this.startDate = props.startDate;
this.endDate = props.endDate;
}
static create(props: {
id: string;
leagueId: string;
gameId: string;
name: string;
year?: number;
order?: number;
status?: SeasonStatus;
startDate?: Date;
endDate?: Date;
}): Season {
if (!props.id || props.id.trim().length === 0) {
throw new RacingDomainValidationError('Season ID is required');
}
if (!props.leagueId || props.leagueId.trim().length === 0) {
throw new RacingDomainValidationError('Season leagueId is required');
}
if (!props.gameId || props.gameId.trim().length === 0) {
throw new RacingDomainValidationError('Season gameId is required');
}
if (!props.name || props.name.trim().length === 0) {
throw new RacingDomainValidationError('Season name is required');
}
const status: SeasonStatus = props.status ?? 'planned';
return new Season({
id: props.id,
leagueId: props.leagueId,
gameId: props.gameId,
name: props.name,
year: props.year,
order: props.order,
status,
startDate: props.startDate,
endDate: props.endDate,
});
}
/**
* Domain rule: Wallet withdrawals are only allowed when season is completed
*/
canWithdrawFromWallet(): boolean {
return this.status === 'completed';
}
/**
* Check if season is active
*/
isActive(): boolean {
return this.status === 'active';
}
/**
* Check if season is completed
*/
isCompleted(): boolean {
return this.status === 'completed';
}
}