private async Task <IEnumerable <Issue> > QueryPRsToConsider(IssuesQuery query)
        {
            SearchIssuesRequest request = new SearchIssuesRequest
            {
                Is        = GetSearchQueryTerm(query),
                Milestone = query.Milestone,
                Labels    = query.FilterLabels
            };

            if (query.Team.LabelsToExclude != null && query.Team.LabelsToExclude.Any())
            {
                request.Exclusions = new SearchIssuesRequestExclusions
                {
                    Labels = query.Team.LabelsToExclude
                };
            }

            request.ApplyRepositoriesFilter(query.Team.Repositories);

            IList <Issue> result = await this.QueryResultsAsync(request, issue => IssueBelongsToTeam(query.Team, issue));

            /// TODO: Remove this later
            //teamIssues = teamIssues.Where(item => !item.ClosedAt.HasValue || item.ClosedAt.Value >= new DateTimeOffset(2019, 5, 27, 0, 0, 0, TimeSpan.Zero)).ToList();
            return(result);
        }
        private static IEnumerable <IssueIsQualifier> GetSearchQueryTerm(IssuesQuery query)
        {
            List <IssueIsQualifier> terms = new List <IssueIsQualifier>(2);

            terms.Add(query.QueryIssues ? IssueIsQualifier.Issue : IssueIsQualifier.PullRequest);
            switch (query.Clause)
            {
            case IssuesQueryClause.All:
                break;

            case IssuesQueryClause.Open:
                terms.Add(IssueIsQualifier.Open);
                break;

            case IssuesQueryClause.Closed:
                terms.Add(IssueIsQualifier.Closed);
                break;

            case IssuesQueryClause.Merged:
                terms.Add(IssueIsQualifier.Merged);
                break;

            default:
                throw new InvalidOperationException("Unkonwn query type");
            }

            return(terms);
        }
        public async Task <IEnumerable <WorkItem> > GetWorkItemsAsync(IssuesQuery query, CancellationToken cancellationToken)
        {
            query.Ensure(nameof(query)).IsNotNull();

            var searchResults = await QueryIssuesAsync(query);

            return(searchResults
                   .Select(item => new WorkItem
            {
                Owner = item.Assignee == null ? "Unassigned" : item.Assignee.Login,
                Cost = this.GetIssueCost(item),
                Id = item.Number
            }).ToList());
        }
        public async Task <BurndownDTO> GetBurndownDataAsync(IssuesQuery query, CancellationToken cancellationToken)
        {
            IList <Issue> allIssues = (await QueryIssuesToConsider(query)).ToList();

            double         totalAmountOfWork    = allIssues.Sum(item => this.GetIssueCost(item));
            var            allClosedIssues      = allIssues.Where(item => item.State.Value == ItemState.Closed).ToList();
            DateTimeOffset currentDate          = GetDateOfFirstClosedIssue(allClosedIssues).UtcDateTime.Date;
            double         workLeft             = totalAmountOfWork;
            int            numberOfClosedIssues = 0;

            IList <WorkDTO> result = new List <WorkDTO>();

            do
            {
                var issuesClosedOnGivenDate = allClosedIssues.Where(item => item.ClosedAt.Value.UtcDateTime.Date == currentDate);
                if (issuesClosedOnGivenDate.Any())
                {
                    numberOfClosedIssues += issuesClosedOnGivenDate.Count();
                    this.logger.LogInformation($"Found '{issuesClosedOnGivenDate.Count()}' issues closed on '{currentDate.ToString()}'. Total closed issues so far {numberOfClosedIssues}");

                    double amountOfWorkClosedOnDate = issuesClosedOnGivenDate.Sum(item => GetIssueCost(item));
                    if (amountOfWorkClosedOnDate > 0)
                    {
                        result.Add(new WorkDTO
                        {
                            Date           = currentDate,
                            DaysOfWorkLeft = workLeft,
                        });
                        workLeft -= amountOfWorkClosedOnDate;
                    }
                }

                currentDate = currentDate.AddDays(1);
            } while (currentDate < DateTimeOffset.UtcNow);

            result.Add(new WorkDTO
            {
                Date           = currentDate,
                DaysOfWorkLeft = workLeft,
            });

            return(new BurndownDTO
            {
                WorkData = result,
                TotalNumberOfIssues = allIssues.Count,
                NumberOfIssuesLeft = allIssues.Count - numberOfClosedIssues,
            });
        }
        public async Task <IEnumerable <PR> > GetPullRequestsAsync(DateTimeOffset mergedOnOrAfter, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            IList <PR> result = new List <PR>();

            var query = new IssuesQuery
            {
                Team                  = this.teamInfo,
                FilterLabels          = null,
                IncludeInvestigations = false,
                Clause                = IssuesQueryClause.Merged,
                QueryIssues           = false
            };

            var queryResult = await QueryPRsToConsider(query);

            foreach (var issue in queryResult)
            {
                if (issue.PullRequest != null && issue.ClosedAt.HasValue && issue.ClosedAt.Value >= mergedOnOrAfter)
                {
                    result.Add(new PR
                    {
                        ClosedAt     = issue.ClosedAt,
                        CreatorLogin = issue.User.Login,
                        Url          = issue.HtmlUrl,
                        Merged       = issue.ClosedAt.HasValue,
                        Number       = issue.Number,
                        MergedAt     = issue.ClosedAt.Value,
                        Title        = issue.Title,
                    });
                }
            }

            var orgUsers = await this.client.Organization.Member.GetAll(this.teamInfo.Organization);

            foreach (var pr in result)
            {
                pr.IsExternal = !orgUsers.Any(ou => String.Equals(ou.Login, pr.CreatorLogin, StringComparison.InvariantCultureIgnoreCase));
            }

            return(result);
        }
        private async Task <IEnumerable <Issue> > QueryIssuesToConsider(IssuesQuery query)
        {
            IEnumerable <Issue> allIssues = await QueryIssuesAsync(query);

            if (!query.IncludeInvestigations)
            {
                allIssues = allIssues.Where(issue =>
                {
                    if (issue.State.Value == ItemState.Closed && !issue.HasLabel(query.Team.FixedIssuesIndicatingLabel))
                    {
                        // Exclude closed issues, which are not marked as fixed.
                        return(false);
                    }

                    return(true);
                });
            }

            return(allIssues);
        }