Skip to main content

Status Codes

Employee status codes and filtering constants used for employee lifecycle management and reporting in the WorkPayCore frontend application.

Overview​

The status codes constants define the various states an employee can have within the system and provide filtering criteria for active employee identification. This ensures consistent employee status handling across all features and reports.

Employee Status Constants​

EMPLOYEE_STATUSES_CONSIDERED_ACTIVE​

Comma-separated string defining which employee statuses should be considered "active" for various business operations and reporting purposes.

export const EMPLOYEE_STATUSES_CONSIDERED_ACTIVE =
'ACTIVE,ON_LEAVE,ON_NOTICE_OF_EXIT';

Active Status Types:

  • ACTIVE: Employee is currently working and available
  • ON_LEAVE: Employee is on approved leave but still employed
  • ON_NOTICE_OF_EXIT: Employee has given notice but is still working

Use Cases:

  • Payroll processing inclusion
  • Active headcount reporting
  • Benefits eligibility checking
  • Access control decisions

Status Code Definitions​

Employee Lifecycle States​

While not explicitly defined in the constants file, the system recognizes these employee states:

Active States (Included in Active Filter)​

  • ACTIVE: Standard working status
  • ON_LEAVE: Temporary absence with job protection
  • ON_NOTICE_OF_EXIT: Resignation period

Inactive States (Excluded from Active Filter)​

  • TERMINATED: Employment ended by company
  • RESIGNED: Employee left voluntarily
  • SUSPENDED: Temporarily barred from work
  • PROBATION: Initial employment period
  • INACTIVE: General inactive status

Usage Examples​

Active Employee Filtering​

import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

const getActiveEmployees = employees => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

return employees.filter(employee => activeStatuses.includes(employee.status));
};

// Usage
const allEmployees = [
{ id: 1, name: 'John Doe', status: 'ACTIVE' },
{ id: 2, name: 'Jane Smith', status: 'ON_LEAVE' },
{ id: 3, name: 'Bob Johnson', status: 'TERMINATED' },
{ id: 4, name: 'Alice Brown', status: 'ON_NOTICE_OF_EXIT' },
];

const activeEmployees = getActiveEmployees(allEmployees);
// Returns: John Doe, Jane Smith, Alice Brown

Payroll Processing Filter​

import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

const PayrollProcessor = {
getEligibleEmployees: (employees, payrollDate) => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

return employees.filter(employee => {
// Check if employee is in active status
if (!activeStatuses.includes(employee.status)) {
return false;
}

// Additional checks for payroll eligibility
if (employee.status === 'ON_NOTICE_OF_EXIT') {
// Check if notice period hasn't ended yet
return new Date(employee.last_working_day) >= payrollDate;
}

if (employee.status === 'ON_LEAVE') {
// Check if it's paid leave
return employee.leave_type === 'PAID' || employee.include_in_payroll;
}

return true;
});
},

calculatePayroll: (employees, payrollDate) => {
const eligibleEmployees = PayrollProcessor.getEligibleEmployees(
employees,
payrollDate,
);

return eligibleEmployees.map(employee => ({
employee_id: employee.id,
status: employee.status,
base_salary: employee.base_salary,
adjustments: PayrollProcessor.getStatusAdjustments(employee),
}));
},

getStatusAdjustments: employee => {
switch (employee.status) {
case 'ON_LEAVE':
return {
leave_deduction:
employee.leave_type === 'UNPAID'
? employee.daily_rate * employee.leave_days
: 0,
};
case 'ON_NOTICE_OF_EXIT':
return {
notice_period_bonus: employee.notice_period_bonus || 0,
exit_benefits: employee.exit_benefits || 0,
};
default:
return {};
}
},
};

Employee Status Validation​

import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

const EmployeeStatusValidator = {
isActiveStatus: status => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');
return activeStatuses.includes(status);
},

canAccessSystem: employee => {
// Active employees can access the system
if (EmployeeStatusValidator.isActiveStatus(employee.status)) {
return true;
}

// Special cases for system access
const limitedAccessStatuses = ['SUSPENDED', 'PROBATION'];
return limitedAccessStatuses.includes(employee.status);
},

canReceiveBenefits: employee => {
// Only active status employees receive full benefits
return EmployeeStatusValidator.isActiveStatus(employee.status);
},

validateStatusTransition: (currentStatus, newStatus) => {
const validTransitions = {
PROBATION: ['ACTIVE', 'TERMINATED'],
ACTIVE: ['ON_LEAVE', 'ON_NOTICE_OF_EXIT', 'SUSPENDED', 'TERMINATED'],
ON_LEAVE: ['ACTIVE', 'TERMINATED'],
ON_NOTICE_OF_EXIT: ['RESIGNED', 'TERMINATED', 'ACTIVE'],
SUSPENDED: ['ACTIVE', 'TERMINATED'],
};

const allowedTransitions = validTransitions[currentStatus] || [];
return allowedTransitions.includes(newStatus);
},
};

Reporting and Analytics​

import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

const EmployeeReporting = {
getHeadcountReport: employees => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

const report = {
total_employees: employees.length,
active_employees: 0,
inactive_employees: 0,
status_breakdown: {},
};

employees.forEach(employee => {
const status = employee.status;

// Count by active/inactive
if (activeStatuses.includes(status)) {
report.active_employees++;
} else {
report.inactive_employees++;
}

// Count by specific status
report.status_breakdown[status] =
(report.status_breakdown[status] || 0) + 1;
});

return report;
},

getActiveEmployeesTrend: (employees, startDate, endDate) => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

// Group employees by status change date
const dailyTrend = {};

employees.forEach(employee => {
employee.status_history?.forEach(history => {
const date = history.change_date;

if (date >= startDate && date <= endDate) {
if (!dailyTrend[date]) {
dailyTrend[date] = { active: 0, inactive: 0 };
}

if (activeStatuses.includes(history.new_status)) {
dailyTrend[date].active++;
} else {
dailyTrend[date].inactive++;
}
}
});
});

return dailyTrend;
},
};

API Query Building​

import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

const EmployeeAPI = {
buildActiveEmployeesQuery: (additionalFilters = {}) => {
const baseQuery = {
status__in: EMPLOYEE_STATUSES_CONSIDERED_ACTIVE,
...additionalFilters,
};

return baseQuery;
},

fetchActiveEmployees: async (filters = {}) => {
const query = EmployeeAPI.buildActiveEmployeesQuery(filters);

const queryString = new URLSearchParams();
Object.entries(query).forEach(([key, value]) => {
queryString.append(key, value);
});

const response = await fetch(`/api/employees?${queryString}`);
return response.json();
},

fetchEmployeesByStatus: async statusFilter => {
let statusQuery;

if (statusFilter === 'active') {
statusQuery = { status__in: EMPLOYEE_STATUSES_CONSIDERED_ACTIVE };
} else if (statusFilter === 'inactive') {
statusQuery = { status__not_in: EMPLOYEE_STATUSES_CONSIDERED_ACTIVE };
} else {
statusQuery = { status: statusFilter };
}

return EmployeeAPI.fetchActiveEmployees(statusQuery);
},
};

React Hook for Status Management​

import { useState, useEffect } from 'react';
import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

const useEmployeeStatusFilter = employees => {
const [statusFilter, setStatusFilter] = useState('all');
const [filteredEmployees, setFilteredEmployees] = useState(employees);

useEffect(() => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

let filtered = employees;

switch (statusFilter) {
case 'active':
filtered = employees.filter(emp => activeStatuses.includes(emp.status));
break;
case 'inactive':
filtered = employees.filter(
emp => !activeStatuses.includes(emp.status),
);
break;
case 'all':
default:
filtered = employees;
break;
}

setFilteredEmployees(filtered);
}, [employees, statusFilter]);

return {
filteredEmployees,
statusFilter,
setStatusFilter,
activeCount: employees.filter(emp =>
EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',').includes(emp.status),
).length,
inactiveCount: employees.filter(
emp =>
!EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',').includes(emp.status),
).length,
};
};

// Usage in component
const EmployeeList = ({ employees }) => {
const {
filteredEmployees,
statusFilter,
setStatusFilter,
activeCount,
inactiveCount,
} = useEmployeeStatusFilter(employees);

return (
<div>
<div>
<button
onClick={() => setStatusFilter('all')}
className={statusFilter === 'all' ? 'active' : ''}
>
All ({employees.length})
</button>
<button
onClick={() => setStatusFilter('active')}
className={statusFilter === 'active' ? 'active' : ''}
>
Active ({activeCount})
</button>
<button
onClick={() => setStatusFilter('inactive')}
className={statusFilter === 'inactive' ? 'active' : ''}
>
Inactive ({inactiveCount})
</button>
</div>

<div>
{filteredEmployees.map(employee => (
<div key={employee.id}>
{employee.name} - {employee.status}
</div>
))}
</div>
</div>
);
};

Status Management Best Practices​

1. Consistent Status Checking​

// Always use the constant for active status checking
import { EMPLOYEE_STATUSES_CONSIDERED_ACTIVE } from '@/utils/constants/statuses';

// ✅ Good
const isActiveEmployee = employee => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');
return activeStatuses.includes(employee.status);
};

// ❌ Bad - hardcoded values
const isActiveEmployee = employee => {
return ['ACTIVE', 'ON_LEAVE'].includes(employee.status);
};

2. Status Transition Validation​

const validateStatusChange = (employee, newStatus, reason) => {
const currentStatus = employee.status;

// Validate the transition is allowed
if (
!EmployeeStatusValidator.validateStatusTransition(currentStatus, newStatus)
) {
throw new Error(
`Invalid status transition from ${currentStatus} to ${newStatus}`,
);
}

// Log the status change
console.log(
`Employee ${employee.id} status changed: ${currentStatus} → ${newStatus}`,
{
reason,
timestamp: new Date().toISOString(),
},
);

return true;
};

3. Status-Dependent Features​

const getEmployeePermissions = employee => {
const permissions = {
canAccessPortal: false,
canReceivePayroll: false,
canTakeLeave: false,
canAccessBenefits: false,
};

if (EmployeeStatusValidator.isActiveStatus(employee.status)) {
permissions.canAccessPortal = true;
permissions.canReceivePayroll = true;
permissions.canAccessBenefits = true;

if (employee.status === 'ACTIVE') {
permissions.canTakeLeave = true;
}
}

return permissions;
};

Status Code Extensions​

Custom Status Handling​

// Extend the active statuses for specific use cases
const getActiveStatusesForContext = context => {
const baseStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

switch (context) {
case 'benefits':
// Benefits might include probation employees
return [...baseStatuses, 'PROBATION'];
case 'training':
// Training might include suspended employees
return [...baseStatuses, 'SUSPENDED'];
case 'payroll':
default:
return baseStatuses;
}
};

Status-Based Styling​

const getStatusColor = status => {
const activeStatuses = EMPLOYEE_STATUSES_CONSIDERED_ACTIVE.split(',');

if (activeStatuses.includes(status)) {
return (
{
ACTIVE: '#10B981', // Green
ON_LEAVE: '#F59E0B', // Yellow
ON_NOTICE_OF_EXIT: '#EF4444', // Red
}[status] || '#10B981'
);
}

return '#6B7280'; // Gray for inactive statuses
};

const StatusBadge = ({ status }) => {
const color = getStatusColor(status);

return (
<span
style={{
backgroundColor: color,
color: 'white',
padding: '2px 8px',
borderRadius: '4px',
}}
>
{status.replace(/_/g, ' ')}
</span>
);
};


TypeScript Definitions​

type ActiveEmployeeStatus = 'ACTIVE' | 'ON_LEAVE' | 'ON_NOTICE_OF_EXIT';
type InactiveEmployeeStatus =
| 'TERMINATED'
| 'RESIGNED'
| 'SUSPENDED'
| 'PROBATION'
| 'INACTIVE';
type EmployeeStatus = ActiveEmployeeStatus | InactiveEmployeeStatus;

export const EMPLOYEE_STATUSES_CONSIDERED_ACTIVE: string;

interface Employee {
id: number;
name: string;
status: EmployeeStatus;
last_working_day?: string;
leave_type?: 'PAID' | 'UNPAID';
include_in_payroll?: boolean;
}

interface StatusTransition {
from_status: EmployeeStatus;
to_status: EmployeeStatus;
change_date: string;
reason?: string;
}

Migration Notes​

Adding New Status Types​

When adding new employee statuses:

  1. Determine if the status is active or inactive
  2. Update the EMPLOYEE_STATUSES_CONSIDERED_ACTIVE constant if needed
  3. Add validation rules for status transitions
  4. Update UI components to handle the new status
  5. Test payroll and benefits calculations with the new status

Status Consolidation​

When consolidating or removing status types:

  1. Create migration mapping for existing data
  2. Update the active statuses constant
  3. Test all status-dependent features
  4. Update documentation and user interfaces
  5. Provide transition period for data migration

These status code constants ensure consistent employee lifecycle management across the WorkPayCore frontend application while providing clear business rules for employee classification and processing.