101 lines
2.6 KiB
TypeScript
101 lines
2.6 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,
|
|
...(props.year !== undefined ? { year: props.year } : {}),
|
|
...(props.order !== undefined ? { order: props.order } : {}),
|
|
status,
|
|
...(props.startDate !== undefined ? { startDate: props.startDate } : {}),
|
|
...(props.endDate !== undefined ? { 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';
|
|
}
|
|
} |