예제 #1
0
        /// <summary>
        /// Method to delete an orphan shift - happens when a shift is deleted from Kronos.
        /// </summary>
        /// <param name="configurationDetails">The configuration details.</param>
        /// <param name="lookUpDataFoundList">The list of data that has been found.</param>
        /// <param name="userModelList">The list of users.</param>
        /// <param name="lookUpData">The Shifts look up data.</param>
        /// <returns>A unit of execution.</returns>
        private async Task DeleteOrphanDataShiftsEntityMappingAsync(
            IntegrationApi.SetupDetails configurationDetails,
            List <TeamsShiftMappingEntity> lookUpDataFoundList,
            List <UserDetailsModel> userModelList,
            List <TeamsShiftMappingEntity> lookUpData)
        {
            // Delete entries from orphan list
            var orphanList = lookUpData.Except(lookUpDataFoundList);

            // Iterating over each item in the orphanList.
            foreach (var item in orphanList)
            {
                var user = userModelList.FirstOrDefault(u => u.KronosPersonNumber == item.KronosPersonNumber);

                if (user == null)
                {
                    return;
                }

                var httpClient = this.httpClientFactory.CreateClient("ShiftsAPI");
                httpClient.DefaultRequestHeaders.Add("X-MS-WFMPassthrough", configurationDetails.WFIId);

                // If the shift mapping doesnt have a teamId take the users teamId
                var teamId = string.IsNullOrEmpty(item.ShiftsTeamId) ? user.ShiftTeamId : item.ShiftsTeamId;

                var requestUrl = $"teams/{teamId}/schedule/shifts/{item.RowKey}";

                var response = await this.graphUtility.SendHttpRequest(configurationDetails.GraphConfigurationDetails, httpClient, HttpMethod.Delete, requestUrl).ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                {
                    var successfulDeleteProps = new Dictionary <string, string>()
                    {
                        { "ResponseCode", response.StatusCode.ToString() },
                        { "ResponseHeader", response.Headers.ToString() },
                    };

                    this.telemetryClient.TrackTrace(MethodBase.GetCurrentMethod().Name, successfulDeleteProps);

                    await this.shiftMappingEntityProvider.DeleteOrphanDataFromShiftMappingAsync(item).ConfigureAwait(false);
                }
                else
                {
                    var errorDeleteProps = new Dictionary <string, string>()
                    {
                        { "ResponseCode", response.StatusCode.ToString() },
                        { "ResponseHeader", response.Headers.ToString() },
                    };

                    this.telemetryClient.TrackTrace(MethodBase.GetCurrentMethod().Name, errorDeleteProps);
                }
            }
        }
        /// <summary>
        /// Method to delete an orphan shift - happens when a shift is deleted from Kronos.
        /// </summary>
        /// <param name="configurationDetails">The configuration details.</param>
        /// <param name="lookUpDataFoundList">The list of data that has been found.</param>
        /// <param name="userModelList">The list of users.</param>
        /// <param name="lookUpData">The Shifts look up data.</param>
        /// <returns>A unit of execution.</returns>
        private async Task DeleteOrphanDataShiftsEntityMappingAsync(
            IntegrationApi.SetupDetails configurationDetails,
            List <TeamsShiftMappingEntity> lookUpDataFoundList,
            List <UserDetailsModel> userModelList,
            List <TeamsShiftMappingEntity> lookUpData)
        {
            // Delete entries from orphan list
            var orphanList = lookUpData.Except(lookUpDataFoundList);

            // Iterating over each item in the orphanList.
            foreach (var item in orphanList)
            {
                var user       = userModelList.FirstOrDefault(u => u.KronosPersonNumber == item.KronosPersonNumber);
                var httpClient = this.httpClientFactory.CreateClient("ShiftsAPI");
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", configurationDetails.ShiftsAccessToken);
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                if (user != null)
                {
                    using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Delete, $"teams/{user.ShiftTeamId}/schedule/shifts/{item.RowKey}"))
                    {
                        var response = await httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false);

                        if (response.IsSuccessStatusCode)
                        {
                            var successfulDeleteProps = new Dictionary <string, string>()
                            {
                                { "ResponseCode", response.StatusCode.ToString() },
                                { "ResponseHeader", response.Headers.ToString() },
                            };

                            this.telemetryClient.TrackTrace(MethodBase.GetCurrentMethod().Name, successfulDeleteProps);

                            await this.shiftMappingEntityProvider.DeleteOrphanDataFromShiftMappingAsync(item).ConfigureAwait(false);
                        }
                        else
                        {
                            var errorDeleteProps = new Dictionary <string, string>()
                            {
                                { "ResponseCode", response.StatusCode.ToString() },
                                { "ResponseHeader", response.Headers.ToString() },
                            };

                            this.telemetryClient.TrackTrace(MethodBase.GetCurrentMethod().Name, errorDeleteProps);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Method that will create the new Shifts Entity Mapping.
        /// </summary>
        /// <param name="configurationDetails">The configuration details.</param>
        /// <param name="userModelNotFoundList">The list of users that have not been found.</param>
        /// <param name="notFoundShifts">The shifts which have not been found.</param>
        /// <param name="monthPartitionKey">The monthwise partition key.</param>
        /// <returns>A unit of execution.</returns>
        private async Task CreateEntryShiftsEntityMappingAsync(
            IntegrationApi.SetupDetails configurationDetails,
            List <UserDetailsModel> userModelNotFoundList,
            List <Shift> notFoundShifts,
            string monthPartitionKey)
        {
            // create entries from not found list
            for (int i = 0; i < notFoundShifts.Count; i++)
            {
                var requestString = JsonConvert.SerializeObject(notFoundShifts[i]);

                var httpClient = this.httpClientFactory.CreateClient("ShiftsAPI");
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", configurationDetails.ShiftsAccessToken);
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "teams/" + userModelNotFoundList[i].ShiftTeamId + "/schedule/shifts")
                {
                    Content = new StringContent(requestString, Encoding.UTF8, "application/json"),
                })
                {
                    var response = await httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false);

                    if (response.IsSuccessStatusCode)
                    {
                        var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                        var shiftResponse      = JsonConvert.DeserializeObject <Models.Response.Shifts.Shift>(responseContent);
                        var shiftId            = shiftResponse.Id;
                        var shiftMappingEntity = this.CreateNewShiftMappingEntity(shiftResponse, notFoundShifts[i].KronosUniqueId, userModelNotFoundList[i]);
                        await this.shiftMappingEntityProvider.SaveOrUpdateShiftMappingEntityAsync(shiftMappingEntity, shiftId, monthPartitionKey).ConfigureAwait(false);

                        continue;
                    }
                    else
                    {
                        var errorProps = new Dictionary <string, string>()
                        {
                            { "ResultCode", response.StatusCode.ToString() },
                            { "IntegerResult", Convert.ToInt32(response.StatusCode, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture) },
                        };

                        // Have the log to capture the 403.
                        this.telemetryClient.TrackTrace(MethodBase.GetCurrentMethod().Name, errorProps);
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Method that will create the new Shifts Entity Mapping.
        /// </summary>
        /// <param name="configurationDetails">The configuration details.</param>
        /// <param name="userModelNotFoundList">The list of users that have not been found.</param>
        /// <param name="notFoundShifts">The shifts which have not been found.</param>
        /// <param name="monthPartitionKey">The monthwise partition key.</param>
        /// <returns>A unit of execution.</returns>
        private async Task CreateEntryShiftsEntityMappingAsync(
            IntegrationApi.SetupDetails configurationDetails,
            List <UserDetailsModel> userModelNotFoundList,
            List <Shift> notFoundShifts,
            string monthPartitionKey)
        {
            // create entries from not found list
            for (int i = 0; i < notFoundShifts.Count; i++)
            {
                var httpClient = this.httpClientFactory.CreateClient("ShiftsAPI");
                httpClient.DefaultRequestHeaders.Add("X-MS-WFMPassthrough", configurationDetails.WFIId);

                var requestUrl    = $"teams/{userModelNotFoundList[i].ShiftTeamId}/schedule/shifts";
                var requestString = JsonConvert.SerializeObject(notFoundShifts[i]);

                var response = await this.graphUtility.SendHttpRequest(configurationDetails.GraphConfigurationDetails, httpClient, HttpMethod.Post, requestUrl, requestString).ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                    var shiftResponse      = JsonConvert.DeserializeObject <Models.Response.Shifts.Shift>(responseContent);
                    var shiftId            = shiftResponse.Id;
                    var shiftMappingEntity = this.CreateNewShiftMappingEntity(shiftResponse, notFoundShifts[i].KronosUniqueId, userModelNotFoundList[i]);
                    await this.shiftMappingEntityProvider.SaveOrUpdateShiftMappingEntityAsync(shiftMappingEntity, shiftId, monthPartitionKey).ConfigureAwait(false);

                    continue;
                }
                else
                {
                    var errorProps = new Dictionary <string, string>()
                    {
                        { "ResultCode", response.StatusCode.ToString() },
                        { "IntegerResult", Convert.ToInt32(response.StatusCode, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture) },
                    };

                    // Have the log to capture the 403.
                    this.telemetryClient.TrackTrace(MethodBase.GetCurrentMethod().Name, errorProps);
                }
            }
        }
        /// <summary>
        /// Method to process the shift entities in a batch manner.
        /// </summary>
        /// <param name="configurationDetails">The configuration details.</param>
        /// <param name="lookUpEntriesFoundList">The lookUp entries that have been found.</param>
        /// <param name="shiftsNotFoundList">The shifts that have not been found.</param>
        /// <param name="userModelList">The users list.</param>
        /// <param name="userModelNotFoundList">The list of users that have not been found.</param>
        /// <param name="lookUpData">The look up data from the Shift Entity Mapping table.</param>
        /// <param name="processKronosUsersQueueInBatch">The Kronos users in the queue.</param>
        /// <param name="shiftsResponse">The Shifts Response from MS Graph.</param>
        /// <param name="monthPartitionKey">The monthwise partition.</param>
        /// <returns>A unit of execution.</returns>
        private async Task ProcessShiftEntitiesBatchAsync(
            IntegrationApi.SetupDetails configurationDetails,
            List <TeamsShiftMappingEntity> lookUpEntriesFoundList,
            List <Shift> shiftsNotFoundList,
            List <UserDetailsModel> userModelList,
            List <UserDetailsModel> userModelNotFoundList,
            List <TeamsShiftMappingEntity> lookUpData,
            IEnumerable <UserDetailsModel> processKronosUsersQueueInBatch,
            App.KronosWfc.Models.ResponseEntities.Shifts.UpcomingShifts.Response shiftsResponse,
            string monthPartitionKey)
        {
            this.telemetryClient.TrackTrace($"ShiftController - ProcessShiftEntitiesBatchAsync started at: {DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)}");
            var shiftNotes = string.Empty;

            // This foreach loop processes each user in the batch.
            foreach (var user in processKronosUsersQueueInBatch)
            {
                // This foreach loop will process the shift(s) that belong to each user.
                foreach (var kronosShift in shiftsResponse?.Schedule?.ScheduleItems?.ScheduleShift)
                {
                    if (user.KronosPersonNumber == kronosShift.Employee.FirstOrDefault().PersonNumber)
                    {
                        this.telemetryClient.TrackTrace($"ShiftController - Processing the shifts for user: {user.KronosPersonNumber}");

                        var shift = this.GenerateTeamsShiftObject(user, kronosShift);

                        shift.KronosUniqueId = this.utility.CreateUniqueId(shift, user.KronosTimeZone);

                        this.telemetryClient.TrackTrace($"ShiftController-KronosHash: {shift.KronosUniqueId}");

                        userModelList.Add(user);

                        if (lookUpData.Count == 0)
                        {
                            shiftsNotFoundList.Add(shift);
                            userModelNotFoundList.Add(user);
                        }
                        else
                        {
                            var kronosUniqueIdExists = lookUpData.Where(c => c.KronosUniqueId == shift.KronosUniqueId);

                            if (kronosUniqueIdExists.Any() && (kronosUniqueIdExists != default(List <TeamsShiftMappingEntity>)))
                            {
                                lookUpEntriesFoundList.Add(kronosUniqueIdExists.FirstOrDefault());
                            }
                            else
                            {
                                shiftsNotFoundList.Add(shift);
                                userModelNotFoundList.Add(user);
                            }
                        }
                    }
                }
            }

            if (lookUpData.Except(lookUpEntriesFoundList).Any())
            {
                await this.DeleteOrphanDataShiftsEntityMappingAsync(configurationDetails, lookUpEntriesFoundList, userModelList, lookUpData).ConfigureAwait(false);
            }

            await this.CreateEntryShiftsEntityMappingAsync(configurationDetails, userModelNotFoundList, shiftsNotFoundList, monthPartitionKey).ConfigureAwait(false);

            this.telemetryClient.TrackTrace($"ShiftController - ProcessShiftEntitiesBatchAsync ended at: {DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)}");
        }
예제 #6
0
        /// <summary>
        /// This method will cause the thread to wait allowing us to retrun a success response
        /// for the delete WFI request. It will then share the changes.
        /// </summary>
        /// <param name="shift">The shift we want to share.</param>
        /// <param name="mappedTeam">The team details of the schedule we want to share.</param>
        /// <param name="allRequiredConfigurations">The required configuration.</param>
        /// <returns>A unit of execution.</returns>
        private async Task ShareScheduleAfterShiftDeletion(ShiftsShift shift, TeamToDepartmentJobMappingEntity mappedTeam, IntegrationApi.SetupDetails allRequiredConfigurations)
        {
            // We want to wait so that there is time to respond a success to the WFI request
            // meaning the shift will be deleted in Teams.
            Thread.Sleep(int.Parse(appSettings.AutoShareScheduleWaitTime));

            // We now want to share the schedule between the start and end time of the deleted shift.
            await this.graphUtility.ShareSchedule(
                allRequiredConfigurations.GraphConfigurationDetails,
                mappedTeam.TeamId,
                shift.SharedShift.StartDateTime,
                shift.SharedShift.EndDateTime,
                false).ConfigureAwait(false);
        }