refactor racing use cases
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Season } from '../../domain/entities/Season';
|
||||
import { League } from '../../domain/entities/League';
|
||||
import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository';
|
||||
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
|
||||
import type { LeagueConfigFormModel } from '../dto/LeagueConfigFormDTO';
|
||||
@@ -13,10 +14,11 @@ import { WeekdaySet } from '../../domain/value-objects/WeekdaySet';
|
||||
import { MonthlyRecurrencePattern } from '../../domain/value-objects/MonthlyRecurrencePattern';
|
||||
import type { Weekday } from '../../domain/types/Weekday';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
export interface CreateSeasonForLeagueCommand {
|
||||
export type CreateSeasonForLeagueInput = {
|
||||
leagueId: string;
|
||||
name: string;
|
||||
gameId: string;
|
||||
@@ -26,13 +28,14 @@ export interface CreateSeasonForLeagueCommand {
|
||||
* When omitted, the Season will be created with minimal metadata only.
|
||||
*/
|
||||
config?: LeagueConfigFormModel;
|
||||
}
|
||||
};
|
||||
|
||||
export interface CreateSeasonForLeagueResultDTO {
|
||||
seasonId: string;
|
||||
}
|
||||
export type CreateSeasonForLeagueResult = {
|
||||
league: League;
|
||||
season: Season;
|
||||
};
|
||||
|
||||
type CreateSeasonForLeagueErrorCode = 'LEAGUE_NOT_FOUND' | 'SOURCE_SEASON_NOT_FOUND';
|
||||
type CreateSeasonForLeagueErrorCode = 'LEAGUE_NOT_FOUND' | 'VALIDATION_ERROR' | 'REPOSITORY_ERROR';
|
||||
|
||||
/**
|
||||
* CreateSeasonForLeagueUseCase
|
||||
@@ -44,79 +47,77 @@ export class CreateSeasonForLeagueUseCase {
|
||||
constructor(
|
||||
private readonly leagueRepository: ILeagueRepository,
|
||||
private readonly seasonRepository: ISeasonRepository,
|
||||
private readonly output: UseCaseOutputPort<CreateSeasonForLeagueResult>,
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
command: CreateSeasonForLeagueCommand,
|
||||
): Promise<Result<CreateSeasonForLeagueResultDTO, ApplicationErrorCode<CreateSeasonForLeagueErrorCode>>> {
|
||||
const league = await this.leagueRepository.findById(command.leagueId);
|
||||
if (!league) {
|
||||
return Result.err({
|
||||
code: 'LEAGUE_NOT_FOUND',
|
||||
details: { message: `League not found: ${command.leagueId}` },
|
||||
});
|
||||
}
|
||||
|
||||
let baseSeasonProps: {
|
||||
schedule?: SeasonSchedule;
|
||||
scoringConfig?: SeasonScoringConfig;
|
||||
dropPolicy?: SeasonDropPolicy;
|
||||
stewardingConfig?: SeasonStewardingConfig;
|
||||
maxDrivers?: number;
|
||||
} = {};
|
||||
|
||||
if (command.sourceSeasonId) {
|
||||
const source = await this.seasonRepository.findById(command.sourceSeasonId);
|
||||
if (!source) {
|
||||
input: CreateSeasonForLeagueInput,
|
||||
): Promise<Result<void, ApplicationErrorCode<CreateSeasonForLeagueErrorCode>>> {
|
||||
try {
|
||||
const league = await this.leagueRepository.findById(input.leagueId);
|
||||
if (!league) {
|
||||
return Result.err({
|
||||
code: 'SOURCE_SEASON_NOT_FOUND',
|
||||
details: { message: `Source Season not found: ${command.sourceSeasonId}` },
|
||||
code: 'LEAGUE_NOT_FOUND',
|
||||
details: { message: `League not found: ${input.leagueId}` },
|
||||
});
|
||||
}
|
||||
baseSeasonProps = {
|
||||
...(source.schedule !== undefined ? { schedule: source.schedule } : {}),
|
||||
...(source.scoringConfig !== undefined
|
||||
? { scoringConfig: source.scoringConfig }
|
||||
: {}),
|
||||
...(source.dropPolicy !== undefined ? { dropPolicy: source.dropPolicy } : {}),
|
||||
...(source.stewardingConfig !== undefined
|
||||
? { stewardingConfig: source.stewardingConfig }
|
||||
: {}),
|
||||
...(source.maxDrivers !== undefined ? { maxDrivers: source.maxDrivers } : {}),
|
||||
};
|
||||
} else if (command.config) {
|
||||
baseSeasonProps = this.deriveSeasonPropsFromConfig(command.config);
|
||||
|
||||
let baseSeasonProps: {
|
||||
schedule?: SeasonSchedule;
|
||||
scoringConfig?: SeasonScoringConfig;
|
||||
dropPolicy?: SeasonDropPolicy;
|
||||
stewardingConfig?: SeasonStewardingConfig;
|
||||
maxDrivers?: number;
|
||||
} = {};
|
||||
|
||||
if (input.sourceSeasonId) {
|
||||
const source = await this.seasonRepository.findById(input.sourceSeasonId);
|
||||
if (!source) {
|
||||
return Result.err({
|
||||
code: 'VALIDATION_ERROR',
|
||||
details: { message: `Source Season not found: ${input.sourceSeasonId}` },
|
||||
});
|
||||
}
|
||||
baseSeasonProps = {
|
||||
...(source.schedule !== undefined ? { schedule: source.schedule } : {}),
|
||||
...(source.scoringConfig !== undefined ? { scoringConfig: source.scoringConfig } : {}),
|
||||
...(source.dropPolicy !== undefined ? { dropPolicy: source.dropPolicy } : {}),
|
||||
...(source.stewardingConfig !== undefined ? { stewardingConfig: source.stewardingConfig } : {}),
|
||||
...(source.maxDrivers !== undefined ? { maxDrivers: source.maxDrivers } : {}),
|
||||
};
|
||||
} else if (input.config) {
|
||||
baseSeasonProps = this.deriveSeasonPropsFromConfig(input.config);
|
||||
}
|
||||
|
||||
const seasonId = uuidv4();
|
||||
|
||||
const season = Season.create({
|
||||
id: seasonId,
|
||||
leagueId: league.id,
|
||||
gameId: input.gameId,
|
||||
name: input.name,
|
||||
year: new Date().getFullYear(),
|
||||
status: 'planned',
|
||||
...(baseSeasonProps?.schedule ? { schedule: baseSeasonProps.schedule } : {}),
|
||||
...(baseSeasonProps?.scoringConfig ? { scoringConfig: baseSeasonProps.scoringConfig } : {}),
|
||||
...(baseSeasonProps?.dropPolicy ? { dropPolicy: baseSeasonProps.dropPolicy } : {}),
|
||||
...(baseSeasonProps?.stewardingConfig ? { stewardingConfig: baseSeasonProps.stewardingConfig } : {}),
|
||||
...(baseSeasonProps?.maxDrivers !== undefined ? { maxDrivers: baseSeasonProps.maxDrivers } : {}),
|
||||
});
|
||||
|
||||
await this.seasonRepository.add(season);
|
||||
|
||||
this.output.present({ league, season });
|
||||
|
||||
return Result.ok(undefined);
|
||||
} catch (error) {
|
||||
return Result.err({
|
||||
code: 'REPOSITORY_ERROR',
|
||||
details: {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const seasonId = uuidv4();
|
||||
|
||||
const season = Season.create({
|
||||
id: seasonId,
|
||||
leagueId: league.id,
|
||||
gameId: command.gameId,
|
||||
name: command.name,
|
||||
year: new Date().getFullYear(),
|
||||
status: 'planned',
|
||||
...(baseSeasonProps?.schedule
|
||||
? { schedule: baseSeasonProps.schedule }
|
||||
: {}),
|
||||
...(baseSeasonProps?.scoringConfig
|
||||
? { scoringConfig: baseSeasonProps.scoringConfig }
|
||||
: {}),
|
||||
...(baseSeasonProps?.dropPolicy
|
||||
? { dropPolicy: baseSeasonProps.dropPolicy }
|
||||
: {}),
|
||||
...(baseSeasonProps?.stewardingConfig
|
||||
? { stewardingConfig: baseSeasonProps.stewardingConfig }
|
||||
: {}),
|
||||
...(baseSeasonProps?.maxDrivers !== undefined
|
||||
? { maxDrivers: baseSeasonProps.maxDrivers }
|
||||
: {}),
|
||||
});
|
||||
|
||||
await this.seasonRepository.add(season);
|
||||
|
||||
return Result.ok({ seasonId });
|
||||
}
|
||||
|
||||
private deriveSeasonPropsFromConfig(config: LeagueConfigFormModel): {
|
||||
@@ -216,4 +217,4 @@ export class CreateSeasonForLeagueUseCase {
|
||||
plannedRounds,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user