LogoSupport Hub

User Edit Log

Generates a log of user edits, tracking changes made to user accounts, including who made the change, what was changed, and when the change occurred.

Parameters

  • None (or list any script parameters if present).

Notes

  • Useful for auditing user account changes and tracking administrative actions.
  • Ensure appropriate permissions to access user edit logs.

T-SQL

user_edit_log.sql
DECLARE @StartDate DATETIME = '2/16/2025';
DECLARE @EndDate DATETIME = '2/22/2025';
DECLARE @ExcludedUsernames NVARCHAR(MAX) = 'AUTOCOMP,ESSUSER,INVALIDWG,SPLPAY,VOUCHER,BLENDOTCRD,CERTOTCRD,AUTOSVC';
--list exclude users
DECLARE @EMPEdits NVARCHAR(MAX) = '98,15,700';
-- List of employee edit types to exclude

WITH
    EditTypeDescriptions
    AS
    (
        SELECT *
        FROM (VALUES
                (601, 'Incident Adjustment (PAYDESNUM=NEW incident #, PREVPAYDES=ORIGINAL incident #)'),
                (500, 'Historical Edit'),
                (2, 'Hours Credit'),
                (4, 'Credit Worked Time'),
                (603, 'Add Incident'),
                (403, 'Addressed Exception'),
                (404, 'EMP Change State Edit'),
                (301, 'Credit Benefit Balance'),
                (302, 'Debit Benefit Balance'),
                (303, 'New Balance'),
                (10, 'Authorized Timecard'),
                (0, 'Added Punch'),
                (1, 'Deleted Punch'),
                (12, 'Adjust Punch to Start of Shift'),
                (13, 'Adjust Punch to End of Shift'),
                (101, 'Workgroup Transfer at Time of Day'),
                (103, 'Paydes Transfer at Time of Day'),
                (114, 'Paydes Block Hours Transfer'),
                (23, 'Delete Schedule'),
                (22, 'Add Schedule'),
                (401, 'Worksheet Hours Entry'),
                (29, 'Add Benefit Schedule'),
                (119, 'Workgroup Transfer time of day'),
                (700, 'EMP Add trans'),
                (6, 'Pay to')
    ) AS T(EditType, Description)
    ),

    ExcludedUsers
    AS
    (
        SELECT value AS ExcludedUsername
        FROM STRING_SPLIT(@ExcludedUsernames, ',')
        -- Split usernames into a table
    ),
    ExcludedEdits
    AS
    (
        SELECT CAST(value AS INT) AS EditType
        FROM STRING_SPLIT(@EMPEdits, ',')
        -- Convert List of employee edit types list into a table
    ),

    Edits
    AS
    (
        -- Current Edits
                            SELECT
                CASE 
            WHEN SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL THEN SE.CANCELBY  -- Use canceling user
            ELSE SE.USERNAME  
        END AS USERNAME,
                CASE 
            WHEN SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL THEN UC.FRIENDLYNAME  -- Friendly name of canceling user
            ELSE U.FRIENDLYNAME  
        END AS UserFriendlyName,
                E.LASTNAME + ', ' + E.FIRSTNAME AS EmployeeName,
                CASE 
            WHEN SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL THEN 'Cancelled A ' + COALESCE(ETD.Description, CAST(SE.EDITTYPE AS VARCHAR))
            WHEN SE.EDITTYPE = 6 AND SE.PAYDESNUM IS NOT NULL THEN 
                COALESCE(ETD.Description, CAST(SE.EDITTYPE AS VARCHAR)) + ' - ' + 
                CASE SE.PAYDESNUM
                    WHEN 1 THEN 'Sch Start'
                    WHEN 2 THEN 'Sch End'
                    WHEN 3 THEN 'Act Start'
                    WHEN 4 THEN 'Act End'
                    ELSE CAST(SE.PAYDESNUM AS VARCHAR)  -- Fallback for unknown values
                END                
            ELSE COALESCE(ETD.Description, CAST(SE.EDITTYPE AS VARCHAR))  
        END AS EditTypeDescription,
                FORMAT(SE.EFFDATE, 'MM/dd/yyyy') AS EFFDATE,
                CASE
            WHEN SE.EDITTYPE IN (6,22,23,29,403) THEN NULL
            ELSE FORMAT(SE.EFFTIME, 'hh:mm tt')
        END AS EFFTIME,
                CASE 
            WHEN SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL THEN SE.USERNAME  -- Show original USERNAME
            WHEN SE.REASON = 0 THEN NULL
            ELSE COALESCE(R.DESCR, CAST(SE.REASON AS VARCHAR))  
        END AS ReasonDescription,
                CASE 
            WHEN SE.HOURS = 0 THEN NULL  
            ELSE CAST(SE.HOURS AS FLOAT) / 60 
        END AS HOURS,
                CASE 
            --WHEN SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL THEN 'Canceled'  -- Mark as Canceled
            WHEN SE.EDITTYPE = 403 THEN EXC.NAME  -- Exception Name for EditType 403
            WHEN SE.EDITTYPE IN (29,301,302) AND SE.PREVPAYDES IS NOT NULL THEN B.NAME  -- Benefit Name for EditType 301, 302
            WHEN SE.EDITTYPE = 2 THEN PDS.NAME
            ELSE NULL
        END AS Description,
                CASE 
            WHEN SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL THEN FORMAT(SE.CANCELON, 'MM/dd/yyyy hh:mm tt')  
            ELSE FORMAT(SE.TSDATETIME, 'MM/dd/yyyy hh:mm tt')  
        END AS FormattedTSDATETIME,
                'Current Edits' AS SourceTable
            FROM SUPEDITS SE
                LEFT JOIN USERS U ON SE.USERNAME = U.NAME
                LEFT JOIN EMPLOYEES E ON SE.FILEKEY = E.FILEKEY
                LEFT JOIN EditTypeDescriptions ETD ON SE.EDITTYPE = ETD.EditType
                LEFT JOIN BENEFITS B ON SE.EDITTYPE IN (29,301,302)
                    AND SE.PREVPAYDES IS NOT NULL
                    AND SE.PREVPAYDES = B.NUM
                LEFT JOIN PAYDESIGNATIONS PDS ON SE.EDITTYPE = 2
                    AND SE.PAYDESNUM IS NOT NULL
                    AND SE.PAYDESNUM = PDS.PAYDESNUM
                LEFT JOIN REASONS R ON SE.REASON = R.NUM -- FIXED: Explicit join on REASON
                LEFT JOIN ExcludedUsers EU ON SE.USERNAME = EU.ExcludedUsername
                LEFT JOIN EXCEPTIONS EXC ON SE.EDITTYPE = 403 AND SE.PAYDESNUM = EXC.NUM
                LEFT JOIN USERS UC ON SE.CANCELBY = UC.NAME
            WHERE SE.EFFDATE BETWEEN @StartDate AND @EndDate
                AND SE.EDITTYPE NOT IN (SELECT EditType
                FROM ExcludedEdits) -- Emp Edits
                AND (
        EU.ExcludedUsername IS NULL -- Regular filter: Exclude system users
                OR (SE.CANCEL <> 0 AND SE.CANCELBY IS NOT NULL)  -- Allow canceled edits
    )

        UNION ALL

            -- Historical Edits
            SELECT
                CASE 
            WHEN SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL THEN SH.CANCELBY  
            ELSE SH.USERNAME  
        END AS USERNAME,
                CASE 
            WHEN SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL THEN UC.FRIENDLYNAME  
            ELSE U.FRIENDLYNAME  
        END AS UserFriendlyName,
                E.LASTNAME + ', ' + E.FIRSTNAME AS EmployeeName,
                CASE 
            WHEN SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL THEN 'Cancelled A ' + COALESCE(ETD.Description, CAST(SH.EDITTYPE AS VARCHAR))
            WHEN SH.EDITTYPE = 6 AND SH.PAYDESNUM IS NOT NULL THEN 
                COALESCE(ETD.Description, CAST(SH.EDITTYPE AS VARCHAR)) + ' - ' + 
                CASE SH.PAYDESNUM
                    WHEN 1 THEN 'Sch Start'
                    WHEN 2 THEN 'Sch End'
                    WHEN 3 THEN 'Act Start'
                    WHEN 4 THEN 'Act End'
                    ELSE CAST(SH.PAYDESNUM AS VARCHAR)
                END
            ELSE COALESCE(ETD.Description, CAST(SH.EDITTYPE AS VARCHAR))  
        END AS EditTypeDescription,
                FORMAT(SH.EFFDATE, 'MM/dd/yyyy') AS EFFDATE,
                CASE
            WHEN SH.EDITTYPE IN (6,22,23,29,403) THEN NULL
            ELSE FORMAT(SH.EFFTIME, 'hh:mm tt')
        END AS EFFTIME,
                CASE 
            WHEN SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL THEN SH.USERNAME
            WHEN SH.REASON = 0 THEN NULL
            ELSE COALESCE(R.DESCR, CAST(SH.REASON AS VARCHAR))  
        END AS ReasonDescription,
                CASE 
            WHEN SH.HOURS = 0 THEN NULL  
            ELSE CAST(SH.HOURS AS FLOAT) / 60 
        END AS HOURS,
                CASE 
            --WHEN SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL THEN 'Canceled'
            WHEN SH.EDITTYPE = 403 THEN EXC.NAME  -- Exception Name for EditType 403
            WHEN SH.EDITTYPE IN (29,301,302) AND SH.PREVPAYDES IS NOT NULL THEN B.NAME  -- Benefit Name for EditType 301, 302
            WHEN SH.EDITTYPE = 2 THEN PDS.NAME
            ELSE NULL 
        END AS Description,
                CASE 
            WHEN SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL THEN FORMAT(SH.CANCELON, 'MM/dd/yyyy hh:mm tt')  
            ELSE FORMAT(SH.TSDATETIME, 'MM/dd/yyyy hh:mm tt')  
        END AS FormattedTSDATETIME,
                'Historical Edits' AS SourceTable
            FROM SUPEDITHIST SH
                LEFT JOIN USERS U ON SH.USERNAME = U.NAME
                LEFT JOIN EMPLOYEES E ON SH.FILEKEY = E.FILEKEY
                LEFT JOIN EditTypeDescriptions ETD ON SH.EDITTYPE = ETD.EditType
                LEFT JOIN BENEFITS B ON SH.EDITTYPE IN (29,301,302)
                    AND SH.PREVPAYDES IS NOT NULL
                    AND SH.PREVPAYDES = B.NUM
                LEFT JOIN PAYDESIGNATIONS PDS ON SH.EDITTYPE = 2
                    AND SH.PAYDESNUM IS NOT NULL
                    AND SH.PAYDESNUM = PDS.PAYDESNUM
                LEFT JOIN REASONS R ON SH.REASON = R.NUM -- FIXED: Explicit join on REASON
                LEFT JOIN ExcludedUsers EU ON SH.USERNAME = EU.ExcludedUsername
                LEFT JOIN EXCEPTIONS EXC ON SH.EDITTYPE = 403 AND SH.PAYDESNUM = EXC.NUM
                LEFT JOIN USERS UC ON SH.CANCELBY = UC.NAME
            WHERE SH.EFFDATE BETWEEN @StartDate AND @EndDate
                AND SH.EDITTYPE NOT IN (SELECT EditType
                FROM ExcludedEdits) --Emp edits
                AND (
        EU.ExcludedUsername IS NULL
                OR (SH.CANCEL <> 0 AND SH.CANCELBY IS NOT NULL)
    )

        UNION ALL

            -- User Activity Data
            SELECT
                U.NAME AS USERNAME,
                U.FRIENDLYNAME AS UserFriendlyName,
                E.LASTNAME + ', ' + E.FIRSTNAME AS EmployeeName,
                'User Activity' AS EditTypeDescription,
                FORMAT(UA.EFFDATE, 'MM/dd/yyyy') AS EFFDATE,
                NULL AS EFFTIME,
                NULL AS ReasonDescription,
                NULL AS HOURS,
                UA.DESCR AS Description,
                FORMAT(UA.EFFDATE, 'MM/dd/yyyy hh:mm tt') AS TSDATETIME,
                'User Activity' AS SourceTable
            FROM USERACTIVITY UA
                LEFT JOIN USERS U ON UA.USERID = U.UNIQUEID
                LEFT JOIN EMPLOYEES E ON UA.FILEKEY = E.FILEKEY
            WHERE UA.EFFDATE BETWEEN @StartDate AND @EndDate
    ),

    RankedEdits
    AS
    (
        SELECT *,
            ROW_NUMBER() OVER (
               PARTITION BY USERNAME, EmployeeName, EditTypeDescription, EFFDATE, EFFTIME, ReasonDescription, HOURS, Description
               ORDER BY CASE WHEN SourceTable = 'Current Edits' THEN 1 ELSE 2 END
           ) AS RowNum
        FROM Edits
    )

SELECT
    USERNAME,
    UserFriendlyName,
    EmployeeName,
    -- Concatenated Description field
    EditTypeDescription + 
    ' | Date: ' + EFFDATE +
    CASE 
        WHEN EFFTIME IS NOT NULL THEN ' | Time: ' + EFFTIME 
        ELSE '' 
    END +
    CASE 
        WHEN HOURS IS NOT NULL THEN ' | Hours: ' + CAST(ROUND(HOURS, 2) AS VARCHAR)
        ELSE '' 
    END +
    CASE 
        WHEN Description IS NOT NULL THEN ' | ' + Description 
        ELSE ''
    END +
    CASE
        WHEN ReasonDescription = USERNAME THEN ' | Original User: ' + USERNAME --Doesnt currently work, Need to come back to.
        WHEN ReasonDescription IS NOT NULL THEN ' | Reason: ' + ReasonDescription 
        ELSE '' 
    END AS Description,
    FormattedTSDATETIME AS TSDATETIME,
    SourceTable
FROM RankedEdits
WHERE RowNum = 1
ORDER BY USERNAME, EmployeeName, EFFDATE;

Content Inventory

  • Doc File: content/docs/reports/users_information/user_edit_log.mdx
  • SQL Script: SQL/reports/users_information/user_edit_log.sql