/// <summary>
 /// Release properties from project, such as during the deny or cancelled statuses
 /// </summary>
 /// <param name="context"></param>
 /// <param name="project"></param>
 /// <returns></returns>
 public static void ReleaseProjectProperties(this PimsContext context, Entity.Project project)
 {
     project.Properties.ForEach(p =>
     {
         context.Update(p.UpdateProjectNumber(null));
     });
 }
Beispiel #2
0
        /// <summary>
        /// Dispose properties from project, during the disposed workflow status.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="project"></param>
        /// <returns></returns>
        public static void DisposeProjectProperties(this PimsContext context, Entity.Project project)
        {
            var disposed      = context.PropertyClassifications.AsNoTracking().FirstOrDefault(c => c.Name == "Disposed") ?? throw new KeyNotFoundException("Classification 'Disposed' not found.");
            var parentParcels = GetSubdivisionParentParcels(project);

            DisposeSubdivisionParentParcels(context, parentParcels);
            project.Properties.Where(p => !parentParcels.Any(pp => pp.Id == p.Id)).ForEach(p =>
            {
                switch (p.PropertyType)
                {
                case (Entity.PropertyTypes.Land):
                    if (p.Parcel == null)
                    {
                        throw new InvalidOperationException("Unable to update parcel status.");
                    }
                    p.Parcel.ClassificationId = disposed.Id;
                    p.Parcel.AgencyId         = null;
                    p.Parcel.PropertyTypeId   = (int)PropertyTypes.Land; // all subdivisions should be transitioned to parcels after they are disposed.
                    p.Parcel.Parcels.Clear();                            // remove all references to parent parcels.
                    break;

                case (Entity.PropertyTypes.Building):
                    if (p.Building == null)
                    {
                        throw new InvalidOperationException("Unable to update building status.");
                    }
                    p.Building.ClassificationId = disposed.Id;
                    p.Building.AgencyId         = null;
                    break;
                }
                context.Update(p);
            });
        }
Beispiel #3
0
        /// Get a collection of responses that have changed from the original to the updated project.
        /// </summary>
        /// <param name="originalProject"></param>
        /// <param name="updatedProject"></param>
        /// <returns></returns>
        public static IEnumerable <ProjectAgencyResponse> GetResponseChanges(this Entity.Project originalProject, Entity.Project updatedProject)
        {
            if (updatedProject == null)
            {
                throw new ArgumentNullException(nameof(updatedProject));
            }

            var responses = new List <ProjectAgencyResponse>(updatedProject.Responses.Count());

            foreach (var response in updatedProject.Responses)
            {
                var originalResponse = originalProject.Responses.FirstOrDefault(r => r.ProjectId == response.ProjectId && r.AgencyId == response.AgencyId);
                if (originalResponse == null || originalResponse.Response != response.Response)
                {
                    responses.Add(response);
                }
            }

            // Any responses that were deleted should now be ignored.
            foreach (var response in originalProject.Responses)
            {
                // Look for original response in the update project.
                var updatedResponse = updatedProject.Responses.FirstOrDefault(r => r.ProjectId == response.ProjectId && r.AgencyId == response.AgencyId);
                if (updatedResponse == null)
                {
                    response.Response = NotificationResponses.Unsubscribe;
                    responses.Add(response);
                }
            }
            return(responses);
        }
        /// <summary>
        /// Dispose properties from project, during the disposed workflow status.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="project"></param>
        /// <returns></returns>
        public static void DisposeProjectProperties(this PimsContext context, Entity.Project project)
        {
            var disposed = context.PropertyClassifications.Find(4) ?? throw new KeyNotFoundException("Classification 'Disposed' not found.");

            project.Properties.ForEach(p =>
            {
                switch (p.PropertyType)
                {
                case (Entity.PropertyTypes.Land):
                    if (p.Parcel == null)
                    {
                        throw new InvalidOperationException("Unable to update parcel status.");
                    }
                    p.Parcel.ClassificationId = disposed.Id;
                    p.Parcel.AgencyId         = null;
                    break;

                case (Entity.PropertyTypes.Building):
                    if (p.Building == null)
                    {
                        throw new InvalidOperationException("Unable to update building status.");
                    }
                    p.Building.ClassificationId = disposed.Id;
                    p.Building.AgencyId         = null;
                    break;
                }
                context.Update(p);
            });
        }
Beispiel #5
0
 /// <summary>
 /// Find the property for the specified 'pid' in inventory and add it to the project.
 /// Assumption is made that if the parcel is added, then also add all the buildings on the parcel.
 /// </summary>
 /// <param name="project"></param>
 /// <param name="pid"></param>
 /// <returns></returns>
 private Entity.Project AddProperty(Entity.Project project, string pid)
 {
     try
     {
         var pidValue = Int32.Parse(pid.Replace("-", ""));
         var parcel   = _adminService.Parcel.GetByPid(pidValue);
         project.AddProperty(parcel).ForEach(p =>
         {
             p.Project = null;
             p.Parcel  = null; // Need to do this so that it isn't reattached.
         });
         var buildings = parcel.Buildings.Select(b => b.Building).ToArray();
         project.AddProperty(buildings).ForEach(b =>
         {
             b.Project  = null;
             b.Building = null; // Need to do this so that it isn't reattached.
         });
         _logger.LogInformation($"Property '{pid}' added to project '{project.ProjectNumber}'.");
     }
     catch (KeyNotFoundException)
     {
         _logger.LogWarning($"Property '{pid}' not found on project '{project.ProjectNumber}'.");
     }
     catch (InvalidOperationException ex)
     {
         _logger.LogWarning(ex, $"Property '{pid}' not found on project '{project.ProjectNumber}'.");
     }
     return(project);
 }
Beispiel #6
0
        public void ExportProjects_Csv_Query_Success()
        {
            // Arrange
            var helper     = new TestHelper();
            var controller = helper.CreateController <ProjectController>(Permissions.PropertyView);
            var headers    = helper.GetService <Mock <Microsoft.AspNetCore.Http.IHeaderDictionary> >();

            headers.Setup(m => m["Accept"]).Returns(ContentTypes.CONTENT_TYPE_CSV);
            var agency = EntityHelper.CreateAgency(1);

            var project = new Entity.Project()
            {
                Agency = agency
            };
            var projects = new[] { project };

            var service = helper.GetService <Mock <IPimsService> >();
            var mapper  = helper.GetService <IMapper>();
            var page    = new Paged <Entity.Project>(projects);

            service.Setup(m => m.Project.GetPage(It.IsAny <Entity.Models.ProjectFilter>())).Returns(page);

            // Act
            var result = controller.ExportProjects();

            // Assert
            var actionResult = Assert.IsType <ContentResult>(result);
            var actualResult = Assert.IsType <string>(actionResult.Content);

            Assert.Equal(ContentTypes.CONTENT_TYPE_CSV, actionResult.ContentType);
            service.Verify(m => m.Project.GetPage(It.IsAny <Entity.Models.ProjectFilter>()), Times.Once());
        }
Beispiel #7
0
        public void ExportProjects_ExcelX_Query_Success(Uri uri)
        {
            // Arrange
            var helper     = new TestHelper();
            var controller = helper.CreateController <ProjectController>(Permissions.PropertyView, uri);
            var headers    = helper.GetService <Mock <Microsoft.AspNetCore.Http.IHeaderDictionary> >();

            headers.Setup(m => m["Accept"]).Returns(ContentTypes.CONTENT_TYPE_EXCELX);
            var agency = EntityHelper.CreateAgency(1);

            var project = new Entity.Project()
            {
                Agency = agency
            };
            var projects = new[] { project };

            var service = helper.GetService <Mock <IPimsService> >();
            var mapper  = helper.GetService <IMapper>();
            var page    = new Paged <Entity.Project>(projects);

            service.Setup(m => m.Project.GetPage(It.IsAny <Entity.Models.ProjectFilter>())).Returns(page);

            // Act
            var result = controller.ExportProjects();

            // Assert
            var actionResult = Assert.IsType <FileStreamResult>(result);

            Assert.Equal(ContentTypes.CONTENT_TYPE_EXCELX, actionResult.ContentType);
            Assert.NotNull(actionResult.FileDownloadName);
            Assert.True(actionResult.FileStream.Length > 0);
            service.Verify(m => m.Project.GetPage(It.IsAny <Entity.Models.ProjectFilter>()), Times.Once());
        }
Beispiel #8
0
 /// <summary>
 /// A parcel can only be updated or removed if not within an active project or user has admin-properties permission
 /// </summary>
 /// <param name="service"></param>
 /// <param name="project"></param>
 /// <param name="options"></param>
 /// <returns></returns>
 public static void ThrowIfNotAllowedToUpdate(this BaseService service, Entity.Project project, ProjectOptions options)
 {
     if (project != null && !project.IsProjectEditable(service.GetUser(), options))
     {
         throw new NotAuthorizedException("Cannot update or delete an active project.");
     }
 }
Beispiel #9
0
 /// <summary>
 /// Determine if the project is in draft.
 /// </summary>
 /// <param name="project"></param>
 /// <param name="options"></param>
 /// <returns></returns>
 public static bool IsProjectInDraft(this Entity.Project project, ProjectOptions options)
 {
     if (project.Workflow == null)
     {
         throw new ArgumentNullException(nameof(project), "The 'Workflow' cannot be null.");
     }
     return(options.DraftWorkflows.Contains(project.Workflow.Code));
 }
Beispiel #10
0
 /// <summary>
 /// Get the latest project associated to this property, using the workflow sort order.
 /// </summary>
 /// <param name="property"></param>
 /// <returns>The workflow code of the latest workflow associated to this property</returns>
 public static Entity.Project GetLatestProject(this Entity.Property property)
 {
     Entity.Project latestProject = null;
     if (property is Entity.Parcel parcel && parcel.Projects.Select(pp => pp.Project).Any())
     {
         latestProject = parcel.Projects.Select(pp => pp.Project).
                         Aggregate((Entity.Project projectWithLatestWorkflow, Entity.Project current) => current.Workflow?.SortOrder > projectWithLatestWorkflow?.Workflow?.SortOrder && current?.Status?.IsTerminal == false ? current : projectWithLatestWorkflow);
     }
Beispiel #11
0
 /// <summary>
 /// Determine the financial year the project is based on.
 /// Scans properties and gets the most recent evaluation date.
 /// </summary>
 /// <param name="project"></param>
 /// <returns></returns>
 public static DateTime GetProjectFinancialDate(this Entity.Project project) // TODO: This is most likely invalid, but for now will work.
 {
     return(project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land).Select(p => p.Parcel).SelectMany(p => p.Evaluations).Max(p => (DateTime?)p.Date)
            ?? project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Building).Select(p => p.Building).SelectMany(p => p.Evaluations).Max(b => (DateTime?)b.Date)
            ?? project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land).Select(p => p.Parcel).SelectMany(p => p.Fiscals).Max(b => (DateTime?)new DateTime(b.FiscalYear, 1, 1))
            ?? project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Building).Select(p => p.Building).SelectMany(p => p.Fiscals).Max(b => (DateTime?)new DateTime(b.FiscalYear, 1, 1))
            ?? DateTime.UtcNow);
 }
Beispiel #12
0
 /// <summary>
 /// Set the project workflow and status to the specified 'workflowStatus'.
 /// </summary>
 /// <param name="project"></param>
 /// <param name="workflowStatus"></param>
 /// <returns></returns>
 public static Entity.Project SetStatus(this Entity.Project project, Entity.WorkflowProjectStatus workflowStatus)
 {
     project.Workflow   = workflowStatus.Workflow;
     project.WorkflowId = workflowStatus.WorkflowId;
     project.Status     = workflowStatus.Status;
     project.StatusId   = workflowStatus.StatusId;
     return(project);
 }
Beispiel #13
0
 /// <summary>
 /// Transfer Project properties to a new agency with updated classifications
 /// </summary>
 /// <param name="context"></param>
 /// <param name="originalProject"></param>
 /// <param name="project"></param>
 /// <returns></returns>
 public static void TransferProjectProperties(this PimsContext context, Entity.Project originalProject, Entity.Project project)
 {
     originalProject.Properties.ForEach(p =>
     {
         var matchingProperty = project.Properties.First(property => p.Id == property.Id);
         context.Update(p.UpdateProjectProperty(matchingProperty));
     });
 }
Beispiel #14
0
 /// <summary>
 /// Add a tasks to the project.
 /// </summary>
 /// <param name="project"></param>
 /// <param name="tasks"></param>
 /// <returns></returns>
 public static Entity.Project AddTask(this Entity.Project project, params Entity.Task[] tasks)
 {
     tasks.ForEach(t =>
     {
         project.Tasks.Add(new Entity.ProjectTask(project, t));
     });
     return(project);
 }
Beispiel #15
0
 /// <summary>
 /// Add responses to the project.
 /// </summary>
 /// <param name="project"></param>
 /// <param name="responses"></param>
 /// <returns></returns>
 public static Entity.Project AddResponses(this Entity.Project project, params Entity.ProjectAgencyResponse[] responses)
 {
     responses.ForEach(r =>
     {
         project.Responses.Add(r);
     });
     return(project);
 }
Beispiel #16
0
        /// <summary>
        /// Set the project workflow and status to the specified 'workflow' and 'status'.
        /// If the status is not part of the specified workflow it will throw an exception.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="project"></param>
        /// <param name="workflowCode"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        public static PimsContext SetStatus(this PimsContext context, Entity.Project project, string workflowCode, string statusCode)
        {
            var workflow = context.Workflows.First(w => w.Code == workflowCode);
            var status   = workflow.Status.First(s => s.Status.Code == statusCode);

            project.SetStatus(status);

            return(context);
        }
Beispiel #17
0
        /// <summary>
        /// Determine if the project is closed or complete.
        /// </summary>
        /// <param name="project"></param>
        /// <returns></returns>
        public static bool IsProjectClosed(this Entity.Project project)
        {
            if (project.Status == null)
            {
                throw new ArgumentNullException(nameof(project.Status));
            }

            return(project.Status.IsTerminal);
        }
Beispiel #18
0
        /// <summary>
        /// Removes any responses from the original project that have been removed from the updated project.
        /// </summary>
        /// <param name="originalProject"></param>
        /// <param name="updatedProject"></param>
        public static void UpdateResponses(this Entity.Project originalProject, Entity.Project updatedProject)
        {
            var responseIds     = updatedProject.Responses.Select(r => r.AgencyId).ToArray();
            var removeResponses = originalProject.Responses.Where(r => !responseIds.Contains(r.AgencyId)).ToArray();

            foreach (var response in removeResponses)
            {
                originalProject.Responses.Remove(response);
            }
        }
Beispiel #19
0
 private string MajorActivity(Entity.Project project)
 {
     return(project.Status.Code switch
     {
         "DIS" => "Complete",
         "SPL-PM" => "Pre-Marketing",
         "SPL-M" => "On the Market",
         "PSL-CIP" => "Contract in Place",
         _ => project.Status.Name
     });
Beispiel #20
0
        /// <summary>
        /// Add a parcel(s) to the project.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="parcels"></param>
        /// <returns></returns>
        public static IEnumerable <Entity.ProjectProperty> AddProperty(this Entity.Project project, params Entity.Parcel[] parcels)
        {
            var result = new List <Entity.ProjectProperty>();

            foreach (var p in parcels)
            {
                var pp = new Entity.ProjectProperty(project, p);
                project.Properties.Add(pp);
                result.Add(pp);
            }
            return(result);
        }
Beispiel #21
0
        /// <summary>
        /// Add a building(s) to the project.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="buildings"></param>
        /// <returns></returns>
        public static IEnumerable <Entity.ProjectProperty> AddProperty(this Entity.Project project, params Entity.Building[] buildings)
        {
            var result = new List <Entity.ProjectProperty>();

            foreach (var b in buildings)
            {
                var pp = new Entity.ProjectProperty(project, b);
                project.Properties.Add(pp);
                result.Add(pp);
            }
            return(result);
        }
Beispiel #22
0
        /// <summary>
        /// Transfer Project properties to a new agency with updated classifications
        /// </summary>
        /// <param name="context"></param>
        /// <param name="originalProject"></param>
        /// <param name="project"></param>
        /// <returns></returns>
        public static void TransferProjectProperties(this PimsContext context, Entity.Project originalProject, Entity.Project project)
        {
            var parentParcels = originalProject.GetSubdivisionParentParcels();

            context.DisposeSubdivisionParentParcels(parentParcels);
            var propertiesWithNoSubdivisions = originalProject.Properties.Where(p => !parentParcels.Any(pp => p.Parcel?.Id == pp.Id));

            propertiesWithNoSubdivisions.ForEach(p =>
            {
                var matchingProperty = project.Properties.First(property => p.Id == property.Id);
                context.Update(p.UpdateProjectProperty(matchingProperty));
            });
        }
Beispiel #23
0
        /// <summary>
        /// Add a snapshot for the project.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="model"></param>
        /// <param name="metadata"></param>
        private void AddSnapshot(Entity.Project project, Model.ImportProjectModel model, Entity.Models.DisposalProjectSnapshotMetadata metadata)
        {
            var today = model.SnapshotOn ?? DateTime.Today.ToUniversalTime(); // Allows for all imports done on the same day to create the same snapshot time.

            metadata.NetProceeds = model.PriorNetProceeds;                    // Temporarily set it to the prior amount for the snapshot.
            var snapshot = new Entity.ProjectSnapshot(project)
            {
                SnapshotOn = today,
                Metadata   = JsonSerializer.Serialize(metadata, _serializerOptions)
            };

            project.Snapshots.Add(snapshot);
            metadata.NetProceeds = model.NetProceeds; // Set it back to the current value.
        }
Beispiel #24
0
        /// <summary>
        /// Update the project financial values for the specified 'project'.
        /// Note - This requires that the referenced project includes all properties and their evaluations and fiscals.
        /// </summary>
        /// <param name="project"></param>
        public static void UpdateProjectFinancials(this Entity.Project project)
        {
            var date       = project.GetProjectFinancialDate();
            var year       = date.Year;
            var fiscalYear = date.GetFiscalYear(); // TODO: Unclear if this should be 'Reported' or 'Actual', or current year.  Using the most recent fiscal year based on financial data in project.

            // Sum up parcel values for the project year.
            // Sum up building values for the project year.
            project.NetBook    = project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land).SelectMany(p => p.Parcel.Fiscals).Where(e => e.FiscalYear == fiscalYear && e.Key == Entity.FiscalKeys.NetBook).Sum(e => e.Value);
            project.NetBook   += project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Building).SelectMany(p => p.Building.Fiscals).Where(e => e.FiscalYear == fiscalYear && e.Key == Entity.FiscalKeys.NetBook).Sum(e => e.Value);
            project.Estimated  = project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land).SelectMany(p => p.Parcel.Fiscals).Where(e => e.FiscalYear == fiscalYear && e.Key == Entity.FiscalKeys.Estimated).Sum(e => e.Value);
            project.Estimated += project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Building).SelectMany(p => p.Building.Fiscals).Where(e => e.FiscalYear == fiscalYear && e.Key == Entity.FiscalKeys.Estimated).Sum(e => e.Value);
            project.Assessed   = project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land).SelectMany(p => p.Parcel.Evaluations).Where(e => e.Date.Year == year && e.Key == Entity.EvaluationKeys.Assessed).Sum(e => e.Value);
            project.Assessed  += project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Building).SelectMany(p => p.Building.Evaluations).Where(e => e.Date.Year == year && e.Key == Entity.EvaluationKeys.Assessed).Sum(e => e.Value);
        }
Beispiel #25
0
 /// <summary>
 /// Set Project properties' visibility to other agencies
 /// </summary>
 /// <param name="context"></param>
 /// <param name="project"></param>
 /// <param name="visibility"></param>
 public static void SetProjectPropertiesVisiblity(this PimsContext context, Entity.Project project, bool visibility)
 {
     project.Properties.ForEach(p =>
     {
         if (p.BuildingId.HasValue)
         {
             p.Building.IsVisibleToOtherAgencies = visibility;
             context.Buildings.Update(p.Building);
         }
         else if (p.ParcelId.HasValue)
         {
             p.Parcel.IsVisibleToOtherAgencies = visibility;
             context.Parcels.Update(p.Parcel);
         }
     });
 }
Beispiel #26
0
        /// <summary>
        /// Append a new note to the project.
        /// Parse the 'noteType' value, or set it as 'General'.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="noteType"></param>
        /// <param name="note"></param>
        private void AddNote(Entity.Project project, string noteType, string note)
        {
            if (!String.IsNullOrWhiteSpace(note))
            {
                if (!Enum.TryParse(noteType, true, out Entity.NoteTypes type))
                {
                    type = noteType switch
                    {
                        "Property" => Entity.NoteTypes.Public,
                        "PID" => Entity.NoteTypes.Public,
                        "LandLegalDescription" => Entity.NoteTypes.Public,
                        "Surplus Dec / Readiness Checklist" => Entity.NoteTypes.Public,
                        "TBL - CBA" => Entity.NoteTypes.Public,
                        "Enhanced Referral Comments" => Entity.NoteTypes.Private,
                        "Business Case Comments" => Entity.NoteTypes.Private,
                        "Business Case Submitted" => Entity.NoteTypes.Private,
                        "Clearance Letter Issued" => Entity.NoteTypes.Private,
                        "Interest from Enhanced Referral" => Entity.NoteTypes.AgencyInterest,
                        "Appraisal Date" => Entity.NoteTypes.Appraisal,
                        "Assessed & Appraised Comments" => Entity.NoteTypes.Appraisal,
                        "Weekly Review" => Entity.NoteTypes.Reporting,
                        _ => Entity.NoteTypes.General
                    };
                }

                var projectNote = project.Notes.FirstOrDefault(n => n.NoteType == type);
                if (projectNote == null)
                {
                    project.Notes.Add(new Entity.ProjectNote(project, type, note));
                }
                else
                {
                    if (!String.IsNullOrWhiteSpace(projectNote.Note))
                    {
                        projectNote.Note += $"{Environment.NewLine}{Environment.NewLine}{noteType}{Environment.NewLine}{note}";
                    }
                    else
                    {
                        projectNote.Note = note;
                    }
                }
            }
        }
Beispiel #27
0
        /// Get a collection of responses that have changed from the original to the updated project.
        /// </summary>
        /// <param name="originalProject"></param>
        /// <param name="updatedProject"></param>
        /// <returns></returns>
        public static IEnumerable <ProjectAgencyResponse> GetResponseChanges(this Entity.Project originalProject, Entity.Project updatedProject)
        {
            if (updatedProject == null)
            {
                throw new ArgumentNullException(nameof(updatedProject));
            }

            var responses = new List <ProjectAgencyResponse>(updatedProject.Responses.Count());

            foreach (var response in updatedProject.Responses)
            {
                var originalResponse = originalProject.Responses.FirstOrDefault(r => r.ProjectId == response.ProjectId && r.AgencyId == response.AgencyId);
                if (originalResponse == null || originalResponse.Response != response.Response)
                {
                    responses.Add(response);
                }
            }
            return(responses);
        }
Beispiel #28
0
        /// <summary>
        /// Create a new instance of a Project.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="agency"></param>
        /// <param name="tierLevel"></param>
        /// <param name="workflowStatus"></param>
        /// <returns></returns>
        public static Entity.Project CreateProject(int id, Entity.Agency agency = null, Entity.TierLevel tierLevel = null, Entity.WorkflowProjectStatus workflowStatus = null, Entity.ProjectRisk risk = null)
        {
            agency ??= EntityHelper.CreateAgency(id);
            tierLevel ??= EntityHelper.CreateTierLevel(id, "tierLevel");
            risk ??= EntityHelper.CreateProjectRisk(id, "risk", "risk", 1);
            var status   = workflowStatus?.Status ?? EntityHelper.CreateProjectStatus("Draft", "DR");
            var workflow = workflowStatus?.Workflow ?? EntityHelper.CreateWorkflow(id, "Submit", "SUBMIT-DISPOSAL", new[] { status });

            var user    = CreateUser(Guid.NewGuid(), "project tester", "asasa", "asasa", null, agency);
            var project = new Entity.Project($"SPP-{id:00000}", $"test-{id}", tierLevel)
            {
                Id = id,
                ReportedFiscalYear = DateTime.UtcNow.GetFiscalYear(),
                ActualFiscalYear   = DateTime.UtcNow.GetFiscalYear(),
                Risk        = risk,
                RiskId      = risk.Id,
                Agency      = agency,
                AgencyId    = agency.Id,
                Workflow    = workflow,
                WorkflowId  = workflow?.Id,
                Status      = status,
                StatusId    = status.Id,
                Description = $"description-{id}",
                CreatedBy   = user,
                CreatedById = user.Id,
                CreatedOn   = DateTime.UtcNow,
                UpdatedById = user.Id,
                UpdatedBy   = user,
                UpdatedOn   = DateTime.UtcNow,
                Metadata    = "{\"offerAmount\": 123}",
                RowVersion  = new byte[] { 12, 13, 14 }
            };

            project.AddOrUpdateNote(Entity.NoteTypes.Public, $"publicNote-{id}");
            project.AddOrUpdateNote(Entity.NoteTypes.Private, $"privateNote-{id}");
            project.AddOrUpdateNote(Entity.NoteTypes.Appraisal, $"appraisedNote-{id}");
            return(project);
        }
Beispiel #29
0
        /// <summary>
        /// Copy the 'model' project properties into existing projects, or add new projects to PIMS.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="model"></param>
        /// <param name="stopOnError"></param>
        /// <param name="defaults"></param>
        /// <returns></returns>
        private Entity.Project Merge(Entity.Project project, Model.ImportProjectModel model, bool stopOnError = true, string[] defaults = null)
        {
            try
            {
                // Use defaults if required
                if (defaults?.Any() ?? false)
                {
                    var props = typeof(Model.ImportProjectModel).GetCachedProperties();
                    foreach (var kv in defaults)
                    {
                        var keyValue = kv.Trim().Split("=");

                        if (keyValue.Length < 2)
                        {
                            throw new ArgumentException($"Argument '{kv}' is not valid.");
                        }

                        var prop       = props.FirstOrDefault(p => String.Compare(p.Name, keyValue[0], true) == 0);
                        var modelValue = prop?.GetValue(model);
                        if (prop != null && modelValue == null || modelValue.Equals(prop.PropertyType.GetDefault()))
                        {
                            var value = Convert.ChangeType(keyValue[1], prop.PropertyType);
                            prop.SetValue(model, value);
                        }
                    }
                }

                _logger.LogDebug($"Importing Project '{model.ProjectNumber}', agency:'{model.Agency}', workflow:'{model.Workflow}', status:'{model.Status}'");

                project ??= new Entity.Project();

                project.ProjectNumber      = model.ProjectNumber;
                project.Name               = model.Description;
                project.Description        = model.Description;
                project.Manager            = model.Manager;
                project.ActualFiscalYear   = model.ActualFiscalYear;
                project.ReportedFiscalYear = model.ReportedFiscalYear;

                project.Agency      = GetAgency(model.Agency);
                project.AgencyId    = project.Agency.Id;
                project.Workflow    = GetWorkflow(model.Workflow);
                project.WorkflowId  = project.Workflow.Id;
                project.Status      = GetStatus(model.Status);
                project.StatusId    = project.Status.Id;
                project.TierLevel   = GetTier(model.Estimated, project.Properties.Count()); // TODO: Need to import or link project properties.
                project.TierLevelId = project.TierLevel.Id;
                project.Risk        = GetRisk(model.Risk);
                project.RiskId      = project.Risk.Id;

                project.OcgFinancialStatement = model.OcgFinancialStatement;
                project.NetBook              = model.NetBook;
                project.Estimated            = model.Estimated;
                project.ProgramCost          = model.ProgramCost;
                project.SalesCost            = model.SalesCost;
                project.InterestComponent    = model.InterestComponent;
                project.NetProceeds          = model.NetProceeds;
                project.GainLoss             = model.GainLoss;
                project.SaleWithLeaseInPlace = model.SaleWithLeaseInPlace;

                if (model.PriorNetProceeds.HasValue)
                {
                    project.Snapshots.Add(new Entity.ProjectSnapshot(project)
                    {
                        NetProceeds = model.PriorNetProceeds.Value
                    });
                }

                project.MarketedOn  = model.MarketedOn;
                project.CompletedOn = model.CompletedOn;

                project.PrivateNote = model.PrivateNote;

                // The data doesn't provide the purchasing agency information so the response will be the current owning agency.
                if (model.AgencyResponseDate.HasValue)
                {
                    var response = project.Responses.FirstOrDefault(r => r.AgencyId == project.AgencyId);
                    if (response == null)
                    {
                        project.Responses.Add(new Entity.ProjectAgencyResponse(project, project.Agency, Entity.NotificationResponses.Watch, model.AgencyResponseDate));
                    }
                    else
                    {
                        response.Response   = Entity.NotificationResponses.Watch;
                        response.ReceivedOn = model.AgencyResponseDate ?? response.ReceivedOn;
                    }
                }

                if (!String.IsNullOrWhiteSpace(model.FinancialNote))
                {
                    var financialNote = project.Notes.FirstOrDefault(n => n.NoteType == Entity.NoteTypes.Financial);
                    if (financialNote == null)
                    {
                        project.Notes.Add(new Entity.ProjectNote(project, Entity.NoteTypes.Financial, model.FinancialNote));
                    }
                    else
                    {
                        financialNote.Note = model.FinancialNote;
                    }
                }

                // Add tasks if they haven't been added already.
                if (!project.Tasks.Any())
                {
                    // Assumption we'll need to add all tasks from Submit to SPL.
                    var tasks = _service.Task.GetForWorkflow("SUBMIT-DISPOSAL");
                    tasks = tasks.Concat(_service.Task.GetForWorkflow("ASSESS-DISPOSAL"));
                    tasks = tasks.Concat(_service.Task.GetForWorkflow("ERP"));
                    tasks = tasks.Concat(_service.Task.GetForWorkflow("SPL"));
                    project.AddTask(tasks.DistinctBy(t => t.Id).ToArray());
                    project.Tasks.ForEach(t =>
                    {
                        t.IsCompleted = !t.Task.IsOptional;
                    });
                }

                _logger.LogDebug($"Parsed project '{project.ProjectNumber}' - '{project.Status.Code}'", project);

                return(project);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Failed to parse this project while importing '{model.ProjectNumber}' - {ex.Message}");
                if (stopOnError)
                {
                    throw;
                }
                return(null);
            }
        }