public async Task <GetCorrectCapacityQueryResponse> RunRequestAsync(GetCorrectCapacityQueryRequest queryRequest) { var httpHelper = new HttpHelper(_config); var responseString = await httpHelper.GetResponseAsync($"{Constants.BaseAzureDevopsUri}/{_config.OrganisationName}/{_config.ProjectName}/{queryRequest.TeamName}" + $"/_apis/work/teamsettings/iterations/{queryRequest.IterationId}/capacities?api-version={_config.AzureDevopsApiVersion}"); var response = JsonConvert.DeserializeObject <GetIterationCapacitiesList>(responseString); var teamDaysResponseString = await httpHelper.GetResponseAsync($"{Constants.BaseAzureDevopsUri}/{_config.OrganisationName}/{_config.ProjectName}/{queryRequest.TeamName}" + $"/_apis/work/teamsettings/iterations/{queryRequest.IterationId}/teamdaysoff?api-version={_config.AzureDevopsApiVersion}"); var teamDaysResponse = JsonConvert.DeserializeObject <GetIterationTeamDaysOff>(teamDaysResponseString); foreach (var person in response.Value) { if (person.DaysOff == null) { person.DaysOff = new List <CapacityDateRange>(); } if (teamDaysResponse.DaysOff != null) { person.DaysOff.AddRange(teamDaysResponse.DaysOff); } } var effectiveCurrentDate = DateTime.Today > queryRequest.IterationEndDate ? queryRequest.IterationEndDate : DateTime.Today; var responseModel = new GetCorrectCapacityQueryResponse { MemberCapacities = response.Value.Select(x => GetMemberCapacity(x, queryRequest.IterationStartDate, effectiveCurrentDate)).ToList() }; _logger.LogInformation($"Correct capacities response model: {JsonConvert.SerializeObject(responseModel)}"); return(responseModel); }
public static void Run([TimerTrigger("0 55 8 * * 1-5" /*, RunOnStartup = true*/)] TimerInfo timer, ILogger log, ExecutionContext context) { log.LogInformation($"{nameof(AzureDevopsHelper)} Timer trigger function executed at: {DateTime.UtcNow}"); var config = InitConfig(context); InitAutoMapper(); GetActiveIterationQueryResponse activeIteration = default; foreach (var teamName in config.TeamNames) { var teamActiveIteration = new GetActiveIterationQuery(config, log).RunRequestAsync(new GetActiveIterationQueryRequest { TeamName = config.TeamNames[1] }).Result; if (activeIteration == default) { activeIteration = teamActiveIteration; } else if (activeIteration.Id != teamActiveIteration.Id) { log.LogCritical($"Active Iteration for team {teamName} does not match other team's active iterations. Not yet supported."); return; } } GetCorrectCapacityQueryResponse correctCapacities = default; foreach (var teamName in config.TeamNames) { var teamCorrectCapacities = new GetCorrectCapacityQuery(config, log).RunRequestAsync( new GetCorrectCapacityQueryRequest { IterationId = activeIteration.Id, IterationStartDate = activeIteration.Attributes.StartDate.Value, IterationEndDate = activeIteration.Attributes.FinishDate.Value, TeamName = teamName }).Result; if (correctCapacities == default) { correctCapacities = teamCorrectCapacities; } else { var currentList = correctCapacities.MemberCapacities.ToList(); //Sum capacity for members who are in both teams var duplicateMembers = teamCorrectCapacities.MemberCapacities.Where(x => currentList.Select(y => y.MemberId).Contains(x.MemberId)).ToList(); foreach (var teamMember in duplicateMembers) { currentList.First(x => x.MemberId == teamMember.MemberId).CorrectCapacity += teamMember.CorrectCapacity; } //Add members who aren't yet tracked currentList.AddRange(teamCorrectCapacities.MemberCapacities.Where(x => !currentList.Select(y => y.MemberId).Contains(x.MemberId))); correctCapacities.MemberCapacities = currentList; } } var currentCapacities = new GetCurrentCapacityQuery(config, log).RunRequestAsync( new GetCurrentCapacityQueryRequest { CorrectMemberCapacities = correctCapacities.MemberCapacities, IterationPath = activeIteration.Path }).Result; var FLOAT_COMPARISON_EPSILON = 0.01F; var IncorrectCapacities = currentCapacities.MemberCapacities .Where(x => !config.ExclusionList.Contains(x.Email.ToLower())) .Where(x => !config.AlertLastDayOnly.Contains(x.Email.ToLower()) || DateTime.Now.Date == activeIteration.Attributes.FinishDate?.Date || // Last day can sometimes be saturday or sunday instead of Friday, added a few checks to detect this as a quick hack. Needs to be refactored. DateTime.Now.Date.AddDays(1) == activeIteration.Attributes.FinishDate?.Date || DateTime.Now.Date.AddDays(2) == activeIteration.Attributes.FinishDate?.Date) .Where(x => Math.Abs(x.CurrentCapacity - x.CorrectCapacity) > FLOAT_COMPARISON_EPSILON) .ToList(); new SendInvalidCapacityEmailsCommand(config, log).RunRequestAsync(new SendInvalidCapacityEmailsCommandRequest { InvalidCapacities = IncorrectCapacities }).Wait(); }