Version 9.1.231 (25 May 2026) Notifications Resolve issue with notification schedule run time not saving correctly (#130537) Problem The user's selected Run time is converted to UTC from the server's time  Solution The user's selected Run time should be converted to UTC from their own timezone Create a helper method to convert the user's local time to UTC  Resolved System Help Page error (#149490) Problem An error occurred when opening the system help modal for Notifications  Solution Missing mapping for page type Resolve issue where images loaded onto the Template email or system message body did not persist (#148295) Problem When adding an image to the body of a template's Email or System Message on the QYSIWYG editor, the image is not persisted after saving the template, nor does it display when the notification is sent.   Solution Ensure the full URL is returned when the image is uploaded, and the blob src is replaced with the actual URL before saving the template details.   Add ruleset password encryption API and helpers. Decrypt passwords when sending email or SMS messages (#147890) Problem Encrypted passwords are not decrypted when sending emails or sms messages. All historic passwords are not encrypted.   Solution Add support for encrypting stored ruleset credentials and decrypting them at runtime. Introduce CryptoHelper.ValidateAndEncryptString and DecryptValue to detect/encrypt plaintext and decrypt stored values using the configured AES key. Add a new gRPC endpoint, EncryptRulesetPasswords and corresponding protobuf message; validate provided encryption key before running.  Add EncryptRulesetPasswordsCommand and handler to encrypt passwords/client secrets/tokens for EmailSetup and SmsSetup records via repositories. Update Notification API and processing services to use CryptoHelper.DecryptValue when reading credentials (password, client secret, tokens) so values are decrypted from storage before use. Add UpdatePassword methods to EmailSetup and SmsSetup aggregates to support credential updates. Add ListAsync(rulesetId) to EmailSetup and SmsSetup repository interfaces and implementations so the handler can enumerate setups to update. Minor cleanup Remove an unused using in Import.API Program and reorder usings in various files.  These changes enable a safe migration path to encrypt existing plaintext credentials in the DB and ensure services decrypt credentials at runtime.   Rename FourHourly, implement front-end and add missing translations (#149046) Problem Some schedules are displayed without a mandatory schedule type    Solution This happened due to the "Four-Hourly" schedule type not being implemented on the front-end. Implement the schedule type on the front-end. Also, renamed the "FourHourly" schedule type enum. It is quite misleading, seeing that this schedule is used for 2-hour schedules too. Lastly, updated a couple of missing translations for schedules and notifications   Ensure that when repeat false, repeat x hours is 0 (#149224) Problem Repeat every x hours shown as '8' when no repeat has been set   Solution Ensure that when repeat false, repeat x hours is 0    When clicking on a schedule, the bread crumb takes the user back to templates (#148308) Problem When the user clicks on a schedule within the schedules tab of Notifications, the bread crumb takes the user to templates instead of schedules.   Solution Modified the existing logic to not take the user back to the index page of rulesets, and rather to the schedules tab.   People Management Correct System help pages file uploads not persisting and resolve toolbox squashed (#148297) Problem Images are not persisting when uploaded onto the user guide help page section editors. Solution Added server-side upload URL to store images and ensure the image is persisted. Fixed squashed toolbar.  Resolve virtual tour slides images uploaded on the editor not persisting (#148297) Problem When uploading an image to the editor for a virtual tour slide, the image does not persist when logging out and back in again. Solution Ensure image upload paths are accessible when the modal is opened, and that editor initialisation options are rendered correctly to allow event handlers to fire.  Try to resolve the issue with syncfusion wysiwyg editor not available when the page help modal is opened (#148296) Problem Page help modal editors don't show the toolbar, and not actually the editor, it shows a textarea Cannot reproduce locally, possible cause is that when the page help modal js file loads and the Syncfusion variable is instantiated, the Syncfusion script hasn't fully run, and the component has not been initialised.  Solution Changed to load the Syncfusion editor via a function on the page help modal to ensure that when it is accessed, the editor control should be initialised.  Incorrect Email is showing when the user resets email and clicks Reset User Password (#127979) Problem When the user changes an email address on People Management, clicks save, and proceeds to do a password reset, the old email is shown.   Solution Added additional logic to ensure the email is updated on the frontend after the save is successful.   Resolved issue where no users are returned in the API call if the list of usernames is not supplied (#149033) Problem When a full user sync is done from V9 to V8, the list of users returned to V8 is empty.   Solution Added functionality to return all users if no list of specific users is returned.   Implemented suggestion to show enter character (#149129) Problem When on the advanced filter, the dropdown is opened, search is only initiated after the first character has been typed, but the wording is read as No Options    Solution Add a change to show wording to enter a character when text is empty, and when no items are returned, only then show No Options   Resolved image urls not imported to V8 and used (#143999) Problem Changes were made when a user selects their profile image, which is stored in a new location defined by the type and the ruleset ID, with the file name as the user ID, but for the imports, the utility did not have this new change    Solution Corrected helper to fetch the correct URLs for the users selected for the import result back to v8   Dashboard Remove universal selector from syncfusion editor styling, causing no borders to display (#148395) Problem Table borders are not shown in the editor. Styling has a universal selector that forces table cells, columns and rows to also have no borders.  Solution Remove the universal selector and explicitly set the border colours for tables within the SF editor component. Added cache busting to syncfusion editor stylesheet load on baselayout  Set the SF WYSIWYG editor toolbar to floating to try to resolve the issue where it gets squashed (#148231) Problem With large content in the editor, the toolbar gets squashed. Solution Cannot replicate locally, trying the suggestion to make the toolbar floating, which should hopefully solve the overflow and squashing of it  Resolve issue with the uploaded image on the custom dashboard widget not displaying after being saved (#148599) Problem When adding an image to a custom dashboard widget, the image is not displayed after saving and does not show on the main dashboard. Image path is not correctly replaced when the content path is returned from the server after editor upload.    Solution Ensure the actual image src path is replaced in the editor after the upload completes.   Imports Implement a unique tab ID when exporting transaction logs and the user validation report on Notification| Imports to ensure a single download (#148249) Problem When exporting transactions or the validation report, the export is auto-downloaded multiple times. When the communication service is unavailable, the notification page fails to load tabs unrelated to communication   Solution This pull request introduces several improvements and refactorings to the user validation export and transaction log export functionality, as well as error handling enhancements for user notifications. The main changes involve switching the export endpoint from GET to POST, improving error handling, and updating the JavaScript logic for exporting user validation reports.   Resolve import error when dual participation is disabled, indicating either person or manager ratings required for final rating (#139918) Problem When importing full agreements on a setup where Dual Participation is disabled (manager rating only). The import fails when you provide both final rating and manager rating, indicating "Person and Manager Ratings required for Final".   Solution Corrected validation that checks final ratings supplied to take the Dual Participation setting into account. NOTE: Actual changes line 863 - 866, the rest is applied to code suggestions   Add custom script for client to exclude all non-permanent employees from the import (#148440) Problem Non-permanent employees are imported with the Payroll sync.   Solution Add a custom script to delete non-permanent employees from the import staging table.   Add additional context logging on Import process errors (#148482) Problem Multiple errors are logged on the Import service regarding the CreateImportErrorsCommand. Possibly due to a scenario where the ImportId provided for the errors is '0'. By looking at the code, it is not clear where or how this scenario would be encountered, as all places where the command is actioned have a guard beforehand (where ImportId > 0) or the ImportId has already been used in prior instances of that caller, so should technically not be 0 at this point.    Solution To assist with identifying where this issue stems from, added a context parameter to the logging on the CreateImportErrorsCommandHandler. Along with the error should now also point out from which context the errors are being logged, and we can then address the root cause more accurately.   Correct duplication in identity when importing a username change (#149214) Problem When importing a username, the change in the identity service is not updated, and a duplicate user is created. When the user fails to create or update the materialisation, wait indefinitely, as the change is not materialised due to rejection   Solution Switch user matching in Identity import to use UserId instead of Username. Update ImportUsersEventConsumer to pass a list of valid usernames into VerifyUserMaterialisation. Change IUserDetailsStagingQueries.UnMaterialisedUserCount signature to accept (rulesetId, List usernames) and update implementation to create a #Usernames temp table, bulk-insert the usernames via SqlBulkCopy, and join against the materialised users table to count unmaterialised entries.   Employee code update retention, correction of pre-import validation, and keep the existing job profile title when importing with code only. Add V8 import retry (#121156, #120370, #127183 and #127189) Problem When the address information is not mandatory, during pre-import validation, the existing employee code is lost when updating a user. The job title of an existing job profiler is overwritten with the Learner title when importing using only the code. When V8 is not available, the import request fails without a retry    Solution Remove logic to prevent incomplete address details when the mandatory is inactive A change has been implemented when updating a user; if the employee code is not provided in the import sheet and already exists in the system, it will not be overridden When importing an existing job with only the job code, keep the existing title when updating the job profile Add a retry on the V8 request to try every minute for 5 minutes when communication is not available.   Performance Management Adding external link confirmation modal on opening doc link and doc link whitelist validation (#140349) Problem On Performance Management, document links(external URLs) can be added that open in a new tab without any validation or user warning. This means users may be redirected to external sites without being informed or protected.   Solution Added validation when creating a document link to ensure the URL belongs to an approved (whitelisted) domain. If not, the link cannot be saved, and an error message is shown. When opening a document link, a confirmation prompt is now displayed with a warning. This helps prevent users from accidentally navigating to external sites.   Performance improvement on Contract Period Section Items select query and Review Files index added (#149185) Problem Query that fetches a list of KPIs for the contract section identified as long-running/high usage and requires some optimisation. Review the Files table, identified as requiring an index.    Solution Added index to Review Files table. Optimised KPI query, moved sub selects out to CTEs to improve performance: Eliminates N+1 query problem (correlated subqueries executing per row) Pre-aggregates counts once using GROUP BY • Uses set-based operations instead of row-by-row execution The query optimiser can better optimise JOIN operations   Resolve issue on Copy From Previous / Another creation where duplicate section items fail contract creation (#149100) Problem When copying from a previous contract (or another / template) and that previous contract has duplicated KPIs (caused by a historical resolved bug), the section item creation fails, but the contract record is created and orphaned due to the db context save getting triggered. Ends up with duplicate users displaying on the dashboard since the query is picking up the extra contract records.    Solution Added error handling to the section item create, and if fail then remove the contract from the DB since this is an orphan. Added handling on the front end as well to better handle error responses.   Correct date verification for check-in started notification recipients (#149007) Problem Checkin Started Email not sent on the correct date   Solution Update NotificationQueries to use explicit table references and cleaner SQL formatting. Replaced dynamic muPerson/muManager/url query fragments with explicit JOINs using {muPerson_query.TableReference}, {url_query.TableReference} and {muManager_query.TableReference}; adjusted date comparisons to cast RYSI.StartDate/EndDate and ISNULL(PD.StartDate, RYSI.StartDate) consistently; added a comment for the manager section and reformatted the SELECTs for readability. Also changed the result return expression (previous ToList() call replaced with the new expression).   Learning Management Fix issue on absent notification not correctly embedding image source when sending absent notification with image (#148368) Problem On the attendance register, when adding an image to the email body, navigating to confirmation and back loses the image. When sending the notification, the image is also not included.    Solution Ensure the selected image is uploaded to the server before sending the notification, and replace the image src in the email body with an absolute URL   Fix SqlException 'Invalid column name RulesetId' on marksheet load (#149479) Problem After the recent materialisation changes, the RulesetId was no longer part of the table, which caused the marksheet to stop loading.   Solution Updated the Join to include RulesetId via other means, which should resolve the marksheet load issue.   Exports Resolve incorrect product displaying on user export list (#126260) Problem When exporting the Error Logs for certain imports, the product is incorrectly displayed as People Management.    Solution The product code is not sent through to the export error logs function and always defaults to PeopleManagement. Added a helper to determine product type from import type. Include Product Type when requesting export of logs/transactions so it correctly saves the User Files with the correct Product Type.   Improve the performance of Excel imports and implement in the service report builder exports (#147972) Problem Exporting large report builder reports creates large memory spikes in MVC, causing the service to crash   Solution Restructures and refactors the location and namespaces of several extension and enum classes related to OpenXML and dictionary mapping, moving them from the WebMVC project to the SignifyExtensions infrastructure project. It also introduces a new dependency and corrects some naming inconsistencies. Key changes include: Refactoring and Relocation of Extensions and Enums: Moved multiple extension classes (such as CellExtensions, ColumnExtensions, OpenXMLOptions, PropertiesExtensions, SheetDataExtensions, SpreadsheetDocumentExtensions, WorkbookAttributes, WorksheetExtensions, and WorksheetPartExtensions) from the WebMVC project to the SignifyExtensions project, updating their namespaces accordingly.  This improves code organisation and reusability across projects. Relocated and updated enum files, such as UserFileType and PropertyType, to the SignifyExtensions.Enums namespace, ensuring consistency and proper separation of concerns. Dictionary Mapping Extension Refactor: Moved the DictionaryExtensions class from MasterDataShared.Extensions to SignifyExtensions.Extensions, and restored its implementation there. The original file is now commented out, centralising this utility in a shared location.  Namespace and Type Corrections: Updated all OpenXML-related extension files and usages to reference the new SignifyExtensions namespaces and corrected enum type references in method calls.  Dependency Management: Added the Microsoft.Extensions.Configuration NuGet package version 10.0.1 to the solution, possibly to support configuration features in the refactored codebase.  Minor Cleanups: Removed unused usings and commented-out code, and made minor adjustments to code formatting and comments for clarity and maintainability. These changes collectively improve code modularity, maintainability, and clarity by consolidating shared logic and ensuring consistent usage of namespaces and dependencies across the solution.   Data Warehouse Updated DataDictionary SSIS Package (#148377) Problem The field name needs to be renamed to the DataSource Contract Surveys    Solution Updated FieldAlias "Comment" to "Review Survey Contract" for Data Source Contract Surveys   Ruleset Management Fixing breadcrumb for back button (#149003) Problem When opening a schedule from the Schedule Setup tab in Ruleset setup -> communications, then navigating back using the Back button, the system redirects to the Templates list instead of returning to the Schedule Setup list.    Solution Updated the breadcrumb generated when opening the edit page to ensure back navigation returns the user to the correct page.   Resolved account inactive on ruleset creation (#148872) Problem When creating a new ruleset, a user is created, but when copied from R1, a user account can be set to inactive.   Solution Added new rule check if it is within the account creation for a new ruleset and is copied from R1, always set active to true   Job Management Add tooltips to copy and preview buttons for job positions (#148304) Problem The copy and preview buttons do not have tooltips in JobProfiler's Positions page.   Solution Add the translation text as hidden fields so the JS can access it and initialise tooltips for those elements.   Resolve overflow of continuous position title in delete modal (#148987) Problem Position name does not fit on the delete modal    Solution Resolve overflow of the continuous position title in the delete modal   Add missing required fields to CreateRequisitions endpoint (#147946) Problem The CreateRequisitions endpoint for v9 does not send EditedUser, and also the PrsEmploymentTypeId should be sent to v8 as PrsEmploymentTypeExternalId.   Solution Corrected the request   Resolved Inactive jobProfiles being selected (#149293) Problem Within people groups, grouped conditions for jobs, inactive job profiles can be selected   Solution Added a condition to only include active jobProfiles   Fix Missing property on Endpoint (#142989) Problem The ListPositions endpoint had a missing property in the response section "NodeId".   Solution Added the missing property to the response.   Ruleset | Integrations Display "No schedules" if the schedule date is past (#143241) Problem Difficult to determine when a schedule is not active due to the ending date being in the past    Solution Display "No schedules" if the schedule date is past    Event Scheduling Ensure training provider filtered results are prioritised (#149337) Problem The Search-as-you-type function does not populate the closest result to the top of the list   Solution Ensure the training provider's filtered results are prioritised    Fix blank notification templates for new event schedules (#149309) Problem The Event notifications page is blank for new event schedules   Solution The integration event consumer (which populates the templates for the event schedule) was not registered and therefore never executed, even though the event was fired.    HR Processes Use uniform button styling for the hidden field add button (#149292) Problem Hidden Fields: Add a button to be uniform with the existing Add button    Solution Use uniform button styling for the hidden field add button    People Groups Fix duplicate insert error into MaterialisedPeopleGroupUsers (#149213) Problem When a user has multiple appointment records where the current position = 1, the full people group refresh will try to insert a duplicate entry into MaterialisedPeopleGroupUsers. You have the same user, same ruleset, same people group, but different status (2 records), it tries to insert both and fails.    Solution Group people, group users, and take the first appointment status (which will be preferred Active). Note, this should technically not be the case, as there should be, in almost all cases, only a single CurrentPosition appointment record, making this more of a defensive fix   Resolved load more on Reporting Lines for People Group (#149115) Problem When opening the modal for reporting line people group, all items are returned with the load more button at the bottom, which does not search extra data to append to the context, the same load of data    Solution Limited results to default 20 items and added a cursor for load more items to append to the end of the data