public Project CreateNewProject(ProjectReservation reservation)
 {
     reservation.Project = new Project()
     {
         Reservation = reservation,
         Updates     = new List <ProjectUpdateItem>(),
         Portfolios  = new List <Portfolio>()
         {
             reservation.Portfolio
         }
     };
     return(reservation.Project);
 }
        public async Task <ProjectReservation> GetProjectReservationAsync(PortfolioConfiguration config)
        {
            var timestamp = DateTime.Now;
            int year      = timestamp.Year;
            int month     = timestamp.Month;

            var maxIndexQuery = ServiceContext.PortfolioContext.ProjectReservations
                                .Where(r => r.Portfolio_Id == config.Portfolio_Id && r.Year == year && r.Month == month)
                                .Select(r => (int?)r.Index);
            int maxIndex = (await maxIndexQuery.MaxAsync()) ?? 0;

            var reservation = new ProjectReservation()
            {
                Year         = year,
                Month        = month,
                Index        = maxIndex + 1,
                ReservedAt   = timestamp,
                Portfolio_Id = config.Portfolio_Id
            };

            ServiceContext.PortfolioContext.ProjectReservations.Add(reservation);
            return(reservation);
        }
        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);
            }
        }