/// <summary> /// Method Handle adaptive card submit in 1:1 chat and Send new ticket details to SME team. /// </summary> /// <param name="message">Message activity of bot.</param> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="ticketGenerateStorageProvider">Provider to get ticket id to Azure Table Storage.</param> /// <param name="ticketDetailStorageProvider">Provider to store ticket details to Azure Table Storage.</param> /// <param name="cardConfigurationStorageProvider">Provider to search card configuration details in Azure Table Storage.</param> /// <param name="microsoftAppCredentials">Microsoft Application credentials for Bot/ME.</param> /// <param name="logger">Sends logs to the Application Insights service.</param> /// <param name="appBaseUrl">Represents the Application base Uri.</param> /// <param name="localizer">The current cultures' string localizer.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns>A task that handles submit action in 1:1 chat.</returns> internal static async Task OnAdaptiveCardSubmitInPersonalChatAsync( IMessageActivity message, ITurnContext <IMessageActivity> turnContext, ITicketIdGeneratorStorageProvider ticketGenerateStorageProvider, ITicketDetailStorageProvider ticketDetailStorageProvider, ICardConfigurationStorageProvider cardConfigurationStorageProvider, MicrosoftAppCredentials microsoftAppCredentials, ILogger logger, string appBaseUrl, IStringLocalizer <Strings> localizer, CancellationToken cancellationToken) { IMessageActivity endUserUpdateCard; switch (message.Text.ToUpperInvariant()) { case Constants.SendRequestAction: TicketDetail newTicketDetail = JsonConvert.DeserializeObject <TicketDetail>(message.Value?.ToString()); if (TicketHelper.ValidateRequestDetail(newTicketDetail)) { AdaptiveCardAction cardDetail = ((JObject)message.Value).ToObject <AdaptiveCardAction>(); logger.LogInformation("Adding new request with additional details."); var ticketTd = await ticketGenerateStorageProvider.GetTicketIdAsync(); // Update new request with additional details. var userDetails = await GetUserDetailsInPersonalChatAsync(turnContext, cancellationToken); newTicketDetail.TicketId = ticketTd.ToString(CultureInfo.InvariantCulture); newTicketDetail = TicketHelper.GetNewTicketDetails(turnContext: turnContext, ticketDetail: newTicketDetail, ticketAdditionalDetails: message.Value?.ToString(), cardId: cardDetail.CardId, member: userDetails); bool result = await ticketDetailStorageProvider.UpsertTicketAsync(newTicketDetail); if (!result) { logger.LogError("Error in storing new ticket details in table storage."); await turnContext.SendActivityAsync(localizer.GetString("AzureStorageErrorText")); return; } logger.LogInformation("New request created with ticket Id:" + newTicketDetail.TicketId); // Get card item element mappings var carditemElementMapping = await cardConfigurationStorageProvider.GetCardItemElementMappingAsync(cardDetail?.CardId); endUserUpdateCard = MessageFactory.Attachment(TicketCard.GetTicketDetailsForPersonalChatCard(carditemElementMapping, newTicketDetail, localizer, false)); await CardHelper.SendRequestCardToSMEChannelAsync(turnContext : turnContext, ticketDetail : newTicketDetail, logger : logger, ticketDetailStorageProvider : ticketDetailStorageProvider, applicationBasePath : appBaseUrl, cardElementMapping : carditemElementMapping, localizer, teamId : cardDetail?.TeamId, microsoftAppCredentials : microsoftAppCredentials, cancellationToken : cancellationToken); await CardHelper.UpdateRequestCardForEndUserAsync(turnContext, endUserUpdateCard); await turnContext.SendActivityAsync(MessageFactory.Text(localizer.GetString("EndUserNotificationText", newTicketDetail.TicketId))); } else { // Update card with validation message. newTicketDetail.AdditionalProperties = CardHelper.ValidateAdditionalTicketDetails(message.Value?.ToString(), timeSpan: turnContext.Activity.LocalTimestamp.Value.Offset); CardConfigurationEntity cardTemplateJson = await cardConfigurationStorageProvider.GetConfigurationAsync(); endUserUpdateCard = MessageFactory.Attachment(TicketCard.GetNewTicketCard(cardConfiguration: cardTemplateJson, localizer: localizer, showValidationMessage: true, ticketDetail: newTicketDetail)); await CardHelper.UpdateRequestCardForEndUserAsync(turnContext, endUserUpdateCard); } break; case Constants.WithdrawRequestAction: var payload = ((JObject)message.Value).ToObject <AdaptiveCardAction>(); endUserUpdateCard = MessageFactory.Attachment(WithdrawCard.GetCard(payload.PostedValues, localizer)); // Get the ticket from the data store. TicketDetail ticketDetail = await ticketDetailStorageProvider.GetTicketAsync(payload.PostedValues); if (ticketDetail.TicketStatus == (int)TicketState.Kapatılmış) { await turnContext.SendActivityAsync(localizer.GetString("WithdrawErrorMessage")); return; } ticketDetail.LastModifiedByName = message.From.Name; ticketDetail.LastModifiedByObjectId = message.From.AadObjectId; ticketDetail.TicketStatus = (int)TicketState.Vazgeçilmiş; bool success = await ticketDetailStorageProvider.UpsertTicketAsync(ticketDetail); if (!success) { logger.LogError("Error in updating ticket details in table storage."); await turnContext.SendActivityAsync(localizer.GetString("AzureStorageErrorText")); return; } logger.LogInformation("Withdrawn the ticket:" + ticketDetail.TicketId); IMessageActivity smeWithdrawNotification = MessageFactory.Text(localizer.GetString("SmeWithdrawNotificationText", ticketDetail.RequesterName)); var itemElementMapping = await cardConfigurationStorageProvider.GetCardItemElementMappingAsync(ticketDetail?.CardId); await CardHelper.UpdateSMECardAsync(turnContext, ticketDetail, smeWithdrawNotification, appBaseUrl, itemElementMapping, localizer, logger, cancellationToken); await CardHelper.UpdateRequestCardForEndUserAsync(turnContext, endUserUpdateCard); break; } }
/// <summary> /// Handle adaptive card submit in channel. /// Updates the ticket status based on the user submission. /// </summary> /// <param name="message">A message in a conversation.</param> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="ticketDetailStorageProvider">Provider to store ticket details to Azure Table Storage.</param> /// <param name="cardConfigurationStorageProvider">Provider to search card configuration details in Azure Table Storage.</param> /// <param name="logger">Sends logs to the Application Insights service.</param> /// <param name="appBaseUrl">Represents the Application base Uri.</param> /// <param name="localizer">The current cultures' string localizer.</param> /// /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns>A task that represents the work queued to execute.</returns> internal static async Task OnAdaptiveCardSubmitInChannelAsync( IMessageActivity message, ITurnContext <IMessageActivity> turnContext, ITicketDetailStorageProvider ticketDetailStorageProvider, ICardConfigurationStorageProvider cardConfigurationStorageProvider, ILogger logger, string appBaseUrl, IStringLocalizer <Strings> localizer, CancellationToken cancellationToken) { string smeNotification; IMessageActivity userNotification; ChangeTicketStatus payload = ((JObject)message.Value).ToObject <ChangeTicketStatus>(); payload.Action = payload.RequestType == null ? payload.Action : RequestTypeText; logger.LogInformation($"Received submit: action={payload.Action} ticketId={payload.TicketId}"); // Get the ticket from the data store. TicketDetail ticketData = await ticketDetailStorageProvider.GetTicketAsync(payload.TicketId); if (ticketData == null) { await turnContext.SendActivityAsync($"Ticket {payload.TicketId} was not found in the data store"); logger.LogInformation($"Ticket {payload.TicketId} was not found in the data store"); return; } // Update the ticket based on the payload. switch (payload.Action) { case ChangeTicketStatus.ReopenAction: ticketData.TicketStatus = (int)TicketState.Atanmamış; ticketData.AssignedToName = null; ticketData.AssignedToObjectId = null; ticketData.ClosedOn = null; smeNotification = localizer.GetString("SmeUnassignedStatus", message.From.Name); userNotification = MessageFactory.Text(localizer.GetString("ReopenedTicketUserNotification", ticketData.TicketId)); break; case ChangeTicketStatus.CloseAction: ticketData.TicketStatus = (int)TicketState.Kapatılmış; ticketData.ClosedByName = message.From.Name; ticketData.ClosedOn = message.From.AadObjectId; smeNotification = localizer.GetString("SmeClosedStatus", message.From.Name); userNotification = MessageFactory.Text(localizer.GetString("ClosedTicketUserNotification", ticketData.TicketId)); break; case ChangeTicketStatus.AssignToSelfAction: ticketData.TicketStatus = (int)TicketState.Atanmış; ticketData.AssignedToName = message.From.Name; ticketData.AssignedToObjectId = message.From.AadObjectId; ticketData.ClosedOn = null; smeNotification = localizer.GetString("SmeAssignedStatus", message.From.Name); userNotification = MessageFactory.Text(localizer.GetString("AssignedTicketUserNotification", ticketData.TicketId)); break; case ChangeTicketStatus.RequestTypeAction: ticketData.Severity = (int)(TicketSeverity)Enum.Parse(typeof(TicketSeverity), payload.RequestType); ticketData.RequestType = payload.RequestType; logger.LogInformation($"Received submit: action={payload.RequestType} ticketId={payload.TicketId}"); smeNotification = localizer.GetString("SmeSeverityStatus", ticketData.RequestType, message.From.Name); userNotification = MessageFactory.Text(localizer.GetString("RequestActionTicketUserNotification", ticketData.TicketId)); break; default: logger.LogInformation($"Unknown status command {payload.Action}", SeverityLevel.Warning); return; } ticketData.LastModifiedByName = message.From.Name; ticketData.LastModifiedByObjectId = message.From.AadObjectId; ticketData.LastModifiedOn = DateTime.UtcNow; await ticketDetailStorageProvider.UpsertTicketAsync(ticketData); logger.LogInformation($"Ticket {ticketData.TicketId} updated to status ({ticketData.TicketStatus}, {ticketData.AssignedToObjectId}) in store"); // Get card item element mappings var cardElementMapping = await cardConfigurationStorageProvider.GetCardItemElementMappingAsync(ticketData.CardId); // Update the card in the SME team. Activity updateCardActivity = new Activity(ActivityTypes.Message) { Id = ticketData.SmeTicketActivityId, Conversation = new ConversationAccount { Id = ticketData.SmeConversationId }, Attachments = new List <Attachment> { new SmeTicketCard(ticketData).GetTicketDetailsForSMEChatCard(cardElementMapping, ticketData, appBaseUrl, localizer) }, }; ResourceResponse updateResponse = await turnContext.UpdateActivityAsync(updateCardActivity, cancellationToken); logger.LogInformation($"Card for ticket {ticketData.TicketId} updated to status ({ticketData.TicketStatus}, {ticketData.AssignedToObjectId}), activityId = {updateResponse.Id}"); // Post update to user and SME team thread. if (!string.IsNullOrEmpty(smeNotification)) { ResourceResponse smeResponse = await turnContext.SendActivityAsync(smeNotification); logger.LogInformation($"SME team notified of update to ticket {ticketData.TicketId}, activityId = {smeResponse.Id}"); } if (userNotification != null) { userNotification.Conversation = new ConversationAccount { Id = ticketData.RequesterConversationId }; ResourceResponse[] userResponse = await turnContext.Adapter.SendActivitiesAsync(turnContext, new Activity[] { (Activity)userNotification }, cancellationToken); logger.LogInformation($"User notified of update to ticket {ticketData.TicketId}, activityId = {userResponse.FirstOrDefault()?.Id}"); } }