/// <summary> /// Generate a Teams open shift entity. /// </summary> /// <param name="kronosOpenShift">the Kronos open shift object.</param> /// <param name="mappedOrgJobEntity">The team details.</param> /// <returns>An open shift request model.</returns> private OpenShiftRequestModel GenerateTeamsOpenShiftEntity(OpenShiftBatch.ScheduleShift kronosOpenShift, TeamToDepartmentJobMappingEntity mappedOrgJobEntity) { var openShiftActivity = new List <Activity>(); // This foreach loop will build the OpenShift activities. foreach (var segment in kronosOpenShift.ShiftSegments.ShiftSegment) { openShiftActivity.Add(new Activity { IsPaid = true, StartDateTime = this.utility.CalculateStartDateTime(segment, mappedOrgJobEntity.KronosTimeZone), EndDateTime = this.utility.CalculateEndDateTime(segment, mappedOrgJobEntity.KronosTimeZone), Code = string.Empty, DisplayName = segment.SegmentTypeName, }); } var openShift = new OpenShiftRequestModel() { SchedulingGroupId = mappedOrgJobEntity.TeamsScheduleGroupId, SharedOpenShift = new OpenShiftItem { DisplayName = string.Empty, OpenSlotCount = Constants.ShiftsOpenSlotCount, Notes = this.utility.GetOpenShiftNotes(kronosOpenShift), StartDateTime = openShiftActivity.First().StartDateTime, EndDateTime = openShiftActivity.Last().EndDateTime, Theme = this.appSettings.OpenShiftTheme, Activities = openShiftActivity, }, }; // Generates the uniqueId for the OpenShift. openShift.KronosUniqueId = this.utility.CreateUniqueId(openShift, mappedOrgJobEntity); return(openShift); }
/// <summary> /// Get the list of time off details from Kronos and push it to Shifts. /// </summary> /// <param name="isRequestFromLogicApp">Checks if request is coming from logic app or portal.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> internal async Task ProcessOpenShiftsAsync(string isRequestFromLogicApp) { this.telemetryClient.TrackTrace($"{Resource.ProcessOpenShiftsAsync} started at: {DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)} for isRequestFromLogicApp: {isRequestFromLogicApp}"); if (isRequestFromLogicApp == null) { throw new ArgumentNullException(nameof(isRequestFromLogicApp)); } var allRequiredConfigurations = await this.utility.GetAllConfigurationsAsync().ConfigureAwait(false); this.utility.SetQuerySpan(Convert.ToBoolean(isRequestFromLogicApp, CultureInfo.InvariantCulture), out var openShiftStartDate, out var openShiftEndDate); // Check whether date range are in correct format. var isCorrectDateRange = Utility.CheckDates(openShiftStartDate, openShiftEndDate); if (allRequiredConfigurations != null && (bool)allRequiredConfigurations?.IsAllSetUpExists && isCorrectDateRange) { var monthPartitions = Utility.GetMonthPartition(openShiftStartDate, openShiftEndDate); // Adding the telemetry properties. var telemetryProps = new Dictionary <string, string>() { { "MethodName", Resource.ProcessOpenShiftsAsync }, { "CallingAssembly", Assembly.GetCallingAssembly().GetName().Name }, }; var processNumberOfOrgJobsInBatch = this.appSettings.ProcessNumberOfOrgJobsInBatch; var orgJobPaths = await this.teamDepartmentMappingProvider.GetAllOrgJobPathsAsync().ConfigureAwait(false); var mappedTeams = await this.teamDepartmentMappingProvider.GetMappedTeamToDeptsWithJobPathsAsync().ConfigureAwait(false); var orgJobsCount = orgJobPaths.Count; int orgJobPathIterations = Utility.GetIterablesCount(Convert.ToInt32(processNumberOfOrgJobsInBatch, CultureInfo.InvariantCulture), orgJobsCount); if (monthPartitions != null && monthPartitions.Count > 0) { // The monthPartitions is a list of strings which are formatted as: MM_YYYY where // MM represents the integer representation of the month, and YYYY is the integer // representation of the year. (i.e. December 2019 = 12_2019) - the month partitions // are used when the data synced from Kronos is over a wide duration. foreach (var monthPartitionKey in monthPartitions) { if (monthPartitionKey != null) { this.telemetryClient.TrackTrace($"Processing data for the month partition: {monthPartitionKey} at {DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)}"); Utility.GetNextDateSpan( monthPartitionKey, monthPartitions.FirstOrDefault(), monthPartitions.LastOrDefault(), openShiftStartDate, openShiftEndDate, out string queryStartDate, out string queryEndDate); // Add to queue var processKronosOrgJobsQueue = new Queue <string>(orgJobPaths); // This for loop will iterate over the number of batches of Org Job Paths. for (int batchedOpenShiftCount = 0; batchedOpenShiftCount < orgJobPathIterations; batchedOpenShiftCount++) { this.telemetryClient.TrackTrace($"OpenShiftController - Processing on iteration number: {batchedOpenShiftCount}"); var processKronosOrgJobsQueueInBatch = processKronosOrgJobsQueue?.Skip(Convert.ToInt32(processNumberOfOrgJobsInBatch, CultureInfo.InvariantCulture) * batchedOpenShiftCount).Take(Convert.ToInt32(processNumberOfOrgJobsInBatch, CultureInfo.InvariantCulture)); // Get the response for a batch of org job paths. var openShiftsResponse = await this.GetOpenShiftResultsByOrgJobPathInBatchAsync( allRequiredConfigurations.WFIId, allRequiredConfigurations.WfmEndPoint, allRequiredConfigurations.KronosSession, processKronosOrgJobsQueueInBatch.ToList(), queryStartDate, queryEndDate).ConfigureAwait(false); var openShiftDisplayName = string.Empty; var openShiftNotes = string.Empty; var openShiftTheme = this.appSettings.OpenShiftTheme; if (openShiftsResponse != null) { // This foreach loop will iterate through a list of orgJobPaths. // Each orgJobPath in Kronos corresponds to a Scheduling Group // in Shifts. foreach (var orgJob in processKronosOrgJobsQueueInBatch) { this.telemetryClient.TrackTrace($"OpenShiftController - Processing the org job path: {orgJob}"); // Open Shift models for Create/Update operation var lookUpEntriesFoundList = new List <AllOpenShiftMappingEntity>(); var openShiftsNotFoundList = new List <OpenShiftRequestModel>(); var mappedTeam = mappedTeams?.FirstOrDefault(x => x.PartitionKey == allRequiredConfigurations.WFIId && x.RowKey == Utility.OrgJobPathDBConversion(orgJob)); // Retrieve lookUpData for the open shift entity. var lookUpData = await this.openShiftMappingEntityProvider.GetAllOpenShiftMappingEntitiesInBatch( monthPartitionKey, mappedTeam?.TeamsScheduleGroupId).ConfigureAwait(false); if (lookUpData != null) { // This foreach loop will process the openShiftSchedule item(s) that belong to a specific Kronos Org Job Path. foreach (var openShiftSchedule in openShiftsResponse?.Schedules.Where(x => x.OrgJobPath == orgJob)) { this.telemetryClient.TrackTrace($"OpenShiftController - Processing the Open Shift schedule for: {openShiftSchedule.OrgJobPath}, and date range: {openShiftSchedule.QueryDateSpan}"); var scheduleShiftCount = (int)openShiftSchedule.ScheduleItems?.ScheduleShifts?.Count; if (scheduleShiftCount > 0) { if (mappedTeam != null) { this.telemetryClient.TrackTrace($"OpenShiftController - Processing Open Shifts for the mapped team: {mappedTeam.ShiftsTeamName}"); // This foreach builds the Open Shift object to push to Shifts via Graph API. foreach (var scheduleShift in openShiftSchedule?.ScheduleItems?.ScheduleShifts) { var shiftSegmentCount = scheduleShift.ShiftSegments; this.telemetryClient.TrackTrace($"OpenShiftController - Processing {scheduleShift.StartDate} with {shiftSegmentCount} segments."); var openShiftActivity = new List <Activity>(); // This foreach loop will build the OpenShift activities. foreach (var segment in scheduleShift.ShiftSegments.ShiftSegment) { openShiftActivity.Add(new Activity { IsPaid = true, StartDateTime = this.utility.CalculateStartDateTime(segment), EndDateTime = this.utility.CalculateEndDateTime(segment), Code = string.Empty, DisplayName = segment.SegmentTypeName, }); } var shift = new OpenShiftRequestModel() { SchedulingGroupId = mappedTeam.TeamsScheduleGroupId, SharedOpenShift = new OpenShiftItem { DisplayName = string.Empty, OpenSlotCount = Constants.ShiftsOpenSlotCount, Notes = this.utility.GetOpenShiftNotes(scheduleShift), StartDateTime = openShiftActivity.First().StartDateTime, EndDateTime = openShiftActivity.Last().EndDateTime, Theme = openShiftTheme, Activities = openShiftActivity, }, }; // Generates the uniqueId for the OpenShift. shift.KronosUniqueId = this.utility.CreateUniqueId(shift, shift.SchedulingGroupId); // Logging the output of the KronosHash creation. this.telemetryClient.TrackTrace("OpenShiftController-KronosHash: " + shift.KronosUniqueId); if (lookUpData.Count == 0) { this.telemetryClient.TrackTrace($"OpenShiftController - Adding {shift.KronosUniqueId} to the openShiftsNotFoundList as the lookUpData count = 0"); openShiftsNotFoundList.Add(shift); } else { var kronosUniqueIdExists = lookUpData.Where(c => c.RowKey == shift.KronosUniqueId); if ((kronosUniqueIdExists != default(List <AllOpenShiftMappingEntity>)) && kronosUniqueIdExists.Any()) { this.telemetryClient.TrackTrace($"OpenShiftController - Adding {kronosUniqueIdExists.FirstOrDefault().RowKey} to the lookUpEntriesFoundList as there is data in the lookUpData list."); lookUpEntriesFoundList.Add(kronosUniqueIdExists.FirstOrDefault()); } else { this.telemetryClient.TrackTrace($"OpenShiftController - Adding {shift.KronosUniqueId} to the openShiftsNotFoundList."); openShiftsNotFoundList.Add(shift); } } } } else { telemetryProps.Add("MappedTeamStatus", $"There is no mappedTeam found with WFI ID: {allRequiredConfigurations.WFIId}"); this.telemetryClient.TrackTrace(Resource.SyncOpenShiftsFromKronos, telemetryProps); continue; } } else { this.telemetryClient.TrackTrace($"ScheduleShiftCount - {scheduleShiftCount} for {openShiftSchedule.OrgJobPath}"); continue; } } if (lookUpData.Except(lookUpEntriesFoundList).Any()) { this.telemetryClient.TrackTrace($"OpenShiftController - The lookUpEntriesFoundList has {lookUpEntriesFoundList.Count} items which could be deleted"); await this.DeleteOrphanDataOpenShiftsEntityMappingAsync(allRequiredConfigurations.ShiftsAccessToken, lookUpEntriesFoundList, lookUpData, mappedTeam).ConfigureAwait(false); } if (openShiftsNotFoundList.Count > 0) { this.telemetryClient.TrackTrace($"OpenShiftController - The openShiftsNotFoundList has {openShiftsNotFoundList.Count} items which could be added."); await this.CreateEntryOpenShiftsEntityMappingAsync(allRequiredConfigurations.ShiftsAccessToken, openShiftsNotFoundList, monthPartitionKey, mappedTeam).ConfigureAwait(false); } } else { this.telemetryClient.TrackTrace($"{Resource.SyncOpenShiftsFromKronos} - There is no lookup data present with the schedulingGroupId: " + mappedTeam?.TeamsScheduleGroupId); continue; } } } } } else { this.telemetryClient.TrackTrace($"{Resource.MonthPartitionKeyStatus} - MonthPartitionKey cannot be found please check the data."); this.telemetryClient.TrackTrace(Resource.SyncOpenShiftsFromKronos, telemetryProps); continue; } } } else { telemetryProps.Add("MonthPartitionsStatus", "There are no month partitions found!"); } } else { throw new Exception($"{Resource.SyncOpenShiftsFromKronos} - {Resource.SetUpNotDoneMessage}"); } this.telemetryClient.TrackTrace($"{Resource.ProcessOpenShiftsAsync} ended at: {DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)} for isRequestFromLogicApp: {isRequestFromLogicApp}"); }