Exemple #1
0
        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());
        }