team rating
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Provider } from '@nestjs/common';
|
||||
|
||||
import { IMAGE_SERVICE_TOKEN, LOGGER_TOKEN } from './TeamTokens';
|
||||
import { IMAGE_SERVICE_TOKEN, LOGGER_TOKEN, TEAM_STATS_REPOSITORY_TOKEN, MEDIA_REPOSITORY_TOKEN } from './TeamTokens';
|
||||
|
||||
export {
|
||||
TEAM_REPOSITORY_TOKEN,
|
||||
@@ -8,16 +8,22 @@ export {
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
IMAGE_SERVICE_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
TEAM_STATS_REPOSITORY_TOKEN,
|
||||
MEDIA_REPOSITORY_TOKEN,
|
||||
} from './TeamTokens';
|
||||
|
||||
// Import core interfaces
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import type { ITeamStatsRepository } from '@core/racing/domain/repositories/ITeamStatsRepository';
|
||||
|
||||
// Import concrete in-memory implementations
|
||||
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
|
||||
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
|
||||
import { InMemoryTeamStatsRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamStatsRepository';
|
||||
import { InMemoryMediaRepository } from '@adapters/racing/persistence/media/InMemoryMediaRepository';
|
||||
|
||||
// Use cases are imported and used directly in the service
|
||||
// Import presenters
|
||||
import { AllTeamsPresenter } from './presenters/AllTeamsPresenter';
|
||||
|
||||
export const TeamProviders: Provider[] = [
|
||||
{
|
||||
@@ -29,5 +35,19 @@ export const TeamProviders: Provider[] = [
|
||||
provide: LOGGER_TOKEN,
|
||||
useClass: ConsoleLogger,
|
||||
},
|
||||
// Use cases are created directly in the service
|
||||
{
|
||||
provide: TEAM_STATS_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryTeamStatsRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: MEDIA_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryMediaRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: AllTeamsPresenter,
|
||||
useFactory: (teamStatsRepository: ITeamStatsRepository) => new AllTeamsPresenter(teamStatsRepository),
|
||||
inject: [TEAM_STATS_REPOSITORY_TOKEN],
|
||||
},
|
||||
];
|
||||
@@ -111,7 +111,37 @@ describe('TeamService', () => {
|
||||
error: vi.fn(),
|
||||
} as unknown as Logger;
|
||||
|
||||
service = new TeamService(teamRepository as unknown as never, membershipRepository as unknown as never, driverRepository as unknown as never, logger);
|
||||
const teamStatsRepository = {
|
||||
getTeamStats: vi.fn(),
|
||||
getTeamStatsSync: vi.fn(),
|
||||
saveTeamStats: vi.fn(),
|
||||
getAllStats: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
};
|
||||
|
||||
const mediaRepository = {
|
||||
getTeamAvatar: vi.fn(),
|
||||
saveTeamAvatar: vi.fn(),
|
||||
getDriverAvatar: vi.fn(),
|
||||
saveDriverAvatar: vi.fn(),
|
||||
};
|
||||
|
||||
const allTeamsPresenter = {
|
||||
reset: vi.fn(),
|
||||
present: vi.fn(),
|
||||
getResponseModel: vi.fn(() => ({ teams: [], totalCount: 0 })),
|
||||
responseModel: { teams: [], totalCount: 0 },
|
||||
};
|
||||
|
||||
service = new TeamService(
|
||||
teamRepository as unknown as never,
|
||||
membershipRepository as unknown as never,
|
||||
driverRepository as unknown as never,
|
||||
logger,
|
||||
teamStatsRepository as unknown as never,
|
||||
mediaRepository as unknown as never,
|
||||
allTeamsPresenter as unknown as never
|
||||
);
|
||||
});
|
||||
|
||||
it('getAll returns teams and totalCount on success', async () => {
|
||||
|
||||
@@ -37,7 +37,9 @@ import { CreateTeamPresenter } from './presenters/CreateTeamPresenter';
|
||||
import { UpdateTeamPresenter } from './presenters/UpdateTeamPresenter';
|
||||
|
||||
// Tokens
|
||||
import { TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LOGGER_TOKEN } from './TeamTokens';
|
||||
import { TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LOGGER_TOKEN, TEAM_STATS_REPOSITORY_TOKEN, MEDIA_REPOSITORY_TOKEN } from './TeamTokens';
|
||||
import type { ITeamStatsRepository } from '@core/racing/domain/repositories/ITeamStatsRepository';
|
||||
import type { IMediaRepository } from '@core/racing/domain/repositories/IMediaRepository';
|
||||
|
||||
@Injectable()
|
||||
export class TeamService {
|
||||
@@ -46,20 +48,29 @@ export class TeamService {
|
||||
@Inject(TEAM_MEMBERSHIP_REPOSITORY_TOKEN) private readonly membershipRepository: ITeamMembershipRepository,
|
||||
@Inject(DRIVER_REPOSITORY_TOKEN) private readonly driverRepository: IDriverRepository,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
@Inject(TEAM_STATS_REPOSITORY_TOKEN) private readonly teamStatsRepository: ITeamStatsRepository,
|
||||
@Inject(MEDIA_REPOSITORY_TOKEN) private readonly mediaRepository: IMediaRepository,
|
||||
private readonly allTeamsPresenter: AllTeamsPresenter,
|
||||
) {}
|
||||
|
||||
async getAll(): Promise<GetAllTeamsOutputDTO> {
|
||||
this.logger.debug('[TeamService] Fetching all teams.');
|
||||
|
||||
const presenter = new AllTeamsPresenter();
|
||||
const useCase = new GetAllTeamsUseCase(this.teamRepository, this.membershipRepository, this.logger, presenter);
|
||||
const useCase = new GetAllTeamsUseCase(
|
||||
this.teamRepository,
|
||||
this.membershipRepository,
|
||||
this.teamStatsRepository,
|
||||
this.mediaRepository,
|
||||
this.logger,
|
||||
this.allTeamsPresenter
|
||||
);
|
||||
const result = await useCase.execute();
|
||||
if (result.isErr()) {
|
||||
this.logger.error('Error fetching all teams', new Error(result.error?.details?.message || 'Unknown error'));
|
||||
return { teams: [], totalCount: 0 };
|
||||
}
|
||||
|
||||
return presenter.getResponseModel()!;
|
||||
return this.allTeamsPresenter.getResponseModel()!;
|
||||
}
|
||||
|
||||
async getDetails(teamId: string, userId?: string): Promise<GetTeamDetailsOutputDTO | null> {
|
||||
|
||||
@@ -2,4 +2,6 @@ export const TEAM_REPOSITORY_TOKEN = 'ITeamRepository';
|
||||
export const TEAM_MEMBERSHIP_REPOSITORY_TOKEN = 'ITeamMembershipRepository';
|
||||
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
|
||||
export const IMAGE_SERVICE_TOKEN = 'IImageServicePort';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
export const TEAM_STATS_REPOSITORY_TOKEN = 'ITeamStatsRepository';
|
||||
export const MEDIA_REPOSITORY_TOKEN = 'IMediaRepository';
|
||||
@@ -1,21 +1,23 @@
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import type { GetAllTeamsResult } from '@core/racing/application/use-cases/GetAllTeamsUseCase';
|
||||
import { GetAllTeamsOutputDTO } from '../dtos/GetAllTeamsOutputDTO';
|
||||
import { TeamStatsStore } from '@adapters/racing/services/TeamStatsStore';
|
||||
import type { ITeamStatsRepository } from '@core/racing/domain/repositories/ITeamStatsRepository';
|
||||
|
||||
export class AllTeamsPresenter implements UseCaseOutputPort<GetAllTeamsResult> {
|
||||
private model: GetAllTeamsOutputDTO | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly teamStatsRepository: ITeamStatsRepository
|
||||
) {}
|
||||
|
||||
reset(): void {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(result: GetAllTeamsResult): void {
|
||||
const statsStore = TeamStatsStore.getInstance();
|
||||
|
||||
this.model = {
|
||||
teams: result.teams.map(team => {
|
||||
const stats = statsStore.getTeamStats(team.id.toString());
|
||||
const stats = this.teamStatsRepository.getTeamStatsSync(team.id.toString());
|
||||
|
||||
return {
|
||||
id: team.id,
|
||||
|
||||
Reference in New Issue
Block a user