public async Task <ActionResult> ImportMappingAsync() { // getting the posted file. var file = this.HttpContext.Request.Form.Files[0]; bool isValidFile = true; int noOfColumns = 0; if (file != null) { using (XLWorkbook workbook = new XLWorkbook(file.OpenReadStream())) { var worksheet = workbook.Worksheet(1); // validation to check if row other than column exists if (worksheet.RowsUsed().Count() == 1) { isValidFile = false; return(this.Json(new { response = isValidFile })); } // getting count of total used cells var usedCellsCount = worksheet.RowsUsed().CellsUsed().Count(); foreach (IXLRow row in worksheet.RowsUsed()) { if (row.RangeAddress.FirstAddress.RowNumber == 1) { // getting count of total coumns available in the template noOfColumns = row.CellsUsed().Count(); continue; } // validation to check if any cell has empty value if ((usedCellsCount % noOfColumns) != 0 || noOfColumns != Convert.ToInt16(Resources.NoOfColumnsInUserExcel, CultureInfo.InvariantCulture)) { isValidFile = false; return(this.Json(new { response = isValidFile })); } AllUserMappingEntity entity = new AllUserMappingEntity() { PartitionKey = Utility.OrgJobPathDBConversion(row.Cell(1).Value.ToString()), RowKey = row.Cell(2).Value.ToString(), KronosUserName = row.Cell(3).Value.ToString(), ShiftUserAadObjectId = row.Cell(4).Value.ToString(), ShiftUserDisplayName = row.Cell(5).Value.ToString(), ShiftUserUpn = row.Cell(6).Value.ToString(), }; if (isValidFile) { isValidFile = await this.userMappingProvider.KronosShiftUsersMappingAsync(entity).ConfigureAwait(false); } } } } return(this.Json(new { response = isValidFile })); }
/// <summary> /// Creates and stores a shift mapping entity. /// </summary> /// <param name="shift">A shift from Shifts.</param> /// <param name="user">A user mapping entity.</param> /// <param name="mappedTeam">A team mapping entity.</param> /// <param name="monthPartitionKey">The partition key for the shift.</param> /// <returns>A task.</returns> private async Task CreateAndStoreShiftMapping(ShiftsShift shift, AllUserMappingEntity user, TeamToDepartmentJobMappingEntity mappedTeam, List <string> monthPartitionKey) { var kronosUniqueId = this.utility.CreateShiftUniqueId(shift, mappedTeam.KronosTimeZone); var shiftMappingEntity = this.CreateNewShiftMappingEntity(shift, kronosUniqueId, user.RowKey, mappedTeam.TeamId); await this.shiftMappingEntityProvider.SaveOrUpdateShiftMappingEntityAsync(shiftMappingEntity, shift.Id, monthPartitionKey[0]).ConfigureAwait(false); }
/// <summary> /// Method to save or update the user mapping. /// </summary> /// <param name="entity">Mapping entity reference.</param> /// <returns>http status code representing the asynchronous operation.</returns> public Task SaveOrUpdateUserMappingEntityAsync(AllUserMappingEntity entity) { if (entity is null) { throw new ArgumentNullException(nameof(entity)); } return(this.StoreOrUpdateEntityAsync(entity)); }
/// <summary> /// Having the ability to create a new TeamsShiftMappingEntity. /// </summary> /// <param name="shift">The Shift model.</param> /// <param name="userMappingEntity">Details of user from User Mapping Entity table.</param> /// <param name="kronosUniqueId">Kronos Unique Id corresponds to the shift.</param> /// <returns>Mapping Entity associated with Team and Shift.</returns> public static TeamsShiftMappingEntity CreateShiftMappingEntity( Models.IntegrationAPI.Shift shift, AllUserMappingEntity userMappingEntity, string kronosUniqueId) { TeamsShiftMappingEntity teamsShiftMappingEntity = new TeamsShiftMappingEntity { AadUserId = shift?.UserId, KronosUniqueId = kronosUniqueId, KronosPersonNumber = userMappingEntity?.RowKey, }; return(teamsShiftMappingEntity); }
/// <summary> /// Having the ability to create a new TeamsShiftMappingEntity. /// </summary> /// <param name="shift">The Shift model.</param> /// <param name="userMappingEntity">Details of user from User Mapping Entity table.</param> /// <param name="kronosUniqueId">Kronos Unique Id corresponds to the shift.</param> /// <returns>Mapping Entity associated with Team and Shift.</returns> public TeamsShiftMappingEntity CreateShiftMappingEntity( Models.IntegrationAPI.Shift shift, AllUserMappingEntity userMappingEntity, string kronosUniqueId) { TeamsShiftMappingEntity teamsShiftMappingEntity = new TeamsShiftMappingEntity { AadUserId = shift?.UserId, KronosUniqueId = kronosUniqueId, KronosPersonNumber = userMappingEntity?.RowKey, ShiftStartDate = this.UTCToKronosTimeZone(shift.SharedShift.StartDateTime), }; return(teamsShiftMappingEntity); }
/// <summary> /// Gets a user model from Shifts in order to return the Org Job Path. /// </summary> /// <returns>A task.</returns> private async Task <UserDetailsModel> GetMappedUserDetailsAsync( string workForceIntegrationId, string userAadObjectId, string teamsId) { UserDetailsModel kronosUser; AllUserMappingEntity mappedUsersResult = await this.userMappingProvider.GetUserMappingEntityAsyncNew(userAadObjectId, teamsId).ConfigureAwait(false); if (mappedUsersResult != null) { var teamMappingEntity = await this.teamDepartmentMappingProvider.GetTeamMappingForOrgJobPathAsync( workForceIntegrationId, mappedUsersResult.PartitionKey).ConfigureAwait(false); if (teamMappingEntity != null) { kronosUser = new UserDetailsModel() { KronosPersonNumber = mappedUsersResult.RowKey, ShiftUserId = mappedUsersResult.ShiftUserAadObjectId, ShiftTeamId = teamsId, ShiftScheduleGroupId = teamMappingEntity.TeamsScheduleGroupId, OrgJobPath = mappedUsersResult.PartitionKey, }; } else { this.telemetryClient.TrackTrace($"Team id {teamsId} is not mapped."); kronosUser = new UserDetailsModel() { Error = Resource.UserTeamNotExists, }; } } else { this.telemetryClient.TrackTrace($"User id {userAadObjectId} is not mapped."); kronosUser = new UserDetailsModel() { Error = Resource.UserMappingNotFound, }; } return(kronosUser); }
/// <summary> /// Method to save or update the user mapping. /// </summary> /// <param name="entity">Mapping entity reference.</param> /// <returns>http status code representing the asynchronous operation.</returns> public async Task <bool> KronosShiftUsersMappingAsync(AllUserMappingEntity entity) { if (entity is null) { throw new ArgumentNullException(nameof(entity)); } try { var result = await this.StoreOrUpdateEntityAsync(entity).ConfigureAwait(false); return(result.HttpStatusCode == (int)HttpStatusCode.NoContent); } catch (Exception) { return(false); throw; } }
/// <summary> /// Edits a shift in Kronos and updates the database. /// </summary> /// <param name="editedShift">The shift to edit.</param> /// <param name="user">The user the shift is for.</param> /// <param name="mappedTeam">The team the user is in.</param> /// <returns>A response for teams.</returns> public async Task <ShiftsIntegResponse> EditShiftInKronosAsync(ShiftsShift editedShift, AllUserMappingEntity user, TeamToDepartmentJobMappingEntity mappedTeam) { // The connector does not support drafting entities as it is not possible to draft shifts in Kronos. // Likewise there is no share schedule WFI call. if (editedShift.DraftShift != null) { return(ResponseHelper.CreateBadResponse(editedShift.Id, error: "Editing a shift as a draft is not supported for your team in Teams. Please publish changes directly using the 'Share' button.")); } if (editedShift.SharedShift == null) { return(ResponseHelper.CreateBadResponse(editedShift.Id, error: "An unexpected error occured. Could not edit the shift.")); } // We use the display name to indicate shift transfers. As we cannot support editing shifts // with a transfer we block edits on shifts containing the transfer string. if (editedShift.SharedShift.DisplayName.Contains(appSettings.TransferredShiftDisplayName)) { return(ResponseHelper.CreateBadResponse(editedShift.Id, error: "You can't edit a shift that includes a shift transfer. Please make your changes in Kronos")); } // We do not support editing activities in Teamsand cannot support editing shift transfers // therefore we only expect activities with the regular segment type. Anything else means the // manager has modified or added an activity. var invalidActivities = editedShift.SharedShift.Activities.Where(x => x.DisplayName != ApiConstants.RegularSegmentType); if (invalidActivities.Any()) { return(ResponseHelper.CreateBadResponse(editedShift.Id, error: "Editing shift activities is not supported for your team in Teams.")); } var allRequiredConfigurations = await this.utility.GetAllConfigurationsAsync().ConfigureAwait(false); if ((allRequiredConfigurations?.IsAllSetUpExists).ErrorIfNull(editedShift.Id, "App configuration incorrect.", out var response)) { return(response); } // We need to get all other shifts the employee works that day. var kronosStartDateTime = this.utility.UTCToKronosTimeZone(editedShift.SharedShift.StartDateTime, mappedTeam.KronosTimeZone); var kronosEndDateTime = this.utility.UTCToKronosTimeZone(editedShift.SharedShift.EndDateTime, mappedTeam.KronosTimeZone); var monthPartitionKey = Utility.GetMonthPartition(this.utility.FormatDateForKronos(kronosStartDateTime), this.utility.FormatDateForKronos(kronosEndDateTime)); var shiftToReplace = await this.shiftMappingEntityProvider.GetShiftMappingEntityByRowKeyAsync(editedShift.Id).ConfigureAwait(false); var shiftToReplaceStartDateTime = this.utility.UTCToKronosTimeZone(shiftToReplace.ShiftStartDate, mappedTeam.KronosTimeZone); var shiftToReplaceEndDateTime = this.utility.UTCToKronosTimeZone(shiftToReplace.ShiftEndDate, mappedTeam.KronosTimeZone); var commentTimeStamp = this.utility.UTCToKronosTimeZone(DateTime.UtcNow, mappedTeam.KronosTimeZone).ToString(CultureInfo.InvariantCulture); var shiftComments = XmlHelper.GenerateEditedShiftKronosComments(editedShift.SharedShift.Notes, this.appSettings.ShiftNotesCommentText, commentTimeStamp); var editResponse = await this.shiftsActivity.EditShift( new Uri(allRequiredConfigurations.WfmEndPoint), allRequiredConfigurations.KronosSession, this.utility.FormatDateForKronos(kronosStartDateTime), this.utility.FormatDateForKronos(kronosEndDateTime), kronosEndDateTime.Day > kronosStartDateTime.Day, Utility.OrgJobPathKronosConversion(user.PartitionKey), user.RowKey, kronosStartDateTime.TimeOfDay.ToString(), kronosEndDateTime.TimeOfDay.ToString(), this.utility.FormatDateForKronos(shiftToReplaceStartDateTime), this.utility.FormatDateForKronos(shiftToReplaceEndDateTime), shiftToReplaceStartDateTime.TimeOfDay.ToString(), shiftToReplaceEndDateTime.TimeOfDay.ToString(), shiftComments).ConfigureAwait(false); if (editResponse.Status != Success) { return(ResponseHelper.CreateBadResponse(editedShift.Id, error: "Shift could not be edited in Kronos.")); } await this.DeleteShiftMapping(editedShift).ConfigureAwait(false); await this.CreateAndStoreShiftMapping(editedShift, user, mappedTeam, monthPartitionKey).ConfigureAwait(false); return(ResponseHelper.CreateSuccessfulResponse(editedShift.Id)); }
/// <summary> /// Adds the shift to Kronos and the database. /// </summary> /// <param name="shift">The shift to add.</param> /// <param name="user">The user the shift is for.</param> /// <param name="mappedTeam">The team the user is in.</param> /// <returns>A response for teams.</returns> public async Task <ShiftsIntegResponse> CreateShiftInKronosAsync(ShiftsShift shift, AllUserMappingEntity user, TeamToDepartmentJobMappingEntity mappedTeam) { // The connector does not support drafting entities as it is not possible to draft shifts in Kronos. // Likewise there is no share schedule WFI call. if (shift.DraftShift != null) { return(ResponseHelper.CreateBadResponse(shift.Id, error: "Creating a shift as a draft is not supported for your team in Teams. Please publish changes directly using the 'Share' button.")); } if (shift.SharedShift == null) { return(ResponseHelper.CreateBadResponse(shift.Id, error: "An unexpected error occured. Could not create the shift.")); } if (shift.SharedShift.Activities.Any()) { return(ResponseHelper.CreateBadResponse(shift.Id, error: "Adding activities to shifts is not supported for your team in Teams. Remove all activities and try sharing again.")); } if (user.ErrorIfNull(shift.Id, "User could not be found.", out var response)) { return(response); } var allRequiredConfigurations = await this.utility.GetAllConfigurationsAsync().ConfigureAwait(false); if ((allRequiredConfigurations?.IsAllSetUpExists).ErrorIfNull(shift.Id, "App configuration incorrect.", out response)) { return(response); } var kronosStartDateTime = this.utility.UTCToKronosTimeZone(shift.SharedShift.StartDateTime, mappedTeam.KronosTimeZone); var kronosEndDateTime = this.utility.UTCToKronosTimeZone(shift.SharedShift.EndDateTime, mappedTeam.KronosTimeZone); var commentTimeStamp = this.utility.UTCToKronosTimeZone(DateTime.UtcNow, mappedTeam.KronosTimeZone).ToString(CultureInfo.InvariantCulture); var comments = XmlHelper.GenerateKronosComments(shift.SharedShift.Notes, this.appSettings.ShiftNotesCommentText, commentTimeStamp); var creationResponse = await this.shiftsActivity.CreateShift( new Uri(allRequiredConfigurations.WfmEndPoint), allRequiredConfigurations.KronosSession, this.utility.FormatDateForKronos(kronosStartDateTime), this.utility.FormatDateForKronos(kronosEndDateTime), kronosEndDateTime.Day > kronosStartDateTime.Day, Utility.OrgJobPathKronosConversion(user.PartitionKey), user.RowKey, kronosStartDateTime.TimeOfDay.ToString(), kronosEndDateTime.TimeOfDay.ToString(), comments).ConfigureAwait(false); if (creationResponse.Status != Success) { return(ResponseHelper.CreateBadResponse(shift.Id, error: "Shift was not created successfully in Kronos.")); } var monthPartitionKey = Utility.GetMonthPartition(this.utility.FormatDateForKronos(kronosStartDateTime), this.utility.FormatDateForKronos(kronosEndDateTime)); await this.CreateAndStoreShiftMapping(shift, user, mappedTeam, monthPartitionKey).ConfigureAwait(false); return(ResponseHelper.CreateSuccessfulResponse(shift.Id)); }
/// <summary> /// Deletes the shift from Kronos and the database. /// </summary> /// <param name="shift">The shift to remove.</param> /// <param name="user">The user the shift is for.</param> /// <param name="mappedTeam">The team the user is in.</param> /// <returns>A response for teams.</returns> public async Task <ShiftsIntegResponse> DeleteShiftInKronosAsync(ShiftsShift shift, AllUserMappingEntity user, TeamToDepartmentJobMappingEntity mappedTeam) { if (shift.SharedShift == null) { return(ResponseHelper.CreateBadResponse(shift.Id, error: "An unexpected error occured. Could not delete the shift.")); } if (user.ErrorIfNull(shift.Id, "User could not be found.", out var response)) { return(response); } var allRequiredConfigurations = await this.utility.GetAllConfigurationsAsync().ConfigureAwait(false); if ((allRequiredConfigurations?.IsAllSetUpExists == false).ErrorIfNull(shift.Id, "App configuration incorrect.", out response)) { return(response); } // Convert to Kronos local time. var kronosStartDateTime = this.utility.UTCToKronosTimeZone(shift.SharedShift.StartDateTime, mappedTeam.KronosTimeZone); var kronosEndDateTime = this.utility.UTCToKronosTimeZone(shift.SharedShift.EndDateTime, mappedTeam.KronosTimeZone); var deletionResponse = await this.shiftsActivity.DeleteShift( new Uri(allRequiredConfigurations.WfmEndPoint), allRequiredConfigurations.KronosSession, this.utility.FormatDateForKronos(kronosStartDateTime), this.utility.FormatDateForKronos(kronosEndDateTime), kronosEndDateTime.Day > kronosStartDateTime.Day, Utility.OrgJobPathKronosConversion(user.PartitionKey), user.RowKey, kronosStartDateTime.TimeOfDay.ToString(), kronosEndDateTime.TimeOfDay.ToString()).ConfigureAwait(false); if (deletionResponse.Status != Success) { return(ResponseHelper.CreateBadResponse(shift.Id, error: "Shift was not successfully removed from Kronos.")); } await this.DeleteShiftMapping(shift).ConfigureAwait(false); #pragma warning disable CS4014 // We do not want to await this call as we need the shift to be deleted in Teams before sharing the schedule. Task.Run(() => this.ShareScheduleAfterShiftDeletion(shift, mappedTeam, allRequiredConfigurations)); #pragma warning restore CS4014 return(ResponseHelper.CreateSuccessfulResponse(shift.Id)); }