refactor racing use cases
This commit is contained in:
@@ -5,44 +5,103 @@
|
||||
*/
|
||||
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import { Logger, UseCaseOutputPort } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
|
||||
import type { IProtestRepository } from '../../domain/repositories/IProtestRepository';
|
||||
|
||||
export interface SubmitProtestDefenseCommand {
|
||||
export type SubmitProtestDefenseInput = {
|
||||
leagueId: string;
|
||||
protestId: string;
|
||||
driverId: string;
|
||||
statement: string;
|
||||
defenseText: string;
|
||||
videoUrl?: string;
|
||||
}
|
||||
};
|
||||
|
||||
type SubmitProtestDefenseErrorCode = 'PROTEST_NOT_FOUND' | 'NOT_ACCUSED_DRIVER' | 'DEFENSE_CANNOT_BE_SUBMITTED';
|
||||
export type SubmitProtestDefenseResult = {
|
||||
leagueId: string;
|
||||
protestId: string;
|
||||
driverId: string;
|
||||
status: 'defense_submitted';
|
||||
};
|
||||
|
||||
export type SubmitProtestDefenseErrorCode =
|
||||
| 'LEAGUE_NOT_FOUND'
|
||||
| 'PROTEST_NOT_FOUND'
|
||||
| 'DRIVER_NOT_ALLOWED'
|
||||
| 'INVALID_PROTEST_STATE'
|
||||
| 'REPOSITORY_ERROR';
|
||||
|
||||
export class SubmitProtestDefenseUseCase {
|
||||
constructor(
|
||||
private readonly leagueRepository: ILeagueRepository,
|
||||
private readonly protestRepository: IProtestRepository,
|
||||
private readonly logger: Logger,
|
||||
private readonly output: UseCaseOutputPort<SubmitProtestDefenseResult>,
|
||||
) {}
|
||||
|
||||
async execute(command: SubmitProtestDefenseCommand): Promise<Result<{ protestId: string }, ApplicationErrorCode<SubmitProtestDefenseErrorCode>>> {
|
||||
// Get the protest
|
||||
const protest = await this.protestRepository.findById(command.protestId);
|
||||
if (!protest) {
|
||||
return Result.err({ code: 'PROTEST_NOT_FOUND' });
|
||||
async execute(
|
||||
input: SubmitProtestDefenseInput,
|
||||
): Promise<Result<void, ApplicationErrorCode<SubmitProtestDefenseErrorCode, { message: string }>>> {
|
||||
try {
|
||||
const league = await this.leagueRepository.findById(input.leagueId);
|
||||
if (!league) {
|
||||
return Result.err({
|
||||
code: 'LEAGUE_NOT_FOUND',
|
||||
details: { message: 'League not found' },
|
||||
});
|
||||
}
|
||||
|
||||
const protest = await this.protestRepository.findById(input.protestId);
|
||||
if (!protest) {
|
||||
return Result.err({
|
||||
code: 'PROTEST_NOT_FOUND',
|
||||
details: { message: 'Protest not found' },
|
||||
});
|
||||
}
|
||||
|
||||
if (protest.accusedDriverId !== input.driverId) {
|
||||
return Result.err({
|
||||
code: 'DRIVER_NOT_ALLOWED',
|
||||
details: { message: 'Driver is not allowed to submit a defense for this protest' },
|
||||
});
|
||||
}
|
||||
|
||||
if (!protest.canSubmitDefense()) {
|
||||
return Result.err({
|
||||
code: 'INVALID_PROTEST_STATE',
|
||||
details: { message: 'Defense cannot be submitted for this protest' },
|
||||
});
|
||||
}
|
||||
|
||||
const updatedProtest = protest.submitDefense(input.defenseText, input.videoUrl);
|
||||
await this.protestRepository.update(updatedProtest);
|
||||
|
||||
const result: SubmitProtestDefenseResult = {
|
||||
leagueId: input.leagueId,
|
||||
protestId: protest.id,
|
||||
driverId: input.driverId,
|
||||
status: 'defense_submitted',
|
||||
};
|
||||
|
||||
this.output.present(result);
|
||||
|
||||
return Result.ok(undefined);
|
||||
} catch (error: unknown) {
|
||||
const message =
|
||||
error instanceof Error && typeof error.message === 'string'
|
||||
? error.message
|
||||
: 'Failed to submit protest defense';
|
||||
|
||||
this.logger.error(
|
||||
'SubmitProtestDefenseUseCase.execute failed',
|
||||
error instanceof Error ? error : undefined,
|
||||
);
|
||||
|
||||
return Result.err({
|
||||
code: 'REPOSITORY_ERROR',
|
||||
details: { message },
|
||||
});
|
||||
}
|
||||
|
||||
// Verify the submitter is the accused driver
|
||||
if (protest.accusedDriverId !== command.driverId) {
|
||||
return Result.err({ code: 'NOT_ACCUSED_DRIVER' });
|
||||
}
|
||||
|
||||
// Check if defense can be submitted
|
||||
if (!protest.canSubmitDefense()) {
|
||||
return Result.err({ code: 'DEFENSE_CANNOT_BE_SUBMITTED' });
|
||||
}
|
||||
|
||||
// Submit defense
|
||||
const updatedProtest = protest.submitDefense(command.statement, command.videoUrl);
|
||||
await this.protestRepository.update(updatedProtest);
|
||||
|
||||
return Result.ok({ protestId: protest.id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user