Ejemplo n.º 1
0
        public void Register(TypeAdapterConfig config)
        {
            config.NewConfig <Entity.ProjectSnapshot, Model.ProjectSnapshotModel>()
            .Map(dest => dest.Id, src => src.Id)
            .Map(dest => dest.ProjectId, src => src.ProjectId)
            .Map(dest => dest.Project, src => src.Project)
            .Map(dest => dest.SnapshotOn, src => src.SnapshotOn)
            .Map(dest => dest.NetBook, src => src.NetBook)
            .Map(dest => dest.Market, src => src.Market)
            .Map(dest => dest.Assessed, src => src.Assessed)
            .Map(dest => dest.Appraised, src => src.Appraised)
            .AfterMapping((src, dest) =>
            {
                var metadata               = JsonSerializer.Deserialize <Entity.Models.DisposalProjectSnapshotMetadata>(src.Metadata ?? "{}", _serializerOptions);
                dest.SalesCost             = metadata.SalesCost;
                dest.NetProceeds           = metadata.NetProceeds;
                dest.BaselineIntegrity     = metadata.BaselineIntegrity;
                dest.ProgramCost           = metadata.ProgramCost;
                dest.GainLoss              = metadata.GainLoss;
                dest.OcgFinancialStatement = metadata.OcgFinancialStatement;
                dest.SaleWithLeaseInPlace  = metadata.SaleWithLeaseInPlace;
                dest.InterestComponent     = metadata.InterestComponent;
            })
            .Inherits <Entity.BaseEntity, Api.Models.BaseModel>();

            config.NewConfig <Model.ProjectSnapshotModel, Entity.ProjectSnapshot>()
            .Map(dest => dest.Id, src => src.Id)
            .Map(dest => dest.ProjectId, src => src.ProjectId)
            .Map(dest => dest.NetBook, src => src.NetBook)
            .Map(dest => dest.Market, src => src.Market)
            .Map(dest => dest.Assessed, src => src.Assessed)
            .Map(dest => dest.Appraised, src => src.Appraised)
            .AfterMapping((src, dest) =>
            {
                var metadata = new Entity.Models.DisposalProjectSnapshotMetadata()
                {
                    SalesCost             = src.SalesCost,
                    NetProceeds           = src.NetProceeds,
                    BaselineIntegrity     = src.BaselineIntegrity,
                    ProgramCost           = src.ProgramCost,
                    GainLoss              = src.GainLoss,
                    OcgFinancialStatement = src.OcgFinancialStatement,
                    SaleWithLeaseInPlace  = src.SaleWithLeaseInPlace,
                    InterestComponent     = src.InterestComponent
                };

                dest.Metadata = JsonSerializer.Serialize(metadata, _serializerOptions);
            })
            .Inherits <Api.Models.BaseModel, Entity.BaseEntity>();
        }
Ejemplo n.º 2
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.
        }
Ejemplo n.º 3
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>
        /// <returns></returns>
        private Entity.Project Merge(Entity.Project project, Model.ImportProjectModel model)
        {
            var status = GetStatus(model.Status);

            // Default to the last workflow this status is associated with.
            // This isn't ideal and could end up with projects associated with an incorrect workflow.
            // Without better data from SIS it isn't entirely possible to determine the correct workflow automatically.
            var workflow = !String.IsNullOrWhiteSpace(model.Workflow) ? GetWorkflow(model.Workflow) : model.Activity switch
            {
                "Completed Deal" => GetWorkflow("SPL"),
                "Contract in Place" => GetWorkflow("SPL"),
                "On Market" => GetWorkflow("SPL"),
                "Pre-Market" => GetWorkflow("SPL"),
                _ => _adminService.Workflow.GetForStatus(model.Status).OrderBy(w => w.SortOrder).Last()
            };

            project ??= new Entity.Project();

            project.ProjectNumber      = String.IsNullOrWhiteSpace(model.ProjectNumber) ? $"TEMP-{DateTime.UtcNow.Ticks:00000}" : model.ProjectNumber;
            project.Name               = model.Description.Truncate(100);
            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   = workflow;
            project.WorkflowId = workflow.Id;
            project.Status     = status;
            project.StatusId   = status.Id;

            // Extract properties from PID note.
            var pidNote = model.Notes?.FirstOrDefault(n => n.Key == "PID").Value;
            var pids    = Regex.Matches(pidNote ?? "", "[0-9]{3}-[0-9]{3}-[0-9]{3}").Select(m => m.Value).NotNull().Distinct();

            if (!String.IsNullOrWhiteSpace(pidNote))
            {
                // Need to load any properties currently linked to this project.
                if (project.Id > 0)
                {
                    var existingProject = _service.Project.Get(project.ProjectNumber);

                    pids.ForEach(pid =>
                    {
                        // If the parcel has not already been added, add it to the project.
                        var addProperty = true;
                        foreach (var property in existingProject.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land))
                        {
                            var parcel = _service.Parcel.Get(property.ParcelId.Value);
                            if (parcel.ParcelIdentity == pid)
                            {
                                addProperty = false;
                                break;
                            }
                        }
                        if (addProperty)
                        {
                            AddProperty(project, pid);
                        }
                    });
                }
                else
                {
                    pids.ForEach(pid => AddProperty(project, pid));
                }
            }

            project.TierLevel   = GetTier(model.Market, pids.Any() ? pids.Count() : project.Properties.Count()); // Most projects have no properties linked.
            project.TierLevelId = project.TierLevel.Id;
            project.Risk        = GetRisk(model.Risk);
            project.RiskId      = project.Risk.Id;

            // If there are properties linked, load them into context.
            decimal assessed = 0;

            if (project.Properties.Any())
            {
                project.Properties.Where(p => p.PropertyType == Entity.PropertyTypes.Land).ForEach(p =>
                {
                    var property = _service.Parcel.Get(p.ParcelId.Value);
                    assessed    += property.Evaluations.Where(e => e.Key == Entity.EvaluationKeys.Assessed).OrderByDescending(e => e.Date).FirstOrDefault()?.Value ?? 0;
                });
            }

            project.Assessed  = model.Assessed ?? assessed;
            project.NetBook   = model.NetBook;
            project.Market    = model.Market;
            project.Appraised = model.Appraised;

            project.SubmittedOn = new DateTime(model.ReportedFiscalYear - 1, 1, 1); // Don't have a source for this information.
            project.ApprovedOn  = project.SubmittedOn;                              // Don't have a source for this information.
            project.CompletedOn = model.CompletedOn;

            var metadata = new Entity.Models.DisposalProjectSnapshotMetadata
            {
                InitialNotificationSentOn   = null,                          // Don't have a source for this information.
                ThirtyDayNotificationSentOn = null,                          // Don't have a source for this information.
                SixtyDayNotificationSentOn  = null,                          // Don't have a source for this information.
                NinetyDayNotificationSentOn = null,                          // Don't have a source for this information.
                OnHoldNotificationSentOn    = null,                          // Don't have a source for this information.
                InterestedReceivedOn        = model.InterestedReceivedOn,
                TransferredWithinGreOn      = null,                          // Don't have a source for this information.
                ClearanceNotificationSentOn = null,                          // Don't have a source for this information.
                RequestForSplReceivedOn     = model.RequestForSplReceivedOn, // Don't have a source for this information.
                ApprovedForSplOn            = model.ApprovedForSplOn,
                MarketedOn            = model.MarketedOn,
                Purchaser             = model.Purchaser,
                OcgFinancialStatement = model.OcgFinancialStatement,
                AppraisedBy           = model.AppraisedBy,
                ProgramCost           = model.ProgramCost,
                SalesCost             = model.SalesCost,
                InterestComponent     = model.InterestComponent,
                NetProceeds           = model.NetProceeds,
                GainLoss             = model.GainLoss,
                SaleWithLeaseInPlace = model.SaleWithLeaseInPlace,
                DisposedOn           = model.DisposedOn ?? (project.Status.Code == "DIS" ? model.CompletedOn : null),
                OfferAmount          = project.Status.Code == "DIS" ? model.Market : (decimal?)null, // This value would only be accurate if the property is disposed.
                OfferAcceptedOn      = null                                                          // Don't have a source for this information.
            };

            // A prior net proceeds was provided, which means a prior snapshot needs to be generated.
            // If the project already exists, don't add prior snapshots.
            if (model.PriorNetProceeds.HasValue && project.Id == 0)
            {
                AddSnapshot(project, model, metadata);
            }

            project.Metadata = JsonSerializer.Serialize(metadata, _serializerOptions);

            // The data doesn't provide the purchasing agency information so the response will be the current owning agency.
            if (model.InterestedReceivedOn.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.InterestedReceivedOn));
                }
                else
                {
                    response.Response   = Entity.NotificationResponses.Watch;
                    response.ReceivedOn = model.InterestedReceivedOn ?? response.ReceivedOn;
                }
            }

            foreach (var note in model.Notes)
            {
                AddNote(project, note.Key, note.Value);
            }

            // 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"));
                var distinctTasks = tasks.DistinctBy(t => t.Id).ToArray();
                project.AddTask(distinctTasks);
                project.Tasks.ForEach(t =>
                {
                    t.IsCompleted = !t.Task.IsOptional; // Complete all required steps.
                    t.Task        = null;
                });

                var erpTasks = _service.Task.GetForWorkflow("ERP");
                var splTasks = erpTasks.Concat(_service.Task.GetForWorkflow("SPL"));
                distinctTasks = splTasks.Where(t => !distinctTasks.Any(dt => dt.Id == t.Id)).DistinctBy(t => t.Id).ToArray();
                project.AddTask(distinctTasks);
                project.Tasks.ForEach(t =>
                {
                    t.IsCompleted = false;
                    t.Task        = null;
                });
            }

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

            return(project);
        }