/// <summary>
 /// Reads the JSON representation of the object.
 /// </summary>
 /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
 /// <param name="objectType">Type of the object.</param>
 /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
 /// <param name="serializer">The calling serializer.</param>
 /// <returns>The object value.</returns>
 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 {
     if (reader.TokenType == JsonToken.Null)
     {
         return(null);
     }
     else
     {
         if (reader.TokenType == JsonToken.Integer)
         {
             try
             {
                 var v = OpportunityStateModel.FromValue(Convert.ToInt32(reader.Value));
                 return(v);
             }
             catch (Exception ex)
             {
                 //throw JsonSerializationException(reader, "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex);
                 throw new JsonSerializationException($"Error parsing version string: {ex.Message}");
             }
         }
         else
         {
             //throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
             throw new JsonSerializationException($"Unexpected token or value when parsing version. Token: {reader.TokenType}, Value: {reader.Value}");
         }
     }
 }
        public async Task <IActionResult> CreateOpportunityAsync(string @event, [FromBody] JObject data)
        {
            if (string.IsNullOrWhiteSpace(@event))
            {
                return(BadRequest($"{nameof(@event)} is required"));
            }
            else if ([email protected]("create", StringComparison.InvariantCultureIgnoreCase))
            {
                return(BadRequest($"{@event} is not supported"));
            }
            else if (data["InputParameters"] == null)
            {
                return(BadRequest($"Payload is malformed"));
            }

            var opportunityMapping = dynamicsConfiguration.OpportunityMapping;

            try
            {
                var jopp = data["InputParameters"].First()["value"];

                if (!jopp["LogicalName"].ToString().Equals(opportunityMapping.EntityName, StringComparison.OrdinalIgnoreCase))
                {
                    _logger.LogError($"DYNAMICS INTEGRATION ENGINE: Incorrect entity type recieved from opportunity creation. Expected ${opportunityMapping.EntityName}, got {jopp["LogicalName"].ToString()}.");
                    return(BadRequest());
                }

                var opportunityId = jopp["Id"].ToString();

                jopp = jopp["Attributes"];
                var attributes = jopp.ToDictionary(p => p["key"], v => v["value"]);

                var opportunityName = GetAttribute(attributes, opportunityMapping.NameProperty)?.ToString();
                var creator         = dynamicsLinkService.GetUserData(data["InitiatingUserId"].ToString());
                var creatorRole     = proposalManagerConfiguration.CreatorRole;

                //Determine customer name
                string customerDisplayName = string.Empty;
                var    customer            = GetAttribute(attributes, "customerid");

                if (customer != null)
                {
                    if (customer["LogicalName"].ToString() == "account")
                    {
                        customerDisplayName = dynamicsLinkService.GetAccountName(customer["Id"].ToString());
                    }
                    else if (customer["LogicalName"].ToString() == "contact")
                    {
                        customerDisplayName = dynamicsLinkService.GetContactName(customer["Id"].ToString());
                    }
                }

                var opp = new OpportunityViewModel
                {
                    Reference        = opportunityId,
                    DisplayName      = opportunityName,
                    OpportunityState = OpportunityStateModel.FromValue(opportunityMapping.MapStatusCode((int)GetAttribute(attributes, "statuscode"))),
                    Customer         = new CustomerModel
                    {
                        DisplayName = customerDisplayName
                    },

                    TeamMembers = new TeamMemberModel[]
                    {
                        new TeamMemberModel
                        {
                            DisplayName       = creator.DisplayName,
                            Id                = creator.Id,
                            Mail              = creator.Email,
                            UserPrincipalName = creator.Email,
                            RoleName          = creatorRole.DisplayName,
                            RoleId            = creatorRole.Id,
                            TeamsMembership   = new TeamsMembershipModel()
                            {
                                Name  = "Member",
                                Value = 1
                            }
                        }
                    },
                    Checklists = Array.Empty <ChecklistModel>()
                };

                var proposalManagerClient = await proposalManagerClientFactory.GetProposalManagerClientAsync();

                var metaDataResult = await proposalManagerClient.GetAsync("/api/MetaData");

                if (!metaDataResult.IsSuccessStatusCode)
                {
                    _logger.LogError("DYNAMICS INTEGRATION ENGINE: Proposal Manager did not return a success status code on metadata request.");
                    return(BadRequest());
                }
                var metadataList = await metaDataResult.Content.ReadAsAsync <List <MetaDataModel> >();

                opp.MetaDataFields = new List <OpportunityMetaDataFields>();

                foreach (var metadata in metadataList)
                {
                    var mappingName = opportunityMapping.MetadataFields.FirstOrDefault(x => x.To == metadata.DisplayName);

                    if (mappingName != null)
                    {
                        opp.MetaDataFields.Add(new OpportunityMetaDataFields
                        {
                            DisplayName = metadata.DisplayName,
                            Values      = GetAttribute(attributes, mappingName.From, metadata.FieldType),
                            FieldType   = metadata.FieldType,
                            Screen      = metadata.Screen
                        });
                    }
                }

                var userProfileResult = await proposalManagerClient.GetAsync($"/api/UserProfile?upn={creator.Email}");

                if (!userProfileResult.IsSuccessStatusCode)
                {
                    _logger.LogError("DYNAMICS INTEGRATION ENGINE: Proposal Manager did not return a success status code on user query request.");
                    return(BadRequest());
                }

                var userProfile = JsonConvert.DeserializeObject <UserProfileViewModel>(await userProfileResult.Content.ReadAsStringAsync());
                if (!userProfile.UserRoles.Any(ur => ur.AdGroupName == creatorRole.AdGroupName))
                {
                    return(BadRequest($"{creator.Email} is not a member of role {creatorRole.AdGroupName}."));
                }

                var remoteEndpoint = $"/api/Opportunity";
                var result         = await proposalManagerClient.PostAsync(remoteEndpoint, new StringContent(JsonConvert.SerializeObject(opp), Encoding.UTF8, "application/json"));

                if (result.IsSuccessStatusCode)
                {
                    await dynamicsLinkService.CreateTemporaryLocationForOpportunityAsync(opportunityId, opportunityName);

                    return(Ok());
                }
                else
                {
                    _logger.LogError("DYNAMICS INTEGRATION ENGINE: Proposal Manager did not return a success status code.");
                    return(BadRequest());
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                _logger.LogError(ex.StackTrace);
                return(BadRequest());
            }
        }
示例#3
0
        public async Task <OpportunityViewModel> OpportunityToViewModelAsync(Opportunity entity, string requestId = "")
        {
            var oppId = entity.Id;

            try
            {
                //var entityDto = TinyMapper.Map<OpportunityViewModel>(entity);
                var viewModel = new OpportunityViewModel
                {
                    Id                   = entity.Id,
                    DisplayName          = entity.DisplayName,
                    Reference            = entity.Reference,
                    Version              = entity.Version,
                    OpportunityState     = OpportunityStateModel.FromValue(entity.Metadata.OpportunityState.Value),
                    OpportunityChannelId = entity.Metadata.OpportunityChannelId,
                    //TODO
                    TemplateLoaded = entity.TemplateLoaded,

                    //TODO : WAVE-4 GENERIC ACCELERATOR Change : start
                    MetaDataFields = entity.Metadata.Fields.Select(
                        field => new OpportunityMetaDataFields()
                    {
                        DisplayName = field.DisplayName,
                        FieldType   = field.FieldType,
                        Screen      = field.Screen,
                        Values      = field.Values
                    }
                        ).ToList(),
                    //TODO : WAVE-4 GENERIC ACCELERATOR Change : end
                    Customer = new CustomerModel
                    {
                        DisplayName = entity.Metadata.Customer.DisplayName,
                        Id          = entity.Metadata.Customer.Id,
                        ReferenceId = entity.Metadata.Customer.ReferenceId
                    },
                    TeamMembers = new List <TeamMemberModel>(),
                    Notes       = new List <NoteModel>(),
                    Checklists  = new List <ChecklistModel>()
                };

                //DealType
                var dealTypeFlag = false;
                dealTypeFlag = entity.Content.Template is null || entity.Content.Template.Id is null;
                if (!dealTypeFlag)
                {
                    viewModel.Template = await _templateHelpers.MapToViewModel(entity.Content.Template);

                    //DealType Processes
                    var checklistPass = false;
                    foreach (var item in entity.Content.Template.ProcessList)
                    {
                        if (item.ProcessType.ToLower() == "checklisttab" && checklistPass == false)
                        {
                            viewModel = await _checkListProcessService.MapToModelAsync(entity, viewModel, requestId);

                            checklistPass = true;
                        }
                        if (item.ProcessType.ToLower() == "customerdecisiontab")
                        {
                            viewModel = await _customerDecisionProcessService.MapToModelAsync(entity, viewModel, requestId);
                        }
                        if (item.ProcessType.ToLower() == "customerfeedbacktab")
                        {
                            viewModel = await _customerFeedbackProcessService.MapToModelAsync(entity, viewModel, requestId);
                        }
                        if (item.ProcessType.ToLower() == "proposalstatustab")
                        {
                            viewModel = await _proposalStatusProcessService.MapToModelAsync(entity, viewModel, requestId);
                        }
                    }
                }


                // TeamMembers
                foreach (var item in entity.Content.TeamMembers.ToList())
                {
                    var memberModel = new TeamMemberModel();
                    memberModel.RoleId            = item.RoleId; //await _userProfileHelpers.RoleToViewModelAsync(item.AssignedRole, requestId);
                    memberModel.Id                = item.Id;
                    memberModel.DisplayName       = item.DisplayName;
                    memberModel.Mail              = item.Fields.Mail;
                    memberModel.UserPrincipalName = item.Fields.UserPrincipalName;
                    memberModel.Title             = item.Fields.Title ?? String.Empty;
                    memberModel.ProcessStep       = item.ProcessStep;
                    memberModel.Permissions       = new List <PermissionModel>();
                    memberModel.AdGroupName       = await _graphUserAppService.GetAdGroupName(item.RoleId, requestId);

                    memberModel.RoleName = item.RoleName;
                    foreach (var permission in item.Fields.Permissions)
                    {
                        memberModel.Permissions.Add(new PermissionModel {
                            Id = permission.Id, Name = permission.Name
                        });
                    }
                    memberModel.TeamsMembership = new TeamsMembershipModel()
                    {
                        Value = item.TeamsMembership.Value,
                        Name  = item.TeamsMembership.Name.ToString()
                    };
                    viewModel.TeamMembers.Add(memberModel);
                }

                // Notes
                foreach (var item in entity.Content.Notes.ToList())
                {
                    var note = new NoteModel();
                    note.Id = item.Id;

                    var userProfile = new UserProfileViewModel();
                    userProfile.Id                = item.CreatedBy.Id;
                    userProfile.DisplayName       = item.CreatedBy.DisplayName;
                    userProfile.Mail              = item.CreatedBy.Fields.Mail;
                    userProfile.UserPrincipalName = item.CreatedBy.Fields.UserPrincipalName;
                    userProfile.UserRoles         = await _userProfileHelpers.RolesToViewModelAsync(item.CreatedBy.Fields.UserRoles, requestId);

                    note.CreatedBy       = userProfile;
                    note.NoteBody        = item.NoteBody;
                    note.CreatedDateTime = item.CreatedDateTime;

                    viewModel.Notes.Add(note);
                }

                // DocumentAttachments
                viewModel.DocumentAttachments = new List <DocumentAttachmentModel>();
                if (entity.DocumentAttachments != null)
                {
                    foreach (var itm in entity.DocumentAttachments)
                    {
                        var doc = new DocumentAttachmentModel();
                        doc.Id            = itm.Id ?? String.Empty;
                        doc.FileName      = itm.FileName ?? String.Empty;
                        doc.Note          = itm.Note ?? String.Empty;
                        doc.Tags          = itm.Tags ?? String.Empty;
                        doc.Category      = new CategoryModel();
                        doc.Category.Id   = itm.Category.Id;
                        doc.Category.Name = itm.Category.Name;
                        doc.DocumentUri   = itm.DocumentUri;

                        viewModel.DocumentAttachments.Add(doc);
                    }
                }

                return(viewModel);
            }
            catch (Exception ex)
            {
                // TODO: _logger.LogError("MapToViewModelAsync error: " + ex);
                throw new ResponseException($"RequestId: {requestId} - OpportunityToViewModelAsync oppId: {oppId} - failed to map opportunity: {ex}");
            }
        }
        public async Task <IActionResult> CreateOpportunityAsync(string @event, [FromBody] JObject data)
        {
            if (!string.IsNullOrWhiteSpace(@event) && @event.Equals("create", StringComparison.InvariantCultureIgnoreCase))
            {
                try
                {
                    var jopp = data["InputParameters"].First()["value"]["Attributes"];

                    var attributes = jopp.ToDictionary(p => p["key"], v => v["value"]);

                    var opportunityMapping = dynamicsConfiguration.OpportunityMapping;
                    var opportunityName    = GetAttribute(attributes, opportunityMapping.DisplayName)?.ToString();
                    var opportunityId      = GetAttribute(attributes, "opportunityid").ToString();
                    var creator            = dynamicsLinkService.GetUserData(data["InitiatingUserId"].ToString());
                    var creatorRole        = proposalManagerConfiguration.CreatorRole;
                    var opp = new OpportunityViewModel
                    {
                        Reference        = opportunityId,
                        DisplayName      = opportunityName,
                        OpportunityState = OpportunityStateModel.FromValue(opportunityMapping.MapStatusCode((int)GetAttribute(attributes, "statuscode")["Value"])),
                        Customer         = new CustomerModel
                        {
                            DisplayName = dynamicsLinkService.GetAccountName(GetAttribute(attributes, "customerid")?["Id"].ToString())
                        },
                        DealSize             = (double?)GetAttribute(attributes, opportunityMapping.DealSize) ?? 0,
                        AnnualRevenue        = (double?)GetAttribute(attributes, opportunityMapping.AnnualRevenue) ?? 0,
                        OpenedDate           = DateTimeOffset.TryParse(GetAttribute(attributes, opportunityMapping.OpenedDate)?.ToString(), out var dto) ? dto : DateTimeOffset.Now,
                        Margin               = (double?)GetAttribute(attributes, opportunityMapping.Margin) ?? 0,
                        Rate                 = (double?)GetAttribute(attributes, opportunityMapping.Rate) ?? 0,
                        DebtRatio            = (double?)GetAttribute(attributes, opportunityMapping.DebtRatio) ?? 0,
                        Purpose              = GetAttribute(attributes, opportunityMapping.Purpose)?.ToString(),
                        DisbursementSchedule = GetAttribute(attributes, opportunityMapping.DisbursementSchedule)?.ToString(),
                        CollateralAmount     = (double?)GetAttribute(attributes, opportunityMapping.CollateralAmount) ?? 0,
                        Guarantees           = GetAttribute(attributes, opportunityMapping.Guarantees)?.ToString(),
                        RiskRating           = (int?)GetAttribute(attributes, opportunityMapping.RiskRating) ?? 0,
                        TeamMembers          = new TeamMemberModel[]
                        {
                            new TeamMemberModel
                            {
                                DisplayName       = creator.DisplayName,
                                Id                = creator.Id,
                                Mail              = creator.Email,
                                UserPrincipalName = creator.Email,
                                AssignedRole      = new RoleModel
                                {
                                    AdGroupName = creatorRole.AdGroupName,
                                    DisplayName = creatorRole.DisplayName,
                                    Id          = creatorRole.Id
                                }
                            }
                        },
                        Checklists = new ChecklistModel[] { }
                    };

                    var proposalManagerClient = await proposalManagerClientFactory.GetProposalManagerClientAsync();

                    var userProfileResult = await proposalManagerClient.GetAsync($"/api/UserProfile?upn={creator.Email}");

                    var userProfile = JsonConvert.DeserializeObject <UserProfileViewModel>(await userProfileResult.Content.ReadAsStringAsync());
                    if (!userProfile.UserRoles.Any(ur => ur.AdGroupName == creatorRole.AdGroupName))
                    {
                        return(BadRequest($"{creator.Email} is not a member of role {creatorRole.AdGroupName}."));
                    }

                    var remoteEndpoint = $"/api/Opportunity";
                    var result         = await proposalManagerClient.PostAsync(remoteEndpoint, new StringContent(JsonConvert.SerializeObject(opp), Encoding.UTF8, "application/json"));

                    if (result.IsSuccessStatusCode)
                    {
                        await dynamicsLinkService.CreateTemporaryLocationForOpportunityAsync(opportunityId, opportunityName);

                        return(Ok());
                    }
                    else
                    {
                        _logger.LogError("DYNAMICS INTEGRATION ENGINE: Proposal Manager did not return a success status code.");
                        return(BadRequest());
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message);
                    _logger.LogError(ex.StackTrace);
                    return(BadRequest());
                }
            }

            return(BadRequest($"{nameof(@event)} is required"));
        }
        public async Task <OpportunityViewModel> OpportunityToViewModelAsync(Opportunity entity, string requestId = "")
        {
            var oppId = entity.Id;

            try
            {
                //var entityDto = TinyMapper.Map<OpportunityViewModel>(entity);
                var viewModel = new OpportunityViewModel
                {
                    Id               = entity.Id,
                    DisplayName      = entity.DisplayName,
                    Reference        = entity.Reference,
                    Version          = entity.Version,
                    OpportunityState = OpportunityStateModel.FromValue(entity.Metadata.OpportunityState.Value),
                    DealSize         = entity.Metadata.DealSize,
                    AnnualRevenue    = entity.Metadata.AnnualRevenue,
                    OpenedDate       = entity.Metadata.OpenedDate,
                    //For DashBoard
                    TargetDate = entity.Metadata.TargetDate,
                    Industry   = new IndustryModel
                    {
                        Name = entity.Metadata.Industry.Name,
                        Id   = entity.Metadata.Industry.Id
                    },
                    Region = new RegionModel
                    {
                        Name = entity.Metadata.Region.Name,
                        Id   = entity.Metadata.Region.Id
                    },
                    Margin               = entity.Metadata.Margin,
                    Rate                 = entity.Metadata.Rate,
                    DebtRatio            = entity.Metadata.DebtRatio,
                    Purpose              = entity.Metadata.Purpose,
                    DisbursementSchedule = entity.Metadata.DisbursementSchedule,
                    CollateralAmount     = entity.Metadata.CollateralAmount,
                    Guarantees           = entity.Metadata.Guarantees,
                    RiskRating           = entity.Metadata.RiskRating,
                    OpportunityChannelId = entity.Metadata.OpportunityChannelId,
                    Customer             = new CustomerModel
                    {
                        DisplayName = entity.Metadata.Customer.DisplayName,
                        Id          = entity.Metadata.Customer.Id,
                        ReferenceId = entity.Metadata.Customer.ReferenceId
                    },
                    TeamMembers = new List <TeamMemberModel>(),
                    Notes       = new List <NoteModel>(),
                    Checklists  = new List <ChecklistModel>()
                };

                //DealType
                var dealTypeFlag = false;
                dealTypeFlag = entity.Content.DealType is null || entity.Content.DealType.Id is null;
                if (!dealTypeFlag)
                {
                    viewModel.DealType = await _templateHelpers.MapToViewModel(entity.Content.DealType);

                    //DealType Processes
                    var checklistPass = false;
                    foreach (var item in entity.Content.DealType.ProcessList)
                    {
                        if (item.ProcessType.ToLower() == "checklisttab" && checklistPass == false)
                        {
                            viewModel = await _checkListProcessService.MapToModelAsync(entity, viewModel, requestId);

                            checklistPass = true;
                        }
                        if (item.ProcessType.ToLower() == "feedbacktab")
                        {
                            viewModel = await customerFeedbackProcessService.MapToModelAsync(entity, viewModel, requestId);
                        }
                        if (item.ProcessType.ToLower() == "customerdecisiontab")
                        {
                            viewModel = await _customerDecisionProcessService.MapToModelAsync(entity, viewModel, requestId);
                        }
                        if (item.ProcessType.ToLower() == "proposalstatustab")
                        {
                            viewModel = await _proposalStatusProcessService.MapToModelAsync(entity, viewModel, requestId);
                        }
                    }
                }



                // TeamMembers
                foreach (var item in entity.Content.TeamMembers.ToList())
                {
                    var memberModel = new TeamMemberModel();
                    memberModel.AssignedRole = await _userProfileHelpers.RoleToViewModelAsync(item.AssignedRole, requestId);

                    memberModel.Id                = item.Id;
                    memberModel.DisplayName       = item.DisplayName;
                    memberModel.Mail              = item.Fields.Mail;
                    memberModel.UserPrincipalName = item.Fields.UserPrincipalName;
                    memberModel.Title             = item.Fields.Title ?? String.Empty;
                    memberModel.ProcessStep       = item.ProcessStep;

                    viewModel.TeamMembers.Add(memberModel);
                }

                // Notes
                foreach (var item in entity.Content.Notes.ToList())
                {
                    var note = new NoteModel();
                    note.Id = item.Id;

                    var userProfile = new UserProfileViewModel();
                    userProfile.Id                = item.CreatedBy.Id;
                    userProfile.DisplayName       = item.CreatedBy.DisplayName;
                    userProfile.Mail              = item.CreatedBy.Fields.Mail;
                    userProfile.UserPrincipalName = item.CreatedBy.Fields.UserPrincipalName;
                    userProfile.UserRoles         = await _userProfileHelpers.RolesToViewModelAsync(item.CreatedBy.Fields.UserRoles, requestId);

                    note.CreatedBy       = userProfile;
                    note.NoteBody        = item.NoteBody;
                    note.CreatedDateTime = item.CreatedDateTime;

                    viewModel.Notes.Add(note);
                }

                // DocumentAttachments
                viewModel.DocumentAttachments = new List <DocumentAttachmentModel>();
                if (entity.DocumentAttachments != null)
                {
                    foreach (var itm in entity.DocumentAttachments)
                    {
                        var doc = new DocumentAttachmentModel();
                        doc.Id            = itm.Id ?? String.Empty;
                        doc.FileName      = itm.FileName ?? String.Empty;
                        doc.Note          = itm.Note ?? String.Empty;
                        doc.Tags          = itm.Tags ?? String.Empty;
                        doc.Category      = new CategoryModel();
                        doc.Category.Id   = itm.Category.Id;
                        doc.Category.Name = itm.Category.Name;
                        doc.DocumentUri   = itm.DocumentUri;

                        viewModel.DocumentAttachments.Add(doc);
                    }
                }

                return(viewModel);
            }
            catch (Exception ex)
            {
                // TODO: _logger.LogError("MapToViewModelAsync error: " + ex);
                throw new ResponseException($"RequestId: {requestId} - OpportunityToViewModelAsync oppId: {oppId} - failed to map opportunity: {ex}");
            }
        }
示例#6
0
        public async Task <OpportunityViewModel> OpportunityToViewModelAsync(Opportunity entity, string requestId = "")
        {
            var oppId = entity.Id;

            try
            {
                //var entityDto = TinyMapper.Map<OpportunityViewModel>(entity);
                var viewModel = new OpportunityViewModel
                {
                    Id               = entity.Id,
                    DisplayName      = entity.DisplayName,
                    Reference        = entity.Reference,
                    Version          = entity.Version,
                    OpportunityState = OpportunityStateModel.FromValue(entity.Metadata.OpportunityState.Value),
                    DealSize         = entity.Metadata.DealSize,
                    AnnualRevenue    = entity.Metadata.AnnualRevenue,
                    OpenedDate       = entity.Metadata.OpenedDate,
                    Industry         = new IndustryModel
                    {
                        Name = entity.Metadata.Industry.Name,
                        Id   = entity.Metadata.Industry.Id
                    },
                    Region = new RegionModel
                    {
                        Name = entity.Metadata.Region.Name,
                        Id   = entity.Metadata.Region.Id
                    },
                    Margin               = entity.Metadata.Margin,
                    Rate                 = entity.Metadata.Rate,
                    DebtRatio            = entity.Metadata.DebtRatio,
                    Purpose              = entity.Metadata.Purpose,
                    DisbursementSchedule = entity.Metadata.DisbursementSchedule,
                    CollateralAmount     = entity.Metadata.CollateralAmount,
                    Guarantees           = entity.Metadata.Guarantees,
                    RiskRating           = entity.Metadata.RiskRating,
                    OpportunityChannelId = entity.Metadata.OpportunityChannelId,
                    Customer             = new CustomerModel
                    {
                        DisplayName = entity.Metadata.Customer.DisplayName,
                        Id          = entity.Metadata.Customer.Id,
                        ReferenceId = entity.Metadata.Customer.ReferenceId
                    },
                    TeamMembers      = new List <TeamMemberModel>(),
                    Notes            = new List <NoteModel>(),
                    Checklists       = new List <ChecklistModel>(),
                    CustomerDecision = new CustomerDecisionModel
                    {
                        Id            = entity.Content.CustomerDecision.Id,
                        Approved      = entity.Content.CustomerDecision.Approved,
                        ApprovedDate  = entity.Content.CustomerDecision.ApprovedDate,
                        LoanDisbursed = entity.Content.CustomerDecision.LoanDisbursed
                    }
                };

                viewModel.ProposalDocument               = new ProposalDocumentModel();
                viewModel.ProposalDocument.Id            = entity.Content.ProposalDocument.Id;
                viewModel.ProposalDocument.DisplayName   = entity.Content.ProposalDocument.DisplayName;
                viewModel.ProposalDocument.Reference     = entity.Content.ProposalDocument.Reference;
                viewModel.ProposalDocument.DocumentUri   = entity.Content.ProposalDocument.Metadata.DocumentUri;
                viewModel.ProposalDocument.Category      = new CategoryModel();
                viewModel.ProposalDocument.Category.Id   = entity.Content.ProposalDocument.Metadata.Category.Id;
                viewModel.ProposalDocument.Category.Name = entity.Content.ProposalDocument.Metadata.Category.Name;
                viewModel.ProposalDocument.Content       = new ProposalDocumentContentModel();
                viewModel.ProposalDocument.Content.ProposalSectionList = new List <DocumentSectionModel>();
                viewModel.ProposalDocument.Notes = new List <NoteModel>();

                viewModel.ProposalDocument.Tags    = entity.Content.ProposalDocument.Metadata.Tags;
                viewModel.ProposalDocument.Version = entity.Content.ProposalDocument.Version;


                // Checklists
                foreach (var item in entity.Content.Checklists)
                {
                    var checklistTasks = new List <ChecklistTaskModel>();
                    foreach (var subitem in item.ChecklistTaskList)
                    {
                        var checklistItem = new ChecklistTaskModel
                        {
                            Id            = subitem.Id,
                            ChecklistItem = subitem.ChecklistItem,
                            Completed     = subitem.Completed,
                            FileUri       = subitem.FileUri
                        };
                        checklistTasks.Add(checklistItem);
                    }

                    var checklistModel = new ChecklistModel
                    {
                        Id = item.Id,
                        ChecklistStatus   = item.ChecklistStatus,
                        ChecklistTaskList = checklistTasks,
                        ChecklistChannel  = item.ChecklistChannel
                    };
                    viewModel.Checklists.Add(checklistModel);
                }


                // TeamMembers
                foreach (var item in entity.Content.TeamMembers.ToList())
                {
                    var memberModel = new TeamMemberModel();
                    memberModel.Status       = item.Status;
                    memberModel.AssignedRole = await _userProfileHelpers.RoleToViewModelAsync(item.AssignedRole, requestId);

                    memberModel.Id                = item.Id;
                    memberModel.DisplayName       = item.DisplayName;
                    memberModel.Mail              = item.Fields.Mail;
                    memberModel.UserPrincipalName = item.Fields.UserPrincipalName;
                    memberModel.Title             = item.Fields.Title ?? String.Empty;

                    viewModel.TeamMembers.Add(memberModel);
                }


                // Notes
                foreach (var item in entity.Content.Notes.ToList())
                {
                    var note = new NoteModel();
                    note.Id = item.Id;

                    var userProfile = new UserProfileViewModel();
                    userProfile.Id                = item.CreatedBy.Id;
                    userProfile.DisplayName       = item.CreatedBy.DisplayName;
                    userProfile.Mail              = item.CreatedBy.Fields.Mail;
                    userProfile.UserPrincipalName = item.CreatedBy.Fields.UserPrincipalName;
                    userProfile.UserRoles         = await _userProfileHelpers.RolesToViewModelAsync(item.CreatedBy.Fields.UserRoles, requestId);

                    note.CreatedBy       = userProfile;
                    note.NoteBody        = item.NoteBody;
                    note.CreatedDateTime = item.CreatedDateTime;

                    viewModel.Notes.Add(note);
                }


                // ProposalDocument Notes
                foreach (var item in entity.Content.ProposalDocument.Metadata.Notes.ToList())
                {
                    var docNote = new NoteModel();

                    docNote.Id = item.Id;
                    docNote.CreatedDateTime = item.CreatedDateTime;
                    docNote.NoteBody        = item.NoteBody;
                    docNote.CreatedBy       = new UserProfileViewModel
                    {
                        Id                = item.CreatedBy.Id,
                        DisplayName       = item.CreatedBy.DisplayName,
                        Mail              = item.CreatedBy.Fields.Mail,
                        UserPrincipalName = item.CreatedBy.Fields.UserPrincipalName,
                        UserRoles         = await _userProfileHelpers.RolesToViewModelAsync(item.CreatedBy.Fields.UserRoles, requestId)
                    };

                    viewModel.ProposalDocument.Notes.Add(docNote);
                }


                // ProposalDocument ProposalSectionList
                foreach (var item in entity.Content.ProposalDocument.Content.ProposalSectionList.ToList())
                {
                    if (!String.IsNullOrEmpty(item.Id))
                    {
                        var docSectionModel = new DocumentSectionModel();
                        docSectionModel.Id                   = item.Id;
                        docSectionModel.DisplayName          = item.DisplayName;
                        docSectionModel.LastModifiedDateTime = item.LastModifiedDateTime;
                        docSectionModel.Owner                = new UserProfileViewModel();
                        if (item.Owner != null)
                        {
                            docSectionModel.Owner.Id          = item.Owner.Id ?? String.Empty;
                            docSectionModel.Owner.DisplayName = item.Owner.DisplayName ?? String.Empty;
                            if (item.Owner.Fields != null)
                            {
                                docSectionModel.Owner.Mail = item.Owner.Fields.Mail ?? String.Empty;
                                docSectionModel.Owner.UserPrincipalName = item.Owner.Fields.UserPrincipalName ?? String.Empty;
                                docSectionModel.Owner.UserRoles         = new List <RoleModel>();

                                if (item.Owner.Fields.UserRoles != null)
                                {
                                    docSectionModel.Owner.UserRoles = await _userProfileHelpers.RolesToViewModelAsync(item.Owner.Fields.UserRoles, requestId);
                                }
                            }
                            else
                            {
                                docSectionModel.Owner.Mail = String.Empty;
                                docSectionModel.Owner.UserPrincipalName = String.Empty;
                                docSectionModel.Owner.UserRoles         = new List <RoleModel>();

                                if (item.Owner.Fields.UserRoles != null)
                                {
                                    docSectionModel.Owner.UserRoles = await _userProfileHelpers.RolesToViewModelAsync(item.Owner.Fields.UserRoles, requestId);
                                }
                            }
                        }

                        docSectionModel.SectionStatus = item.SectionStatus;
                        docSectionModel.SubSectionId  = item.SubSectionId;
                        docSectionModel.AssignedTo    = new UserProfileViewModel();
                        if (item.AssignedTo != null)
                        {
                            docSectionModel.AssignedTo.Id                = item.AssignedTo.Id;
                            docSectionModel.AssignedTo.DisplayName       = item.AssignedTo.DisplayName;
                            docSectionModel.AssignedTo.Mail              = item.AssignedTo.Fields.Mail;
                            docSectionModel.AssignedTo.Title             = item.AssignedTo.Fields.Title;
                            docSectionModel.AssignedTo.UserPrincipalName = item.AssignedTo.Fields.UserPrincipalName;
                            // TODO: Not including role info since it is not relevant but if needed it needs to be set here
                        }
                        docSectionModel.Task = item.Task;

                        viewModel.ProposalDocument.Content.ProposalSectionList.Add(docSectionModel);
                    }
                }

                // DocumentAttachments
                viewModel.DocumentAttachments = new List <DocumentAttachmentModel>();
                if (entity.DocumentAttachments != null)
                {
                    foreach (var itm in entity.DocumentAttachments)
                    {
                        var doc = new DocumentAttachmentModel();
                        doc.Id            = itm.Id ?? String.Empty;
                        doc.FileName      = itm.FileName ?? String.Empty;
                        doc.Note          = itm.Note ?? String.Empty;
                        doc.Tags          = itm.Tags ?? String.Empty;
                        doc.Category      = new CategoryModel();
                        doc.Category.Id   = itm.Category.Id;
                        doc.Category.Name = itm.Category.Name;
                        doc.DocumentUri   = itm.DocumentUri;

                        viewModel.DocumentAttachments.Add(doc);
                    }
                }

                return(viewModel);
            }
            catch (Exception ex)
            {
                // TODO: _logger.LogError("MapToViewModelAsync error: " + ex);
                throw new ResponseException($"RequestId: {requestId} - OpportunityToViewModelAsync oppId: {oppId} - failed to map opportunity: {ex}");
            }
        }