private void SyncUpdates <T>(PortfolioContext dest, IEnumerable <T> sourceProjectDetail, Project destProject) where T : IPostgresProject { // Now sync the updates T lastUpdate = default(T); foreach (var sourceUpdate in sourceProjectDetail.OrderBy(u => u.timestamp)) { var destUpdate = destProject.Updates.SingleOrDefault(u => u.SyncId == sourceUpdate.id); if (lastUpdate == null || !lastUpdate.IsDuplicate(sourceUpdate)) { if (destUpdate == null) { destUpdate = new ProjectUpdateItem() { SyncId = sourceUpdate.id, Project = destProject }; destProject.Updates.Add(destUpdate); } mapper.Map(sourceUpdate, destUpdate, opt => { opt.Items[nameof(PortfolioContext)] = dest; }); if (lastUpdate != null && (lastUpdate.update?.Equals(sourceUpdate.update) ?? false)) { destUpdate.Text = null; debugLogDiscardedUpdateText(sourceUpdate); } } else { debugLogDiscardedUpdateText(sourceUpdate); if (destUpdate != null) { dest.ProjectUpdates.Remove(destUpdate); } } lastUpdate = sourceUpdate; } dest.SaveChanges(); // Set the latest update var updates = destProject.Updates.OrderBy(u => u.Timestamp); destProject.FirstUpdate = updates.First(); destProject.LatestUpdate = updates.Last(); dest.SaveChanges(); }
public T Resolve(object source, ProjectUpdateItem destination, string sourceMember, T destMember, ResolutionContext context) { T result = null; if (!string.IsNullOrWhiteSpace(sourceMember)) { if (destMember?.ViewKey == sourceMember && !forceResync) { result = destMember; } else { result = GetOption(destination, sourceMember); } if (result == null) { throw new PortfolioConfigurationException($"Unrecognised {option} key [{sourceMember}]"); } } return(result); }
public async Task <IActionResult> ChangeFailureRateUpdates() { ServiceApiClient serviceApiClient = new ServiceApiClient(Configuration); //Get a list of settings List <AzureDevOpsSettings> azureDevOpsSettings = await serviceApiClient.GetAzureDevOpsSettings(); List <GitHubSettings> githubSettings = await serviceApiClient.GetGitHubSettings(); //Create project items from each Azure DevOps setting and add it to a project list. List <ProjectUpdateItem> projectList = new List <ProjectUpdateItem>(); foreach (AzureDevOpsSettings item in azureDevOpsSettings) { ProjectUpdateItem newItem = new ProjectUpdateItem { ProjectId = item.RowKey, ProjectName = item.Project }; projectList.Add(newItem); } //Create project items from each GitHub setting and add it to a project list. foreach (GitHubSettings item in githubSettings) { ProjectUpdateItem newItem = new ProjectUpdateItem { ProjectId = item.RowKey, ProjectName = item.Repo }; projectList.Add(newItem); } //Create a percentage completed dropdown List <CompletionPercentItem> completionList = new List <CompletionPercentItem> { new CompletionPercentItem { CompletionPercent = 0 }, new CompletionPercentItem { CompletionPercent = 10 }, new CompletionPercentItem { CompletionPercent = 25 }, new CompletionPercentItem { CompletionPercent = 50 }, new CompletionPercentItem { CompletionPercent = 75 }, new CompletionPercentItem { CompletionPercent = 98 }, new CompletionPercentItem { CompletionPercent = 100 } }; //Create the days to process dropdown List <NumberOfDaysItem> numberOfDaysList = new List <NumberOfDaysItem> { new NumberOfDaysItem { NumberOfDays = 1 }, new NumberOfDaysItem { NumberOfDays = 7 }, new NumberOfDaysItem { NumberOfDays = 21 }, new NumberOfDaysItem { NumberOfDays = 30 }, new NumberOfDaysItem { NumberOfDays = 60 }, new NumberOfDaysItem { NumberOfDays = 90 } }; ProjectUpdateViewModel model = new ProjectUpdateViewModel { ProjectList = new SelectList(projectList, "ProjectId", "ProjectName"), CompletionPercentList = new SelectList(completionList, "CompletionPercent", "CompletionPercent"), NumberOfDaysList = new SelectList(numberOfDaysList, "NumberOfDays", "NumberOfDays") }; return(View(model)); }
public async Task UpdateProject(ProjectUpdateModel update, ProjectReservation reservation = null, Action <Portfolio> permissionCallback = null) { try { if (reservation == null) { reservation = await GetProjectReservationAsync(update.project_id); } if (reservation == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } else { if (permissionCallback != null) { permissionCallback(reservation.Portfolio); } var project = reservation?.Project; if (project == null) { project = CreateNewProject(reservation); } // Map the model to the project - map the leads manually because they can require an async AD lookup var context = ServiceContext.PortfolioContext; PortfolioMapper.ProjectMapper.Map(update, project, opt => { opt.Items[nameof(PortfolioContext)] = context; }); await personService.MapPeopleAsync(update, project); // Audit and save if (project.AuditLogs != null) { LogAuditChanges(project); } await context.SaveChangesAsync(); // Get the last update and create a new one if necessary ProjectUpdateItem lastUpdate = project.LatestUpdate; ProjectUpdateItem projectUpdate = lastUpdate; if (projectUpdate == null || projectUpdate.Timestamp.Date != DateTime.Today) { // Create a new update projectUpdate = new ProjectUpdateItem() { Project = project }; if (project.FirstUpdate_Id == null) { project.FirstUpdate = projectUpdate; } } // Map the data to the update and add if not a duplicate PortfolioMapper.ProjectMapper.Map(update, projectUpdate, opt => opt.Items[nameof(PortfolioContext)] = context); if (!projectUpdate.IsDuplicate(lastUpdate)) { project.Updates.Add(projectUpdate); project.LatestUpdate = projectUpdate; project.LatestUpdate.Timestamp = DateTime.Now; // Set the person making the update if (!string.IsNullOrWhiteSpace(ServiceContext.ActiveDirectoryId)) { projectUpdate.Person = await context.People.SingleOrDefaultAsync(p => p.ActiveDirectoryId == ServiceContext.ActiveDirectoryId); } } // Save await context.SaveChangesAsync(); } } catch (AutoMapperMappingException ame) { if (ame.InnerException is PortfolioConfigurationException) { var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { ReasonPhrase = ame.InnerException.Message }; throw new HttpResponseException(resp); } else { throw ame; } } catch (DbEntityValidationException e) { var resp = new HttpResponseMessage(HttpStatusCode.BadRequest); if (e.EntityValidationErrors != null && e.EntityValidationErrors.Count() > 0) { resp.ReasonPhrase = string.Join(", ", e.EntityValidationErrors.SelectMany(err => err.ValidationErrors).Select(ve => ve.ErrorMessage)); } else { resp.ReasonPhrase = e.Message; } throw new HttpResponseException(resp); } }
protected override ProjectOnHoldStatus GetOption(ProjectUpdateItem destination, string viewKey) => destination.Project.Reservation.Portfolio.Configuration.OnHoldStatuses.SingleOrDefault(c => c.ViewKey == viewKey);
protected abstract T GetOption(ProjectUpdateItem destination, string viewKey);
public void NoLeadSummaryTest() { // Configure test data var l1 = new Person() { Id = 1, ActiveDirectoryDisplayName = "Person1" }; var ph1 = new ProjectPhase() { Id = 1, Name = "Phase1", ViewKey = "phase1", Order = 0 }; var ph2 = new ProjectPhase() { Id = 2, Name = "Phase2", ViewKey = "phase2", Order = 1 }; var ph5 = new ProjectPhase() { Id = 5, Name = "Phase5", ViewKey = "phase5", Order = 2 }; PortfolioConfiguration config = new PortfolioConfiguration() { Phases = new List <ProjectPhase>() { ph1, ph2, ph5 }, Labels = new List <PortfolioLabelConfig>() }; ph1.Configuration = config; ph2.Configuration = config; ph5.Configuration = config; var up1 = new ProjectUpdateItem() { Phase = ph1 }; var up2 = new ProjectUpdateItem() { Phase = ph1 }; Portfolio portfolio = new Portfolio() { Configuration = config, Projects = new List <Project>() { new Project() { ProjectReservation_Id = 1, Name = "Project1", Updates = new List <ProjectUpdateItem>() { up1 }, LatestUpdate = up1 }, new Project() { ProjectReservation_Id = 2, Name = "Project2", Updates = new List <ProjectUpdateItem>() { up2 }, LatestUpdate = up2, Lead = l1, Lead_Id = l1.Id } } }; portfolio.Configuration.Portfolio = portfolio; portfolio.Configuration.CompletedPhase = ph5; var summaryType = PortfolioSummaryModel.ByLead; // Initialise mapping configuration PortfolioMapper.Configure(); // Map the test data var result = PortfolioMapper.ConfigMapper.Map <PortfolioSummaryModel>( portfolio, opt => { opt.Items[nameof(PortfolioConfiguration)] = portfolio.Configuration; opt.Items[PortfolioSummaryResolver.SummaryTypeKey] = summaryType; }); // Check result // result // -- Phases // -- Phases[0] // -- ViewKey: phase1 // -- Count: 2 // -- Phases[1] // -- ViewKey: phase2 // -- Count: 0 // -- Summaries // -- Summaries[0] // -- Name: "None set" // -- PhaseProjects // -- Count: 2 // -- PhaseProjects[0] // -- ViewKey: "phase1" // -- Projects // -- Count: 1 // -- Projects[0] // -- Name: "Project1" // -- PhaseProjects[1] // -- ViewKey: "phase2" // -- Projects // -- Count: 0 // -- Summaries[1] // -- Name: "Person1" // -- PhaseProjects // -- PhaseProjects[0] // -- ViewKey: "phase1" // -- Projects // -- Count: 1 // -- Projects[0] // -- Name: "Project2" // -- PhaseProjects[1] // -- ViewKey: "phase2" // -- Projects // -- Count: 0 var phases = result.Phases.ToList(); Assert.AreEqual(2, phases.Count()); Assert.AreEqual("phase1", phases[0].ViewKey); Assert.AreEqual("phase2", phases[1].ViewKey); Assert.AreEqual(2, phases[0].Count); // Projects in phase 1 Assert.AreEqual(0, phases[1].Count); // This is phase 2 (completed phase is hidden) var summaries = result.Summaries.ToList(); // ... counts Assert.AreEqual(2, summaries.Count()); // ... Summary 0 ("None set") should have 1 project in phase1 Assert.AreEqual(ProjectTeamConstants.NotSetName, summaries[0].Name); Assert.AreEqual(2, summaries[0].PhaseProjects.ToList().Count()); Assert.AreEqual("phase1", summaries[0].PhaseProjects.ToList()[0].ViewKey); Assert.AreEqual(1, summaries[0].PhaseProjects.ToList()[0].Projects.Count()); Assert.AreEqual("Project1", summaries[0].PhaseProjects.ToList()[0].Projects.First().Name); Assert.AreEqual("phase2", summaries[0].PhaseProjects.ToList()[1].ViewKey); Assert.AreEqual(0, summaries[0].PhaseProjects.ToList()[1].Projects.Count()); // ... Summary 1 ("Person1") should have 1 project in phase1 Assert.AreEqual("Person1", summaries[1].Name); Assert.AreEqual(2, summaries[1].PhaseProjects.ToList().Count()); Assert.AreEqual("phase1", summaries[1].PhaseProjects.ToList()[0].ViewKey); Assert.AreEqual(1, summaries[1].PhaseProjects.ToList()[0].Projects.Count()); Assert.AreEqual("Project2", summaries[1].PhaseProjects.ToList()[0].Projects.First().Name); Assert.AreEqual("phase2", summaries[1].PhaseProjects.ToList()[1].ViewKey); Assert.AreEqual(0, summaries[1].PhaseProjects.ToList()[1].Projects.Count()); }