import { Inject } from '@nestjs/common' ; import { IQueryHandler , QueryHandler } from '@nestjs/cqrs' ; import { PrEntity , RepositoryEntity } from '@pimp-my-pr/server/repository/core/domain' ; import { PrRepository , prRepositoryFactoryToken , RepositoryRepository , SettingsRepository } from '@pimp-my-pr/server/repository/core/domain-services' ; import { Platform } from '@pimp-my-pr/shared/domain' ; import { ReviewerModelWithPr } from '../../read-models/reviewer-model-with-pr.interface' ; import { ListReviewersStatisticsQuery } from './list-reviewers-statistics.query' ; import { ReviewersStatisticsItemReadModel } from './reviewers-statistics-item-read.model' ; import { getTimeDiffInHours } from '@pimp-my-pr/shared/util-time-diff-in-hours' ; @ QueryHandler ( ListReviewersStatisticsQuery ) export class ListReviewersStatisticsHandler implements IQueryHandler < ListReviewersStatisticsQuery , ReviewersStatisticsItemReadModel [ ] > { constructor ( @ Inject ( prRepositoryFactoryToken ) private prRepositoryFactory , private repositoryRepository , private settingsRepository ) { } async execute ( query ) { const prRepository = this . prRepositoryFactory ( query . platform ) ; const repositories = await this . repositoryRepository . findByUserId ( query . userId ) ; const repositoriesPrs = new Map < RepositoryEntity , PrEntity [ ] > ( ) ; const nestedPrs = await Promise . all ( repositories . map ( repository => prRepository . findByRepositoryId ( repository . fullName , query . token ) ) ) ; nestedPrs . forEach ( ( prs , index ) => repositoriesPrs . set ( repositories [ index ] , prs ) ) ; const maxPrsPending = await this . settingsRepository . getByUserAndType ( query . userId , 'maxPendingPR' ) ; const maxTimeWaiting = await this . settingsRepository . getByUserAndType ( query . userId , 'maxSumTimeForPR' ) ; const maxLinesToCheck = await this . settingsRepository . getByUserAndType ( query . userId , 'maxTotalLines' ) ; const reviewersWithPrs = this . groupPrsByReviewers ( repositoriesPrs ) ; return reviewersWithPrs . map ( ( { reviewer , prs } ) => new ReviewersStatisticsItemReadModel ( reviewer , prs , this . getTotalPrsWarning ( prs , Number ( maxPrsPending . typedValue ) ) , this . getMaxLinesWarning ( prs , Number ( maxLinesToCheck . typedValue ) ) , this . getMaxWaitingTimeWarning ( prs , Number ( maxTimeWaiting . typedValue ) ) ) ) ; } private groupPrsByReviewers ( repositoriesPrs ) { const result = { } ; repositoriesPrs . forEach ( ( repositoryPrs , repository ) => { repositoryPrs . forEach ( repositoryPr => { repositoryPr . reviewers . forEach ( reviewer => { const prs = result [ reviewer . id ] ?. prs . concat ( repositoryPr ) || [ repositoryPr ] ; result [ reviewer . id ] = { reviewer , prs : prs } ; } ) ; } ) ; } ) ; return Object . values ( result ) ; } private getTotalPrsWarning ( prs , limit ) { return prs . length > limit ; } private getMaxWaitingTimeWarning ( prs , limit ) { return ( prs . reduce ( ( max , model ) => Math . max ( max , getTimeDiffInHours ( model . updatedAt ) ) , 0 ) > limit ) ; } private getMaxLinesWarning ( prs , limit ) { return prs . reduce ( ( max , current ) => Math . max ( max , current . linesOfCodeToCheck ) , 0 ) > limit ; } }