LOW Payroll Export (Version 2)
Documentation for the LOW Payroll Export (Version 2) script that generates an export file for LOW payroll system
Download Alternative Formats
📥 Browser Export Format:
- Download Export File - Download this export for external processing
Parameters
{mindate}- Start date for the export period (commented out in sample, example: '2025-03-01'){maxdate}- End date for the export period (commented out in sample, example: '2025-03-31')- Multiple configurable parameters:
@HideRatesSalPayclass- Comma-delimited list of pay classes for which rates should be hidden@PayClassFilter- Filter by pay class (default: '*' for all)@TimeLocFilter- Filter by time location (default: '*' for all)@ExportingPDs- Pay designations to include in export@PDDecriptions- Pay designations to show descriptions for@OnlyEvents- Toggle to show only events (0=off, 1=on)@MyEmployees- Toggle to apply user access filtering (0=off, 1=on, default: on)@SpecialRateDist- Special rate distribution values- Pay type category parameters (
@OT,@SOT,@DBL, etc.)
Data Components
The report dynamically categorizes hours into attendance types based on configurable parameters:
- Regular Hours - Based on special rate distribution or default
- Event Hours - When WG7 name starts with '*'
- Overtime Hours - Based on pay designations in
@OTparameter - Straight Overtime - Based on pay designations in
@SOTparameter - Double Time - Based on pay designations in
@DBLparameter - Absence - Based on pay designations in
@ABSparameter - Comp Time (Earned) - Based on pay designations in
@CompEparameter - Comp Time (Paid) - Based on pay designations in
@CompPparameter - Unpaid - Based on pay designations in
@Unpaidparameter - Event - Based on pay designations in
@HEventparameter
Output Format
The export generates the following columns:
- Pay Record ID - ID with 'B' suffix removed and workgroup added
- Attendance Type - Dynamically determined based on parameters
- Attendance Date
- Absence - NULL in this version
- Days/Hours
- Work Location - From WG5
- Work Pay Group - NULL in this version
- Comment - NULL in this version
- Description - Based on WG7 name or pay designation
- Special Rate/Distribution
- Special Rate - Conditionally shown based on pay class
- Special Distribution - NULL in this version
Employee Access Control
The @MyEmployees parameter provides user-based access control:
- When enabled (1): Results are filtered to only include employees the user has access to based on the USERACCESS table
- When disabled (0): All employees meeting other criteria are included regardless of user permissions
- Access Logic: Checks user permissions across all workgroup levels (WG1-WG7), where users have access if:
- They have specific access to that workgroup, OR
- They have universal access (when workgroup value = 0)
- Default Setting: Enabled (1) for security by default
Technical Implementation
The script features:
- Extensive parameterization with STRING_SPLIT for flexible configuration
- Dynamic attendance type categorization through CASE expressions
- Special handling for employee IDs ending with 'B'
- TRY_CAST to safely handle parameter values
- Complex filtering options:
- By date range
- By pay designation
- By work location
- By pay class
- By event flag
- By user access permissions (when
@MyEmployeesis enabled)
- Exclusion of test employee ID (999999999)
- Only active employees (ACTIVESTATUS=0)
Improvements Over V1
- Fully parameterized configuration without hard-coded values
- Dynamic attendance type categorization
- Flexible filtering options
- Special handling for employee IDs ending with 'B'
- More comprehensive event handling
- Consolidated single-query approach vs. multiple INSERTs
- Better description handling with pay designation names
- User-based access control with
@MyEmployeesparameter
T-SQL
DECLARE @MIN DATE, @MAX DATE
SET @MIN={mindate}
SET @MAX={maxdate}
--------Parameters Section----------
DECLARE @HideRatesSalPayclass NVARCHAR(MAX) = '99'
DECLARE @PayClassFilter NVARCHAR(MAX) = '*'
DECLARE @TimeLocFilter NVARCHAR(MAX) = '*'
DECLARE @ExportingPDs NVARCHAR(MAX) = '1,2,3,4,5,7,9,10,11,12,13,16,18,19,20,21,22,23,24,25,26,27,30'
DECLARE @PDDecriptions NVARCHAR(MAX) = '3,4,5,7,9,10,11,13,16,18,19,20,21,22,23,24,25,26,27,30'
DECLARE @OnlyEvents BIT = 0 -- 0 = OFF, 1 = ON
DECLARE @MyEmployees BIT = 1 -- 0 = OFF, 1 = ON
DECLARE @SpecialRateDist NVARCHAR(MAX) = '*'
DECLARE @OT NVARCHAR(MAX) = '2,19'
DECLARE @SOT NVARCHAR(MAX) = '12'
DECLARE @DBL NVARCHAR(MAX) = '*'
DECLARE @ABS NVARCHAR(MAX) = '*'
DECLARE @CompE NVARCHAR(MAX) = '*'
DECLARE @CompP NVARCHAR(MAX) = '*'
DECLARE @Unpaid NVARCHAR(MAX) = '11,24'
DECLARE @HEvent NVARCHAR(MAX) = '13'
SELECT
CONCAT(
CASE WHEN RIGHT(E.IDNUM,1)='B' THEN LEFT(E.IDNUM,LEN(E.IDNUM)-1) ELSE E.IDNUM END,
'-0',
CONVERT(VARCHAR, pd.WG6)
) AS 'Pay Record ID',
CASE
WHEN PD.WG7 IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@SpecialRateDist, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'Regular'
WHEN WG7.name LIKE '[*]%' THEN 'Event'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@OT, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'Overtime'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@SOT, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'STR OT'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@DBL, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'DoubleTime'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@ABS, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'Absence'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@CompE, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'CompTime (Earned)'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@CompP, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'CompTime Paid'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@Unpaid, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'Unpaid'
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@HEvent, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN 'Event'
ELSE 'Regular'
END AS 'Attendance Type',
pd.EVENTDATE AS 'Attendance Date',
NULL AS Absence,
pd.HOURS AS 'Days/Hours',
WG5.NAME AS 'Work Location',
NULL AS 'Work Pay Group',
NULL AS 'Comment',
CASE
WHEN PD.WG7 IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@SpecialRateDist, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN NULL
WHEN WG7.name LIKE '[*]%' THEN RIGHT(WG7.name, LEN(WG7.Name) - 1)
WHEN pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@PDDecriptions, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN PDS.NAME
ELSE NULL
END AS 'Description',
CASE
WHEN PD.WG7 IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@SpecialRateDist, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
) THEN RIGHT(WG7.name, LEN(WG7.Name) - 1)
ELSE NULL
END AS 'Special Rate/Dist',
CASE
WHEN @HideRatesSalPayclass IS NOT NULL AND @HideRatesSalPayclass <> ''
AND e.PAYCLASS IN (
SELECT value
FROM STRING_SPLIT(@HideRatesSalPayclass, ',')
) THEN NULL
ELSE pd.RATE
END AS 'Special Rate',
NULL AS 'Special Distribution'
FROM PAYDESHIST PD
INNER JOIN EMPLOYEES E ON E.FILEKEY = PD.FILEKEY
INNER JOIN WORKGROUP5 WG5 ON PD.WG5 = WG5.WGNUM
INNER JOIN WORKGROUP7 WG7 ON PD.WG7 = WG7.WGNUM
INNER JOIN PAYDESIGNATIONS PDS ON PD.PAYDESNUM = PDS.PAYDESNUM
WHERE pd.EVENTDATE BETWEEN @MIN AND @MAX
AND pd.PAYDESNUM IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@ExportingPDs, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
)
AND (
@OnlyEvents = 0 -- If @OnlyEvents is OFF, ignore WG7.name check
OR
(
WG7.name LIKE '[*]%' -- Always include WG7.name starting with *
OR
pd.PAYDESNUM IN ( -- Include PDs listed in @OT, @SOT, or @DBL
SELECT TRY_CAST(value AS INT)
FROM (
SELECT value
FROM STRING_SPLIT(@OT, ',')
-- Split @OT
UNION ALL
SELECT value
FROM STRING_SPLIT(@SOT, ',')
-- Split @SOT
UNION ALL
SELECT value
FROM STRING_SPLIT(@DBL, ',') -- Split @DBL
) AS CombinedPDs
WHERE TRY_CAST(value AS INT) IS NOT NULL -- Ignore non-integer values (e.g., '*')
)
)
)
AND e.idnum != '999999999'
AND e.ACTIVESTATUS=0
AND (
@TimeLocFilter = '*'
OR pd.WG5 IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@TimeLocFilter, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
)
)
AND (
@PayClassFilter = '*'
OR e.payclass IN (
SELECT TRY_CAST(value AS INT)
FROM STRING_SPLIT(@PayClassFilter, ',')
WHERE TRY_CAST(value AS INT) IS NOT NULL
)
)
AND (
@MyEmployees = 0 -- If @MyEmployees is OFF, ignore employee access check
OR
(
(SELECT COUNT(*)
FROM USERACCESS U
WHERE (U.USERID={userid}) AND (((U.WG1=E.WG1) OR (U.WG1=0)) AND ((U.WG2=E.WG2) OR (U.WG2=0)) AND ((U.WG3=E.WG3) OR (U.WG3=0)) AND ((U.WG4=E.WG4) OR (U.WG4=0)) AND ((U.WG5=E.WG5) OR (U.WG5=0)) AND ((U.WG6=E.WG6) OR (U.WG6=0)) AND ((U.WG7=E.WG7) OR (U.WG7=0))))>0
)
)
ORDER BY 1,3;Content Inventory
- Doc File:
content/docs/payroll_exports/low_payroll_export_v2.mdx - SQL Script:
SQL/payroll_exports/low_payroll_export_v2.sql