public async Task <string> CreateTimerHoursAsync(DateTimeOffset dateTime, string requestId = "") { _logger.LogInformation($"RequestId: {requestId} - TimerHourRepository_CreateTimerHoursAsync called."); try { // Create JSON object dynamic fieldsObject = new JObject(); fieldsObject.Date = dateTime.ToString("MM/dd/yyyy"); fieldsObject.StartTime = dateTime.ToString("h:mm tt"); fieldsObject.StopTime = "InProgress"; dynamic jsonObject = new JObject(); jsonObject.fields = fieldsObject; // Get the site list var userObjectIdentifier = _userContext.User.FindFirst(AzureAdAuthenticationBuilderExtensions.ObjectIdentifierType)?.Value; var siteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.TimerHoursSchema); // Call graph to create the item in the SHarePoint List var entryId = await _graphSharePointService.CreateSiteListItemAsync(siteList, jsonObject.ToString()); return(entryId); } catch (Exception ex) { _logger.LogError($"RequestId: {requestId} - TimerHoursRepository_CreateTimerHoursAsync Service Exception: {ex}"); throw; } }
public async Task SaveItemAsync(WorkHours modelData) { if (String.IsNullOrEmpty(modelData.Id)) { throw new ArgumentNullException(nameof(modelData.Id)); } try { var workHoursList = new List <WorkHours>(); var workHoursListCollectionPage = new ListCollectionPage <WorkHours>(); // This works when dateTime is longer. var dateQuery = modelData.Fields.Date.Remove(6); // Get the site list var userObjectIdentifier = _objectIdentifier; // _userContext.User.FindFirst(ObjectIdentifierType)?.Value; var siteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.WorkHoursListSchema); //if (String.IsNullOrEmpty(siteList.ListId)) siteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.WorkHoursListSchema); // Create JSON object dynamic fieldsObject = new JObject(); fieldsObject.MeetingAdjustedHours = modelData.Fields.MeetingAdjustedHours; fieldsObject.MeetingAdjustedMinutes = modelData.Fields.MeetingAdjustedMinutes; fieldsObject.EmailAdjustedHours = modelData.Fields.EmailAdjustedHours; fieldsObject.EmailAdjustedMinutes = modelData.Fields.EmailAdjustedMinutes; fieldsObject.OtherAdjustedHours = modelData.Fields.OtherAdjustedHours; fieldsObject.OtherAdjustedMinutes = modelData.Fields.OtherAdjustedMinutes; fieldsObject.AdjustedHoursReason = modelData.Fields.AdjustedHoursReason; dynamic rootObject = new JObject(); rootObject.fields = fieldsObject; // Persist to SharePoint var result = await _graphSharePointService.UpdateSiteListItemAsync(siteList, modelData.Id, rootObject.ToString()); } catch (Exception ex) { } }
// Private methods public async Task <ListCollectionPage <ReportHours> > GetItemsResultsAsync(DateTime date, int pageSize = 10, string searchQuery = "") { try { var dateQuery = date.ToString("yyyyMM"); var listCollectionPage = new ListCollectionPage <ReportHours>(); listCollectionPage.QueryDate = dateQuery; listCollectionPage.ObjectIdentifier = _reportHoursIdentifier; listCollectionPage.CurrentPageIndex = 1; listCollectionPage.PageSize = pageSize; listCollectionPage.SearchQuery = searchQuery; listCollectionPage.SiteList = await _graphSharePointService.GetSiteListAsync(_reportHoursIdentifier, ListSchema.ReportHoursListSchema); var queryOptions = new List <QueryOption>(); queryOptions.Add(new QueryOption("filter", @"startswith(fields/Date,'" + listCollectionPage.QueryDate + "')")); // Filter to get all entries of a month // Call to SharePoint graph service var graphResults = await _graphSharePointService.GetSiteListItemsAsync(listCollectionPage.SiteList, queryOptions, pageSize); if (graphResults.DataList?.Count == 0) { return(new ListCollectionPage <ReportHours>()); // No entries were found } listCollectionPage.SkipToken = ""; if (!String.IsNullOrEmpty(graphResults.SkipToken)) { listCollectionPage.SkipToken = graphResults.SkipToken; // Store skiptoken if any } listCollectionPage.DataList = await AddItemsToDataListAsync(graphResults.DataList, dateQuery); return(listCollectionPage); } catch (Exception ex) { _logger.LogError("Error getting report hour items in repository: " + ex.Message); throw; } }
public async Task <IEnumerable <Analytics> > GetItemsAsync(DateTime date) { if (date == null) { throw new ArgumentNullException(nameof(date)); } try { var analyticsListCollectionPage = new ListCollectionPage <Analytics>(); var dateQuery = date.ToString("yyyyMM"); // Get all items in a given month string objectIdentifier = Guid.NewGuid().ToString(); // Get the site list analyticsListCollectionPage.SiteList = await _graphSharePointService.GetSiteListAsync(objectIdentifier, ListSchema.TotalHrsListSchema); var siteList = analyticsListCollectionPage.SiteList; analyticsListCollectionPage.QueryDate = dateQuery; // Get the results from the call to GraphService.GetSiteListItemByDateAsync var results = await _graphSharePointService.GetSiteListItemsAsync(siteList, dateQuery); var analyticsResults = await AddItemsToDataListAsync(siteList, results); // get the datewise groupings and the count of users both total and reported overtime //var groupings = from item in analyticsResults // group item by item.Fields.selDate into data // select data.Distinct(); return(analyticsResults); } catch (Exception ex) { _logger.LogError("Error getting work hour items in repository: " + ex.Message); throw; } }
public async Task <UserProfile> GetItemAsync() { try { var identifier = _userContext.User.FindFirst(AzureAdAuthenticationBuilderExtensions.ObjectIdentifierType)?.Value; var userProfile = new UserProfile { Id = identifier }; // Try to get the user profile from from cache var cacheKey = _userContext.User.FindFirst(AzureAdAuthenticationBuilderExtensions.ObjectIdentifierType)?.Value; userProfile = await _memoryCacheService.TryRetrieveFromCacheAsync(userProfile, cacheKey); if (userProfile != null) { return(userProfile); } // Get user info from Graph var userInfoResults = await _graphUserService.GetMyUserInfoAsync(identifier); // Check to see that users exists on Users List, if not add it with default personal settings if (_usersList == null) { _usersList = await _graphSharePointService.GetSiteListAsync("users", Helpers.ListSchema.UsersListSchema); } var queryOptions = new List <QueryOption>(); queryOptions.Add(new QueryOption("filter", @"startswith(fields/ObjectIdentifier,'" + identifier + "')")); var usersListResults = await _graphSharePointService.GetSiteListItemsAsync(_usersList, queryOptions); if (usersListResults?.Count == 0) { // Register user in Users List // Create JSON object to add the user in the list dynamic userListFieldsObject = new JObject(); userListFieldsObject.ObjectIdentifier = identifier; userListFieldsObject.UserMail = userInfoResults.Properties["Mail"].ToString() ?? userInfoResults.Properties["Upn"].ToString(); userListFieldsObject.FirstDayOfWeek = _timeTrackerOptions.FirstDayWeek ?? "Monday"; userListFieldsObject.EmailNotificationsEnabled = true; userListFieldsObject.AutoSubmitData = "scheduled"; userListFieldsObject.DailyUpdateStatus = "scheduled"; userListFieldsObject.UpdateDate = DateTime.Now; userListFieldsObject.AutoSubmitStatus = "initial"; userListFieldsObject.SubmitDate = Convert.ToDateTime("01/01/2017"); dynamic userListRootObject = new JObject(); userListRootObject.fields = userListFieldsObject; // Call graph to create the entry i the list await _graphSharePointService.CreateSiteListItemAsync(_usersList, userListRootObject.ToString()); // Call graph again to fetch the newly created entry (to confirm and have the object expected for functional below usersListResults = await _graphSharePointService.GetSiteListItemsAsync(_usersList, queryOptions); } //var firstDayWeek = _timeTrackerOptions.FirstDayWeek; var firstDayWeek = usersListResults[0].Properties["FirstDayOfWeek"].ToString(); // Get groups the user belongs to //var memberOfResults = await _graphUserService.GetMemberOfAsync(); // Get manager info for the user var managerResults = await _graphUserService.GetMyManagerAsync(identifier); // Get the user direct reports list var isManager = await _graphUserService.GetMyHasDirectReportsAsync(identifier); var dailyUpdateStatus = usersListResults[0].Properties["DailyUpdateStatus"].ToString(); var updateDate = usersListResults[0].Properties["UpdateDate"].ToString(); var autoSubmitStatus = usersListResults[0].Properties["AutoSubmitStatus"].ToString(); var submitDate = usersListResults[0].Properties["SubmitDate"].ToString(); userProfile = new UserProfile { Id = userInfoResults.Id, Fields = new UserProfileFields { ObjectIdentifier = userInfoResults.Id, DisplayName = userInfoResults.DisplayName, Upn = userInfoResults.Properties["Upn"].ToString(), Mail = userInfoResults.Properties["Mail"].ToString(), UserPicture = userInfoResults.Properties["Picture"].ToString(), IsManager = isManager, //IsAdmin = memberOfResults.Exists(x => x.DisplayName == _timeTrackerOptions.AdminGroup), IsAdmin = await _graphUserService.GetMemberOfAsync(_timeTrackerOptions.AdminGroup), //IsHr = memberOfResults.Exists(x => x.DisplayName == _timeTrackerOptions.HrGroup), IsHr = await _graphUserService.GetMemberOfAsync(_timeTrackerOptions.HrGroup), // TODO: Store this in personalization settings for user, for now just set to default which is true EmailNotifications = Convert.ToBoolean(usersListResults[0].Properties["EmailNotificationsEnabled"]), Manager = managerResults.DisplayName, ManagerPicture = managerResults.Properties["Picture"].ToString(), SpSiteId = _timeTrackerOptions.SharePointSiteId, FirstDayWeek = firstDayWeek, DailyUpdateStatus = dailyUpdateStatus, UpdateDate = Convert.ToDateTime(updateDate), AutoSubmitStatus = autoSubmitStatus, SubmitDate = Convert.ToDateTime(submitDate) } }; // Write the user profile to cache await _memoryCacheService.SaveToCacheAsync(userProfile, cacheKey); return(userProfile); } catch (Exception ex) { _logger.LogError("Error getting user in repository: " + ex.Message); return(null); } }
public async Task SendNotificationAsync(GraphResultItem sendToObject, NotificationType notificationType, string messageBody = "") { try { if (sendToObject == null) { throw new ArgumentNullException(nameof(sendToObject)); } var userProfile = await _userProfileRepository.GetItemAsync(); // Create notification entry and persist var notification = new Notifications { Fields = new NotificationsFields { SentToMail = sendToObject.Properties["Mail"].ToString(), SentToName = sendToObject.DisplayName, SentFromMail = userProfile.Fields.Mail ?? userProfile.Fields.Upn, SentFromName = userProfile.Fields.DisplayName, SentDate = DateTime.Now, MessageBody = messageBody } }; if (!_timeTrackerOptions.HrNotificationAlerts && sendToObject.Id == "inbox") { // Don't create the notification alert for HR if disabled in app settings } else { // Get the SpSiteList, if the list does not exists, it will create one var notificationsSiteList = await _graphSharePointService.GetSiteListAsync(sendToObject.Id, ListSchema.NotificationsListSchema); // Create JSON object to update or create WORK HOURS (aka employee entries) in SharePoint dynamic notificationsFieldsObject = new JObject(); notificationsFieldsObject.SentToMail = notification.Fields.SentToMail; notificationsFieldsObject.SentDate = notification.Fields.SentDate; notificationsFieldsObject.SentFromMail = notification.Fields.SentFromMail; notificationsFieldsObject.MessageBody = notification.Fields.MessageBody ?? ""; dynamic notificationsRootObject = new JObject(); notificationsRootObject.fields = notificationsFieldsObject; // Add new notification in SharePoint var result = await _graphSharePointService.CreateSiteListItemAsync(notificationsSiteList, notificationsRootObject.ToString()); } // If user elected to get notifications by email, send the notification email if (userProfile.Fields.EmailNotifications) { var emailTemplate = "/" + notificationType.ToString() + "_template.html"; // Send email TODO: Add localization to subject parameter below await _graphUserService.SendEmailAsync(userProfile.Fields.ObjectIdentifier, notification.Fields.SentToMail, "Notification from Time Tracker", emailTemplate); } } catch (Exception ex) { _logger.LogError("Error sending a notification in workflow for WorkHours: " + ex.Message); } }
public async Task <bool> UpdateAnalytics() { try { // Get the site list string objectIdentifier = Guid.NewGuid().ToString(); var analyticsSiteList = await _graphSharePointService.GetSiteListAsync(objectIdentifier, ListSchema.TotalHrsListSchema); bool processForToday = true; var analyticsRecords = await _graphSharePointService.GetSiteListItemsAsync(analyticsSiteList); processForToday = analyticsRecords.Count > 0; // get the reportHours var reportHoursSiteList = await _graphSharePointService.GetSiteListAsync(_reportHoursListIdentifier, ListSchema.ReportHoursListSchema); // if is first time process the submissions during current month, else check for any submits today. //var submittedDate = DateTime.Now.Date.ToString("yyyyMMdd", CultureInfo.InvariantCulture); ////var todayDate = DateTime.ParseExact(submittedDate, "yyyyMMdd", CultureInfo.InvariantCulture); //submittedDate = processForToday ? submittedDate : submittedDate.Remove(6); //var options = new List<QueryOption>(); //options.Add(new QueryOption("filter", @"startswith(fields/TeamHoursSubmittedDate,'" + submittedDate + "')")); //var reportHoursList = await _graphSharePointService.GetSiteListItemsAsync(reportHoursSiteList, options); var submitDate = DateTime.Now.Date.AddDays(-1); var startDate = processForToday ? submitDate : submitDate.AddDays(1 - submitDate.Day); var endDate = submitDate; // processForToday ? submitDate : startDate.AddMonths(1).AddDays(-1); var reportHoursList = await _graphSharePointService.GetSiteListItemsAsync(reportHoursSiteList); var filteredList = reportHoursList.Where(k => (DateTime.Parse(k.Properties["TeamHoursSubmittedDate"].ToString()).Date >= startDate) && (DateTime.Parse(k.Properties["TeamHoursSubmittedDate"].ToString()).Date <= endDate)).ToList(); foreach (var item in filteredList) { // Get work hours list for this teamHours entry and update the TeamHoursItemState var userObjectIdentifier = item.Properties["ObjectIdentifier"].ToString(); var workHoursSiteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.WorkHoursListSchema); // Works for longer yyyyMMdd date. var dateQuery = item.Properties["Date"].ToString().Remove(6); var workHoursResult = await _graphSharePointService.GetSiteListItemsAsync(workHoursSiteList, dateQuery); if (workHoursResult?.Count == 0) { throw new ServiceException(new Error { Code = "invalidRequest", Message = "Can't retrieve work hours for a team hours entry" }); } foreach (var workHoursItem in workHoursResult) { if ((workHoursItem.Properties["TeamHoursItemState"].ToString() != ItemState.Submitted.ToString()) || (item.Properties["TeamHoursSubmittedDate"].ToString() != workHoursItem.Properties["TeamHoursSubmittedDate"].ToString())) { // log error and continue; // continue; //TODO: find out why only one item is getting updated in workhours with teamhourssubmitteddate. } WorkHoursFields whf = WorkHoursRepository.ConvertToWorkHours(workHoursItem, userObjectIdentifier); Dictionary <string, short> dailyTotals = Helpers.HoursComputeHelper.ComputeDailyTotals(whf); // calculate totals and overtime int totalHours = Convert.ToInt16(dailyTotals["FinalTotalHrs"]); int totalMins = Convert.ToInt16(dailyTotals["FinalTotalMins"]); int dailyGoalHrs = _timeTrackerOptions.DayHours; int dailyGoalMin = 0; int OTHours = 0; int OTMins = 0; if ((totalHours > dailyGoalHrs) || ((totalHours == dailyGoalHrs) && (dailyGoalMin > 0) && (totalMins > dailyGoalMin))) { OTHours = totalHours - dailyGoalHrs; OTMins = totalMins - dailyGoalMin; //TODO: verify -ve values if (OTMins < 0) { OTMins += 60; OTHours--; } } // create analytic record. // Create JSON object to add a new list item in Daily OT Hours list in SharePoint dynamic dailyOTHoursFieldsObject = new JObject(); dailyOTHoursFieldsObject.ObjectIdentifier = userObjectIdentifier; dailyOTHoursFieldsObject.Date = workHoursItem.Properties["Date"].ToString(); dailyOTHoursFieldsObject.TotalHours = totalHours; dailyOTHoursFieldsObject.TotalMins = totalMins; dailyOTHoursFieldsObject.OTHours = OTHours; dailyOTHoursFieldsObject.OTMins = OTMins; dynamic dailyOTHoursRootObject = new JObject(); dailyOTHoursRootObject.fields = dailyOTHoursFieldsObject; var saveResults = await _graphSharePointService.CreateSiteListItemAsync(analyticsSiteList, dailyOTHoursRootObject.ToString()); } } } catch (Exception ex) { _logger.LogError("Error saving team hours in submit: " + ex.Message); throw ex; } return(true); }
// Private methods private async Task <ListCollectionPage <TeamHours> > GetItemsResultsAsync(DateTime date, int pageSize, string searchQuery = "") { try { // Get the user object identifier var userObjectIdentifier = _userContext.User.FindFirst(AzureAdAuthenticationBuilderExtensions.ObjectIdentifierType)?.Value; // Prepare call to graph to fetch teamhours records from SharePoint var listCollectionPage = new ListCollectionPage <TeamHours>(); listCollectionPage.QueryDate = date.ToString("yyyyMM"); listCollectionPage.ObjectIdentifier = userObjectIdentifier; listCollectionPage.CurrentPageIndex = 1; listCollectionPage.PageSize = pageSize; listCollectionPage.SearchQuery = searchQuery; listCollectionPage.SiteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.TeamHoursListSchema); // Get the direct reports of the manager (paged) var directReports = await _graphUserService.GetUserDirectReportsAsync(userObjectIdentifier, String.Empty, pageSize); listCollectionPage.SkipToken = directReports.SkipToken; // Get all Team hours for the date if (_teamHoursDataList?.Count == 0 || _teamHoursDataList[0].Fields.Date != date.ToString("yyyyMM")) { var teamHoursResults = await _graphSharePointService.GetSiteListItemsAsync(listCollectionPage.SiteList, date.ToString("yyyyMM")); foreach (var teamHoursItem in teamHoursResults) { var teamHoursFields = ConvertToTeamHours(teamHoursItem); var userInfo = await _graphUserService.GetUserBasicAsync(teamHoursFields.ObjectIdentifier); teamHoursFields.DisplayName = userInfo.DisplayName ?? ""; _teamHoursDataList.Add(new TeamHours { Id = teamHoursItem.Id, ListId = listCollectionPage.SiteList.ListId, Fields = teamHoursFields }); } } var teamHoursDataList = new List <TeamHours>(); foreach (var item in directReports.DataList) { var teamHoursId = String.Empty; var teamHoursFields = new TeamHoursFields { ObjectIdentifier = item.Id, Date = date.ToString("yyyyMM"), ItemState = ItemState.NotSubmitted, TeamHoursItemState = ItemState.NotSubmitted }; foreach (var teamHoursItem in _teamHoursDataList) { if (teamHoursItem.Fields.ObjectIdentifier == item.Id) { teamHoursId = teamHoursItem.Id; teamHoursFields = teamHoursItem.Fields; } } if (String.IsNullOrEmpty(teamHoursFields.DisplayName)) { var userInfo = await _graphUserService.GetUserBasicAsync(teamHoursFields.ObjectIdentifier); teamHoursFields.DisplayName = userInfo.DisplayName ?? ""; } teamHoursDataList.Add(new TeamHours { Id = teamHoursId, ListId = listCollectionPage.SiteList.ListId, Fields = teamHoursFields }); } listCollectionPage.DataList = teamHoursDataList; return(listCollectionPage); } catch (Exception ex) { _logger.LogError("Error getting team hour items in repository: " + ex.Message); throw; } }
public async Task SubmitHoursAsync(IEnumerable <WorkHours> workHoursToSubmit, string userObjectIdentifier, GraphResultItem managerOfUser, string messageBody = "") { try { if (workHoursToSubmit == null) { throw new ArgumentNullException(nameof(workHoursToSubmit)); } if (((List <WorkHours>)workHoursToSubmit)?.Count == 0) { return; // Nothing to do } if (String.IsNullOrEmpty(userObjectIdentifier)) { return; // Nothing to do } // Try to get the work hours from cache var workHoursListCollectionPage = new ListCollectionPage <WorkHours>(); var dateQuery = workHoursToSubmit.ToList(); // Works for longer Date yyyyMMdd var cacheKey = userObjectIdentifier + dateQuery[0].Fields.Date.Remove(6); var workHoursCacheEntry = await _cacheService.TryRetrieveFromCacheAsync(workHoursListCollectionPage, cacheKey); if (workHoursCacheEntry != null) { workHoursListCollectionPage = workHoursCacheEntry; } var managerObjectIdentifier = managerOfUser.Id ?? ""; var teamHoursSiteList = new SiteList(); if (String.IsNullOrEmpty(managerObjectIdentifier)) { // Skip manager by passing report hours identifier as manager identifier and handling that when building the models for the report by setting the manager display name to blank managerObjectIdentifier = ""; managerOfUser.DisplayName = ""; teamHoursSiteList = await _graphSharePointService.GetSiteListAsync("entries", ListSchema.ReportHoursListSchema); } // Get the SpSiteList, if the list does not exists, it will create one var workHoursSiteList = workHoursListCollectionPage.SiteList; if (String.IsNullOrEmpty(workHoursSiteList.ListId)) { workHoursSiteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.WorkHoursListSchema); } if (!String.IsNullOrEmpty(managerObjectIdentifier)) { teamHoursSiteList = await _graphSharePointService.GetSiteListAsync(managerObjectIdentifier, ListSchema.TeamHoursListSchema); } var teamHoursRow = new TeamHours(); var submittedDate = DateTime.Now; var hasRequestedRevision = false; var tasksList = new List <Task>(); var workHoursDate = DateTime.Now; foreach (var workHours in workHoursToSubmit) { // Only count not submitted and requieres revision if (workHours.Fields.ItemState == ItemState.NotSubmitted || workHours.Fields.ItemState == ItemState.RequiresRevision) { //Update the workHoursDate so we can assamble the message of the notification workHoursDate = DateTime.ParseExact(workHours.Fields.Date, "yyyyMMdd", CultureInfo.InvariantCulture); // To track if there is an entry that has a requiered revision if (!hasRequestedRevision && workHours.Fields.ItemState == ItemState.RequiresRevision) { hasRequestedRevision = true; } teamHoursRow.Fields.Date = workHours.Fields.Date; teamHoursRow.Fields.ObjectIdentifier = workHours.Fields.ObjectIdentifier; teamHoursRow.Fields.MeetingHours += workHours.Fields.MeetingHours; teamHoursRow.Fields.MeetingMinutes += workHours.Fields.MeetingMinutes; if (workHours.Fields.MeetingAdjustedHours != 0 || workHours.Fields.MeetingAdjustedMinutes != 0) { teamHoursRow.Fields.MeetingAdjustedHours += workHours.Fields.MeetingAdjustedHours; teamHoursRow.Fields.MeetingAdjustedMinutes += workHours.Fields.MeetingAdjustedMinutes; } else { teamHoursRow.Fields.MeetingAdjustedHours += workHours.Fields.MeetingHours; teamHoursRow.Fields.MeetingAdjustedMinutes += workHours.Fields.MeetingMinutes; } teamHoursRow.Fields.EmailHours += workHours.Fields.EmailHours; teamHoursRow.Fields.EmailMinutes += workHours.Fields.EmailMinutes; if (workHours.Fields.EmailAdjustedHours != 0 || workHours.Fields.EmailAdjustedMinutes != 0) { teamHoursRow.Fields.EmailAdjustedHours += workHours.Fields.EmailAdjustedHours; teamHoursRow.Fields.EmailAdjustedMinutes += workHours.Fields.EmailAdjustedMinutes; } else { teamHoursRow.Fields.EmailAdjustedHours += workHours.Fields.EmailHours; teamHoursRow.Fields.EmailAdjustedMinutes += workHours.Fields.EmailMinutes; } teamHoursRow.Fields.OtherHours += workHours.Fields.OtherHours; teamHoursRow.Fields.OtherMinutes += workHours.Fields.OtherMinutes; if (workHours.Fields.OtherAdjustedHours != 0 || workHours.Fields.OtherAdjustedMinutes != 0) { teamHoursRow.Fields.OtherAdjustedHours += workHours.Fields.OtherAdjustedHours; teamHoursRow.Fields.OtherAdjustedMinutes += workHours.Fields.OtherAdjustedMinutes; } else { teamHoursRow.Fields.OtherAdjustedHours += workHours.Fields.OtherHours; teamHoursRow.Fields.OtherAdjustedMinutes += workHours.Fields.OtherMinutes; } teamHoursRow.Fields.TeamHoursItemState = ItemState.NotSubmitted; teamHoursRow.Fields.ItemState = ItemState.Submitted; teamHoursRow.Fields.SubmittedDate = submittedDate; // Create JSON object to update WORK HOURS (aka employee entries) in SharePoint dynamic workHoursFieldsObject = new JObject(); if (String.IsNullOrEmpty(managerObjectIdentifier)) { // Skip submit to manager and send to HR since user does not has manager workHoursFieldsObject.TeamHoursItemState = ItemState.Submitted.ToString(); workHoursFieldsObject.TeamHoursSubmittedDate = submittedDate; } workHoursFieldsObject.ItemState = ItemState.Submitted.ToString(); workHoursFieldsObject.SubmittedDate = submittedDate; dynamic workHoursRootObject = new JObject(); workHoursRootObject.fields = workHoursFieldsObject; // Update List Item in WorkHours List await _graphSharePointService.UpdateSiteListItemAsync(workHoursSiteList, workHours.Id, workHoursRootObject.ToString()); } } // Adjust minutes to hours due the sum (above) var timeSpan = new TimeSpan(teamHoursRow.Fields.MeetingHours, teamHoursRow.Fields.MeetingMinutes, 0); teamHoursRow.Fields.MeetingHours = Convert.ToInt16(timeSpan.Hours + (timeSpan.Days * 24)); teamHoursRow.Fields.MeetingMinutes = Convert.ToInt16(timeSpan.Minutes); timeSpan = new TimeSpan(teamHoursRow.Fields.MeetingAdjustedHours, teamHoursRow.Fields.MeetingAdjustedMinutes, 0); teamHoursRow.Fields.MeetingAdjustedHours = Convert.ToInt16(timeSpan.Hours + (timeSpan.Days * 24)); teamHoursRow.Fields.MeetingAdjustedMinutes = Convert.ToInt16(timeSpan.Minutes); timeSpan = new TimeSpan(teamHoursRow.Fields.EmailHours, teamHoursRow.Fields.EmailMinutes, 0); teamHoursRow.Fields.EmailHours = Convert.ToInt16(timeSpan.Hours + (timeSpan.Days * 24)); teamHoursRow.Fields.EmailMinutes = Convert.ToInt16(timeSpan.Minutes); timeSpan = new TimeSpan(teamHoursRow.Fields.EmailAdjustedHours, teamHoursRow.Fields.EmailAdjustedMinutes, 0); teamHoursRow.Fields.EmailAdjustedHours = Convert.ToInt16(timeSpan.Hours + (timeSpan.Days * 24)); teamHoursRow.Fields.EmailAdjustedMinutes = Convert.ToInt16(timeSpan.Minutes); timeSpan = new TimeSpan(teamHoursRow.Fields.OtherHours, teamHoursRow.Fields.OtherMinutes, 0); teamHoursRow.Fields.OtherHours = Convert.ToInt16(timeSpan.Hours + (timeSpan.Days * 24)); teamHoursRow.Fields.OtherMinutes = Convert.ToInt16(timeSpan.Minutes); timeSpan = new TimeSpan(teamHoursRow.Fields.OtherAdjustedHours, teamHoursRow.Fields.OtherAdjustedMinutes, 0); teamHoursRow.Fields.OtherAdjustedHours = Convert.ToInt16(timeSpan.Hours + (timeSpan.Days * 24)); teamHoursRow.Fields.OtherAdjustedMinutes = Convert.ToInt16(timeSpan.Minutes); // Create JSON object to add a new list item in team Hours list in SharePoint dynamic teamHoursFieldsObject = new JObject(); teamHoursFieldsObject.ObjectIdentifier = teamHoursRow.Fields.ObjectIdentifier; teamHoursFieldsObject.Date = teamHoursRow.Fields.Date; teamHoursFieldsObject.MeetingHours = teamHoursRow.Fields.MeetingHours; teamHoursFieldsObject.MeetingMinutes = teamHoursRow.Fields.MeetingMinutes; teamHoursFieldsObject.MeetingAdjustedHours = teamHoursRow.Fields.MeetingAdjustedHours; teamHoursFieldsObject.MeetingAdjustedMinutes = teamHoursRow.Fields.MeetingAdjustedMinutes; teamHoursFieldsObject.EmailHours = teamHoursRow.Fields.EmailHours; teamHoursFieldsObject.EmailMinutes = teamHoursRow.Fields.EmailMinutes; teamHoursFieldsObject.EmailAdjustedHours = teamHoursRow.Fields.EmailAdjustedHours; teamHoursFieldsObject.EmailAdjustedMinutes = teamHoursRow.Fields.EmailAdjustedMinutes; teamHoursFieldsObject.OtherHours = teamHoursRow.Fields.OtherHours; teamHoursFieldsObject.OtherMinutes = teamHoursRow.Fields.OtherMinutes; teamHoursFieldsObject.OtherAdjustedHours = teamHoursRow.Fields.OtherAdjustedHours; teamHoursFieldsObject.OtherAdjustedMinutes = teamHoursRow.Fields.OtherAdjustedMinutes; teamHoursFieldsObject.AdjustedHoursReason = "" + teamHoursRow.Fields.AdjustedHoursReason; if (String.IsNullOrEmpty(managerObjectIdentifier)) { // Skip submit to manager and send to HR since user does not has manager teamHoursFieldsObject.TeamHoursItemState = ItemState.Submitted.ToString(); teamHoursFieldsObject.TeamHoursSubmittedDate = submittedDate; } else { teamHoursFieldsObject.TeamHoursItemState = teamHoursRow.Fields.TeamHoursItemState.ToString(); } teamHoursFieldsObject.ItemState = teamHoursRow.Fields.ItemState.ToString(); teamHoursFieldsObject.SubmittedDate = teamHoursRow.Fields.SubmittedDate; dynamic teamHoursRootObject = new JObject(); teamHoursRootObject.fields = teamHoursFieldsObject; // If submit is not due to a request revision, create team hours entry otherwise we only update the existing one if (hasRequestedRevision) { // Update existing team hours entry (this is the case for requesting revision) List <QueryOption> options = new List <QueryOption>(); options.Add(new QueryOption("filter", @"startswith(fields/Date,'" + teamHoursRow.Fields.Date + "') and startswith(fields/ObjectIdentifier,'" + teamHoursRow.Fields.ObjectIdentifier + "')")); var teamHoursResults = await _graphSharePointService.GetSiteListItemsAsync(teamHoursSiteList, options); var updateResults = await _graphSharePointService.UpdateSiteListItemAsync(teamHoursSiteList, teamHoursResults[0].Id, teamHoursRootObject.ToString()); } else { // Create List Item in TeamHours list var createResults = await _graphSharePointService.CreateSiteListItemAsync(teamHoursSiteList, teamHoursRootObject.ToString()); } // Create notification and send email //var messageBody = _workflowServiceHelper.ComposeMessageBody(NotificationType.SubmitWorkHours, workHoursDate); await _workflowServiceHelper.SendNotificationAsync(managerOfUser, NotificationType.SubmitWorkHours, messageBody); // Clear te cache await _cacheService.ClearCacheAsync(cacheKey); } catch (Exception ex) { _logger.LogError("Error submitting work hours in workflow: " + ex.Message); } }
public async Task SubmitHoursAsync(IEnumerable <TeamHours> teamHoursToSubmit, string messageBody = "") { try { if (teamHoursToSubmit == null) { throw new ArgumentNullException(nameof(teamHoursToSubmit)); } var hoursToSubmit = teamHoursToSubmit.ToList(); if (hoursToSubmit?.Count == 0) { return; // Nothing to do } // Get the Team hours site list for current user, if the list does not exists, it will create one var userProfile = await _userProfileRepository.GetItemAsync(); var managerObjectIdentifier = userProfile.Id; var teamHoursSiteList = await _graphSharePointService.GetSiteListAsync(managerObjectIdentifier, ListSchema.TeamHoursListSchema); var reportHoursSiteList = await _graphSharePointService.GetSiteListAsync(_reportHoursListIdentifier, ListSchema.ReportHoursListSchema); // Try fetching the data from cache var dateKey = hoursToSubmit[0].Fields.Date.ToString(); var cacheKey = managerObjectIdentifier + dateKey; await _cacheService.ClearCacheAsync(cacheKey); var teamHoursSubmitList = teamHoursToSubmit.ToList(); var submittedDate = DateTime.Now; var teamHoursDate = DateTime.Now; foreach (var item in teamHoursToSubmit) { // Hours Submitted, but NO HR Report. //if (item.Fields.TeamHoursItemState == ItemState.NotSubmitted || item.Fields.TeamHoursItemState == ItemState.RequiresRevision) if (item.Fields.TeamHoursItemState == ItemState.NotSubmitted && item.Fields.ItemState == ItemState.Submitted) { // Update teamHoursDate with last date value which is used in the notificationn message body // Date contains a string! yyyyMMdd teamHoursDate = DateTime.ParseExact(item.Fields.Date, "yyyyMMdd", CultureInfo.InvariantCulture); // Create JSON object to update Team Hours in SharePoint dynamic teamHoursFieldsObject = new JObject(); teamHoursFieldsObject.TeamHoursItemState = ItemState.Submitted.ToString(); teamHoursFieldsObject.TeamHoursSubmittedDate = submittedDate; dynamic teamHoursRootObject = new JObject(); teamHoursRootObject.fields = teamHoursFieldsObject; // Create JSON object to create entries in Report Hours in SharePoint dynamic reportHoursFieldsObject = new JObject(); reportHoursFieldsObject.ObjectIdentifier = item.Fields.ObjectIdentifier; reportHoursFieldsObject.ManagerObjectIdentifier = managerObjectIdentifier; reportHoursFieldsObject.Date = item.Fields.Date; reportHoursFieldsObject.TeamHoursItemState = ItemState.Submitted.ToString(); reportHoursFieldsObject.TeamHoursSubmittedDate = submittedDate; reportHoursFieldsObject.ItemState = item.Fields.ItemState.ToString(); reportHoursFieldsObject.SubmittedDate = item.Fields.SubmittedDate; dynamic reportHoursRootObject = new JObject(); reportHoursRootObject.fields = reportHoursFieldsObject; // Update the team hours entry in SharePoint await _graphSharePointService.UpdateSiteListItemAsync(teamHoursSiteList, item.Id, teamHoursRootObject.ToString()); // Create List Item in ReportHours List var createResult = await _graphSharePointService.CreateSiteListItemAsync(reportHoursSiteList, reportHoursRootObject.ToString()); // Get work hours list for this teamHours entry and update the TeamHoursItemState var workHoursSiteList = await _graphSharePointService.GetSiteListAsync(item.Fields.ObjectIdentifier, ListSchema.WorkHoursListSchema); // Works for longer yyyyMMdd date. var dateQuery = item.Fields.Date.Remove(6); var workHoursResult = await _graphSharePointService.GetSiteListItemsAsync(workHoursSiteList, dateQuery); if (workHoursResult?.Count == 0) { throw new ServiceException(new Error { Code = ErrorConstants.Codes.InvalidRequest, Message = "Can't retrieve work hours for a team hours entry" }); } foreach (var workHoursItem in workHoursResult) { // Create JSON object to update Work Hours list in SharePoint dynamic workHoursFieldsObject = new JObject(); workHoursFieldsObject.TeamHoursItemState = ItemState.Submitted.ToString(); workHoursFieldsObject.TeamHoursSubmittedDate = submittedDate; dynamic workHoursRootObject = new JObject(); workHoursRootObject.fields = workHoursFieldsObject; // Update List Item in WorkHours List // var updateResult = await _graphSharePointService.UpdateSiteListItemAsync(workHoursSiteList, workHoursItem.Id, workHoursRootObject.ToString()); await _graphSharePointService.UpdateSiteListItemAsync(workHoursSiteList, workHoursItem.Id, workHoursRootObject.ToString()); } } } // Create notification and send email var sendToObject = new GraphResultItem { Id = _hrListIdentifier, Properties = new Dictionary <string, object> { { "Mail", _timeTrackerOptions.HrNotificationMail }, } }; // Send notification //var messageBody = _workflowServiceHelper.ComposeMessageBody(NotificationType.SubmitTeamHours, teamHoursDate); await _workflowServiceHelper.SendNotificationAsync(sendToObject, NotificationType.SubmitTeamHours, messageBody); } catch (Exception ex) { _logger.LogError("Error saving team hours in submit: " + ex.Message); throw ex; } }
public async Task SaveItemAsync(Notifications modelData) { try { if (modelData == null) { throw new ArgumentNullException(nameof(modelData)); } var notificationsList = new List <Notifications>(); var notificationListCollectionPage = new ListCollectionPage <Notifications>(); var userProfile = await _userProfileRepository.GetItemAsync(); var userObjectIdentifier = userProfile.Id; var hrSiteListId = _timeTrackerOptions.NotificationsListPrefix + _hrListIdentifier; // Try to get the work hours from cache var cacheKey = userObjectIdentifier; var notificationsListEntry = await _memoryCacheService.TryRetrieveFromCacheAsync(notificationListCollectionPage, cacheKey); if (notificationsListEntry != null) { notificationsList = notificationsListEntry.DataList.ToList(); notificationListCollectionPage = notificationsListEntry; // remove from cache so it can be updated and saved back in cache await _memoryCacheService.RemoveFromCacheAsync(cacheKey); // Find in the entries from cache the item to update then save it back to cache var cacheUpdated = false; foreach (var item in notificationsList) { if (item.Id == modelData.Id && item.ListId == modelData.ListId) { if (modelData.Fields.SentDate != null) { item.Fields.SentDate = modelData.Fields.SentDate; } if (modelData.Fields.ReadDate != null && !String.IsNullOrEmpty(modelData.Id)) { item.Fields.ReadDate = modelData.Fields.ReadDate; } cacheUpdated = true; } } // Save the entry back to cache if (cacheUpdated) { notificationListCollectionPage.DataList = notificationsList; await _memoryCacheService.SaveToCacheAsync(notificationListCollectionPage, cacheKey); } } // Get the SpSiteList, if the list does not exists, it will create one if (String.IsNullOrEmpty(notificationListCollectionPage.SiteList.ListId)) { notificationListCollectionPage.SiteList = await _graphSharePointService.GetSiteListAsync(userObjectIdentifier, ListSchema.NotificationsListSchema); } var notificationsSiteList = notificationListCollectionPage.SiteList; if (modelData.ListId == hrSiteListId) { notificationsSiteList.ListId = modelData.ListId; // Change ListId if shared notifications in box (for HR) } // Add relevant properties to cache entry if (String.IsNullOrEmpty(notificationListCollectionPage.ObjectIdentifier)) { notificationListCollectionPage.ObjectIdentifier = userObjectIdentifier; } // Create JSON object to update or create WORK HOURS (aka employee entries) in SharePoint dynamic notificationsFieldsObject = new JObject(); notificationsFieldsObject.SentToMail = modelData.Fields.SentToMail; if (modelData.Fields.SentDate != null) { notificationsFieldsObject.SentDate = modelData.Fields.SentDate; } if (modelData.Fields.ReadDate != null && !String.IsNullOrEmpty(modelData.Id)) { notificationsFieldsObject.ReadDate = modelData.Fields.ReadDate; } notificationsFieldsObject.MessageBody = modelData.Fields.MessageBody ?? ""; dynamic notificationsRootObject = new JObject(); notificationsRootObject.fields = notificationsFieldsObject; // If Id empty we assume new notification: note creating via this methd does not trigger sending emails, that is part of workflow service helper if (String.IsNullOrEmpty(modelData.Id)) { // Add new notification in SharePoint var result = await _graphSharePointService.CreateSiteListItemAsync(notificationsSiteList, notificationsRootObject.ToString()); } else { // Update an existing notification var result = await _graphSharePointService.UpdateSiteListItemAsync(notificationsSiteList, modelData.Id, notificationsRootObject.ToString()); } } catch (Exception ex) { _logger.LogError("Error saving notifiction items in repository: " + ex.Message); throw; } }