harden business rules
This commit is contained in:
97
core/racing/domain/value-objects/MaxParticipants.ts
Normal file
97
core/racing/domain/value-objects/MaxParticipants.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Domain Value Object: MaxParticipants
|
||||
*
|
||||
* Represents the maximum number of participants allowed in a league or race.
|
||||
* Enforces reasonable limits and constraints.
|
||||
*/
|
||||
|
||||
import type { IValueObject } from '@core/shared/domain';
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
|
||||
export interface MaxParticipantsProps {
|
||||
value: number;
|
||||
}
|
||||
|
||||
export class MaxParticipants implements IValueObject<MaxParticipantsProps> {
|
||||
readonly value: number;
|
||||
|
||||
private constructor(value: number) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
static create(value: number): MaxParticipants {
|
||||
if (!Number.isInteger(value) || value <= 0) {
|
||||
throw new RacingDomainValidationError('Max participants must be a positive integer');
|
||||
}
|
||||
|
||||
// Enforce reasonable upper limit to prevent system abuse
|
||||
if (value > 100) {
|
||||
throw new RacingDomainValidationError('Max participants cannot exceed 100');
|
||||
}
|
||||
|
||||
return new MaxParticipants(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that max participants meets minimum requirements for ranked leagues
|
||||
*/
|
||||
validateForRankedLeague(): { valid: boolean; error?: string } {
|
||||
if (this.value < 10) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Ranked leagues must allow at least 10 participants'
|
||||
};
|
||||
}
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that max participants meets minimum requirements for unranked leagues
|
||||
*/
|
||||
validateForUnrankedLeague(): { valid: boolean; error?: string } {
|
||||
if (this.value < 2) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Unranked leagues must allow at least 2 participants'
|
||||
};
|
||||
}
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if max participants is sufficient for the given participant count
|
||||
*/
|
||||
canAccommodate(participantCount: number): boolean {
|
||||
return participantCount <= this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if max participants is at least the given minimum
|
||||
*/
|
||||
isAtLeast(min: number): boolean {
|
||||
return this.value >= min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if max participants is exactly the given value
|
||||
*/
|
||||
isExactly(value: number): boolean {
|
||||
return this.value === value;
|
||||
}
|
||||
|
||||
get props(): MaxParticipantsProps {
|
||||
return { value: this.value };
|
||||
}
|
||||
|
||||
equals(other: IValueObject<MaxParticipantsProps>): boolean {
|
||||
return this.value === other.props.value;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.value.toString();
|
||||
}
|
||||
|
||||
toNumber(): number {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user