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.