/// <summary> /// Get timesheet approval notification card. /// </summary> /// <param name="cardDetails">Card details.</param> /// <returns>Timesheet approval notification card attachment.</returns> public Attachment GetApprovedNotificationCard(ApproveRejectCard cardDetails) { cardDetails = cardDetails ?? throw new ArgumentNullException(nameof(cardDetails)); var cardPayload = this.GetCardPayload(ApprovedNotificationCardCacheKey, "\\TimesheetApprovedCard\\approved-card.json"); var welcomeCardOptions = new ApproveRejectCard { TimesheetTabUrl = $"https://teams.microsoft.com/l/entity/{this.botOptions.Value.ManifestId}/fill-timesheet", Date = cardDetails.Date, ProjectLabel = this.localizer.GetString("ProjectLabel"), ProjectTitle = cardDetails.ProjectTitle, HoursLabel = this.localizer.GetString("HoursLabel"), Hours = cardDetails.Hours, CardTitle = this.localizer.GetString("TimesheetApprovedCardTitle"), StatusLabel = this.localizer.GetString("ApprovedStatus"), ViewTimesheetButtonText = this.localizer.GetString("ViewTimesheetButtonText"), }; var template = new AdaptiveCardTemplate(cardPayload); var cardJson = template.Expand(welcomeCardOptions); AdaptiveCard card = AdaptiveCard.FromJson(cardJson).Card; var adaptiveCardAttachment = new Attachment() { ContentType = AdaptiveCard.ContentType, Content = card, }; return(adaptiveCardAttachment); }
/// <summary> /// Generate adaptive card for notification. /// </summary> /// <param name="cardDetails">Adaptive card to be sent.</param> /// <param name="userConversation">User conversation.</param> /// <param name="status">Status of timesheet approval.</param> /// <returns>Task represent async operation.</returns> internal async Tasks.Task NotifyUserAsync(ApproveRejectCard cardDetails, Conversation userConversation, TimesheetStatus status) { if (status == TimesheetStatus.Approved) { var approvedCardAttachment = this.adaptiveCardService.GetApprovedNotificationCard(cardDetails); await this.notificationHelper.SendNotificationToUserAsync(userConversation, approvedCardAttachment); } else if (status == TimesheetStatus.Rejected) { var rejectedCardAttachment = this.adaptiveCardService.GetRejectedNotificationCard(cardDetails); await this.notificationHelper.SendNotificationToUserAsync(userConversation, rejectedCardAttachment); } }
public void PrepareCard_WithSameTimesheetDates_ShouldRetunCorrectTemplatingModel() { // ARRANGE var timesheetsForApproval = new List <TimesheetEntity> { this.CreateTimesheetEntity(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 5)), this.CreateTimesheetEntity(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 5)), }; var expectedResult = new ApproveRejectCard { Date = "{{DATE(2021-03-05T00:00:00Z)}}", Hours = "10", ProjectTitle = "Project", }; // ACT var result = this.timesheetHelper.PrepareCard(timesheetsForApproval.ToList()); Assert.AreEqual(expectedResult.Date, result.Date); Assert.AreEqual(expectedResult.Hours, result.Hours); Assert.AreEqual(expectedResult.ProjectTitle, result.ProjectTitle); }
/// <summary> /// Send notification. /// </summary> /// <param name="timesheets">Details of timesheet.</param> /// <param name="status">Status of timesheet.</param> /// <returns>Task represent async operation.</returns> private async Task <bool> SendNotificationsAsync(List <TimesheetEntity> timesheets, TimesheetStatus status) { var timesheetsGroupedByUser = timesheets.Where(timesheet => timesheet.Hours > 0).GroupBy(timesheet => timesheet.UserId); foreach (var userTimesheets in timesheetsGroupedByUser) { var userConversation = await this.repositoryAccessors.ConversationRepository.GetAsync(userTimesheets.First().UserId); if (userConversation != null) { var groupedByProject = userTimesheets.GroupBy(timesheet => timesheet.Task.ProjectId); foreach (var projectwiseTimesheets in groupedByProject) { var tprojectwiseTimesheets = projectwiseTimesheets.OrderBy(timesheet => timesheet.TimesheetDate).ToList(); var daterange = new List <TimesheetEntity> [100]; int currentItemIndex = 0; for (int i = 0; i < tprojectwiseTimesheets.Count; i++) { if (i == 0) { daterange[currentItemIndex] = new List <TimesheetEntity>(); daterange[currentItemIndex].Add(tprojectwiseTimesheets[i]); } else { if ((tprojectwiseTimesheets[i].TimesheetDate == daterange[currentItemIndex].Last().TimesheetDate) || (tprojectwiseTimesheets[i].TimesheetDate.AddDays(-1) == daterange[currentItemIndex].Last().TimesheetDate)) { daterange[currentItemIndex].Add(tprojectwiseTimesheets[i]); } else { currentItemIndex += 1; daterange[currentItemIndex] = new List <TimesheetEntity>(); daterange[currentItemIndex].Add(tprojectwiseTimesheets[i]); } } } var filteredDaterange = daterange.Where(item => item != null && item.Count > 0); foreach (var item in filteredDaterange) { if (item.Count > 0) { var isTimesheetForOneDay = item.First().TimesheetDate.Date == item.Last().TimesheetDate.Date; var cardDetails = new ApproveRejectCard { Date = isTimesheetForOneDay ? "{{DATE(" + item.First().TimesheetDate.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.InvariantCulture) + ")}}" : "{{DATE(" + item.First().TimesheetDate.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.InvariantCulture) + ")}} - {{DATE(" + item.Last().TimesheetDate.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.InvariantCulture) + ")}}", Hours = Convert.ToString(item.Sum(timesheet => timesheet.Hours), CultureInfo.InvariantCulture), ProjectTitle = item.First().Task.Project.Title, }; if (status == TimesheetStatus.Approved) { var approvedCardAttachment = this.adaptiveCardService.GetApprovedNotificationCard(cardDetails); await this.notificationHelper.SendNotificationToUserAsync(userConversation, approvedCardAttachment); } else if (status == TimesheetStatus.Rejected) { var commentByManager = item.First().ManagerComments; cardDetails.Comment = string.IsNullOrEmpty(commentByManager) ? "-" : commentByManager; var rejectedCardAttachment = this.adaptiveCardService.GetRejectedNotificationCard(cardDetails); await this.notificationHelper.SendNotificationToUserAsync(userConversation, rejectedCardAttachment); } } } } } } return(true); }