private static void CalculatePlotTimesNotStarted(AsyncDashboardNotStartedViewModel.DatesSectionViewModel datesTab) { var plotTimes = new List<AsyncDashboardNotStartedViewModel.DatesSectionViewModel.PlotTime>(); var dtCurrent = DateTime.Now; // 0. Start time if (datesTab.StartDate.HasValue) plotTimes.Add(new AsyncDashboardNotStartedViewModel.DatesSectionViewModel.PlotTime("Start Date", datesTab.StartDate.Value)); // 1. Current time plotTimes.Add(new AsyncDashboardNotStartedViewModel.DatesSectionViewModel.PlotTime("Now", dtCurrent)); if (datesTab.StartDate.HasValue) { datesTab.MinimumTime = TimeUtils.Min(dtCurrent, datesTab.StartDate.Value); } // 2. Code freeze time var codeFreeze = datesTab.CodeFreeze; if (codeFreeze.HasValue) plotTimes.Add(new AsyncDashboardNotStartedViewModel.DatesSectionViewModel.PlotTime("Code Freeze", codeFreeze.Value)); datesTab.MinimumTime = (datesTab.StartDate.HasValue ? TimeUtils.Min(dtCurrent, datesTab.StartDate.Value) : (codeFreeze.HasValue ? TimeUtils.Min(dtCurrent, codeFreeze.Value) : dtCurrent)).AddDays(-7); // 3. Release date if (datesTab.Rollout != null) { plotTimes.Add(new AsyncDashboardNotStartedViewModel.DatesSectionViewModel.PlotTime("Release", datesTab.Rollout.Value)); datesTab.MaximumTime = TimeUtils.Max(dtCurrent, datesTab.Rollout.Value).AddDays(7); datesTab.PlotTimes = plotTimes.OrderBy(plotTime => plotTime.DateTime).ToArray(); } }
public ActionResult AsyncDashboardNotStarted(int projectId, int milestoneId, int? subProjectParentCaseId = null) { var today = DateTime.Today; var model = new AsyncDashboardNotStartedViewModel(); model.Setup(projectId, milestoneId, subProjectParentCaseId); string cacheKey = MsCacheKey.GenCaseSetKey(projectId, milestoneId, subProjectParentCaseId); model.MsCache.CreatedAt = MsCache.GetObjectExpirationTime(cacheKey); UpdateViewBagForProjectLayout(model); IList<Case> cases = new List<Case>(); foreach (var casesWithMilestone in model.CaseSet.Cases.Where(casesWithMilestone => casesWithMilestone.IndexFixFor == milestoneId)) { cases.Add(casesWithMilestone); } model.CasesSection.Total = cases.Count(); model.CasesSection.Active = cases.Count(CaseUtils.IsActive); model.CasesSection.Resolved = cases.Count(CaseUtils.IsResolved); model.CasesSection.Verified = cases.Count(CaseUtils.IsResolvedVerified); model.CasesSection.Closed = cases.Count(CaseUtils.IsClosed); model.TimeSection.TotalEstimated = cases.Sum(@case => @case.HoursCurrentEstimate.GetValueOrDefault(0)); model.TimeSection.Elapsed = cases.Sum(@case => @case.HoursElapsed.GetValueOrDefault(0)); model.TimeSection.ActiveEstimated = cases.Where(CaseUtils.IsActive).Sum(@case => @case.HoursCurrentEstimate.GetValueOrDefault(0)); model.TimeSection.ActiveRemaining = cases.Where(CaseUtils.IsActive).Sum(@case => Math.Max( 0, @case.HoursCurrentEstimate.GetValueOrDefault(0) - @case.HoursElapsed.GetValueOrDefault(0))); model.EstimatesSection.WithEstimates = cases.Where(CaseUtils.IsActive).Count(@case => @case.HoursCurrentEstimate.GetValueOrDefault(0) > 0); model.EstimatesSection.WithoutEstimates = cases.Count(CaseUtils.IsActive) - model.EstimatesSection.WithEstimates; //at this point model.EstimatesSection.WithoutEstimates can be negative. //it is possible when cases which has subcases (IndexBugChildren.Count>0) are estimated too if (model.EstimatesSection.WithoutEstimates < 0) model.EstimatesSection.WithoutEstimates = 0; model.EstimatesSection.GoingOverEstimate = cases.Where(CaseUtils.IsActive).Count( @case => @case.HoursElapsed.GetValueOrDefault(0) > @case.HoursCurrentEstimate.GetValueOrDefault(0)); model.AccuracySection.EstimatedTime = cases.Where(@case => CaseUtils.IsResolved(@case) || CaseUtils.IsClosed(@case)).Sum(@case => @case.HoursCurrentEstimate.GetValueOrDefault(0)); model.AccuracySection.ActualTime = cases.Where(@case => CaseUtils.IsResolved(@case) || CaseUtils.IsClosed(@case)).Sum(@case => @case.HoursElapsed.GetValueOrDefault(0)); Case projectParentCase = null; if (subProjectParentCaseId.HasValue) { var client = FogBugzGateway.GetClientForParallel(); projectParentCase = client.GetCase(subProjectParentCaseId.Value); } foreach (var casesWithMilestone in model.CaseSet.Cases.Where(casesWithMilestone => casesWithMilestone.IndexFixFor == milestoneId)) { cases.Add(casesWithMilestone); } var fbSchedule = FogBugzGateway.GetFbSchedule(); if (model.CaseSet.Milestone != null) { model.DatesSection.StartDate = model.CaseSet.Milestone.DateStart; if (model.DatesSection.StartDate.HasValue) { model.DatesSection.StartDateDaysRemaining = DateUtils.Difference(today, model.DatesSection.StartDate.Value); } model.DatesSection.CodeFreeze = (projectParentCase != null && projectParentCase.DateDue != null) ? projectParentCase.DateDue : MilestoneUtils.CodeFreezeCalculate(projectId, model.Milestone, model.SubProjectParentCaseId, model.CaseSet.Milestone.Name, CodeFreezeSubstringRegex); if (model.DatesSection.CodeFreeze.HasValue) { model.DatesSection.CodeFreezeDaysRemaining = DateUtils.Difference(today, model.DatesSection.CodeFreeze.Value); model.DatesSection.CodeFreezeHolidaysBefore = fbSchedule.GetSiteScheduledDays(today, model.DatesSection.CodeFreeze.Value).TimeOffRanges; } model.DatesSection.Rollout = projectParentCase != null ? (model.CaseSet.Milestone.Name.Contains("CF") ? DateUtils.GetCodeFreezeFromName(model.CaseSet.Milestone.Name, CodeFreezeSubstringRegex) : null) : model.CaseSet.Milestone.DateRelease; if (model.DatesSection.Rollout.HasValue) { model.DatesSection.RolloutDaysRemaining = DateUtils.Difference(today, model.DatesSection.Rollout.Value); model.DatesSection.RolloutHolidaysBefore = fbSchedule.GetSiteScheduledDays(today, model.DatesSection.Rollout.Value).TimeOffRanges; } CalculatePlotTimesNotStarted(model.DatesSection); model.DatesSection.IsActiveProject = today >= model.DatesSection.StartDate && today <= model.DatesSection.Rollout; } var persons = FogBugzGateway.GetPersons(); var isLoadedByAdmin = FogBugzGateway.GetIsScheduleLoadedByAdmin(); var projectStatusCalculator = new ProjectStatusCalculator(model.CaseSet, persons.ToList(), isLoadedByAdmin, fbSchedule); model.ProjectStatus = projectStatusCalculator.GetProjectStatus(); return PartialView("_AsyncDashboardNotStarted", model); }