public async Task <StatusCodes> CallAddInWebhookAsync(Opportunity opportunity, string requestId = "") { var client = await proposalManagerClientFactory.GetProposalManagerClientAsync(); var result = await client.PostAsync("/api/dynamics/LinkSharePointLocations", new StringContent(JsonConvert.SerializeObject(await opportunityHelpers.OpportunityToViewModelAsync(opportunity, requestId)), Encoding.UTF8, "application/json")); return(result.IsSuccessStatusCode ? StatusCodes.Status200OK : StatusCodes.Status400BadRequest); }
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()); } }
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 ProcessFormalProposalChangesAsync(string opportunityName, string resource) { var resetLink = $"https://graph.microsoft.com/v1.0{resource}/delta"; var deltaLink = deltaLinksStorage.OpportunityDeltaLinks.ContainsKey(opportunityName) ? deltaLinksStorage.OpportunityDeltaLinks[opportunityName] : resetLink; var result = ProcessDriveChangesAsync( ref deltaLink, di => ( di.ParentReference?.Path == "/drive/root:/Formal Proposal" && di.Name.EndsWith(".docx") && true // change by CreatedBy check ), async batch => { var preResult = new List <Task>(); var actions = batch.Select(d => new { FileName = d.Name, OpportunityName = d.ParentReference.Path.Split('/').Last() }); var graphClient = graphClientContext.GraphClient; var item = batch.Last(); var fileUri = $"https://graph.microsoft.com/v1.0{resource}:/Formal Proposal/{item.Name}[email protected]"; var parts = new Uri(fileUri).Segments; var partsLength = parts.Length; var docName = parts[partsLength - 1]; var oppName = parts[partsLength - 2].Replace("/", ""); try { var hrm = new HttpRequestMessage(HttpMethod.Get, fileUri); var response = new HttpResponseMessage(); // Authenticate (add access token) to the HttpRequestMessage await graphClient.AuthenticationProvider.AuthenticateRequestAsync(hrm); // Send the request and get the response var jsonResponse = await graphClient.HttpProvider.SendAsync(hrm); var dataJson = JsonConvert.DeserializeObject <GraphMetadata>(jsonResponse.Content.ReadAsStringAsync().Result); var hrmContent = new HttpRequestMessage(HttpMethod.Get, dataJson.DownloadUrl); await graphClient.AuthenticationProvider.AuthenticateRequestAsync(hrmContent); var responseContent = await graphClient.HttpProvider.SendAsync(hrmContent); var arr = await responseContent.Content.ReadAsByteArrayAsync(); var fileContent = new ByteArrayContent(arr); var multiContent = new MultipartFormDataContent() { { fileContent, "file", docName }, { new StringContent(opportunityName), "opportunityName" }, { new StringContent("ProposalTemplate"), "docType" } }; var client = await proposalManagerClientFactory.GetProposalManagerClientAsync(); var pmResult = await client.PutAsync($"/api/Document/UploadFile/{opportunityName}/ProposalTemplate", multiContent); if (!pmResult.IsSuccessStatusCode) { throw new Exception($@"DYNAMICS INTEGRATION ENGINE: Something went wrong when expecting Proposal Manager to parse the document. Relevant context is as follows: Opportunity: {opportunityName} Resource: {resource} Proposal Manager result: {await pmResult.Content.ReadAsStringAsync()}"); } } catch (Exception ex) { throw new Exception($@"DYNAMICS INTEGRATION ENGINE: Something went wrong when processing file changes for the opportunity specified. Relevant context is as follows: Opportunity: {opportunityName} Resource: {resource} [INNER EXCEPTION]: Message: {ex.Message} Stacktrace: {ex.StackTrace}", ex); } }, resetLink); /* This causes the next immediate request to be bypassed, given that it will correspond to the * file overwriting that Proposal Manager performs after analyzing the document. */ deltaLinksStorage.OpportunityDeltaLinks.Remove(opportunityName); await result; }