systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; require_once SYSTEMPATH . 'Config/DotEnv.php'; (new CodeIgniter\Config\DotEnv(ROOTPATH))->load(); defined('ENVIRONMENT') || define('ENVIRONMENT', env('CI_ENVIRONMENT', 'development')); $boot = APPPATH . 'Config/Boot/' . ENVIRONMENT . '.php'; if (is_file($boot)) { require_once $boot; } helper('excel_util_helper'); use App\Controllers\EmployeeServiceController; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xls; $pass = 0; $fail = 0; $results = []; function ok(string $label, bool $cond, string $detail = ''): void { global $pass, $fail, $results; if ($cond) { $pass++; $results[] = '[PASS] ' . $label . ($detail ? " — {$detail}" : ''); } else { $fail++; $results[] = '[FAIL] ' . $label . ($detail ? " — {$detail}" : ''); } } function getDeletionExcelColumns(EmployeeServiceController $controller): array { $property = new ReflectionProperty($controller, 'deletion_excel_columns'); $property->setAccessible(true); return $property->getValue($controller); } function deletionColumnCountIsValid(array $columnsToCheck, array $excelHeaderRow): bool { $totalDefinedColumns = count($columnsToCheck); $excelColumnsCount = count($excelHeaderRow); $optionalColumnCount = 0; foreach ($columnsToCheck as $columnConfig) { if (!empty($columnConfig['is_column_optional'])) { $optionalColumnCount++; } } $minRequiredColumns = $totalDefinedColumns - $optionalColumnCount; if ($optionalColumnCount > 0) { return $excelColumnsCount >= $minRequiredColumns && $excelColumnsCount <= $totalDefinedColumns; } return $excelColumnsCount === $totalDefinedColumns; } function validateDeletionRowClaimStatus(array $columnsToCheck, array $row, string $currentColumnAction = 'D'): array { $result = ['error_summary' => [], 'error_data' => []]; $keys = array_keys($columnsToCheck); $rowKey = 2; foreach ($row as $colKey => $col) { if (!isset($keys[$colKey])) { continue; } $isMandatory = $columnsToCheck[$keys[$colKey]]['is_mandatory']; $allowedValues = $columnsToCheck[$keys[$colKey]]['allowed_values']; $columnName = $columnsToCheck[$keys[$colKey]]['col_name']; $columnIndex = $columnsToCheck[$keys[$colKey]]['col_idx']; if (is_bool($isMandatory) && $isMandatory === true && ($col === '' || $col === null)) { $result['error_summary'][] = 1; $result['error_data'][$rowKey][$keys[$colKey]]['error'][] = 'Value is mandatory'; } if ( $currentColumnAction !== null && is_array($isMandatory) && in_array(strtoupper(trim($currentColumnAction)), $isMandatory, true) && ($col === '' || $col === null) ) { $result['error_summary'][] = 1; $result['error_data'][$rowKey][$keys[$colKey]]['error'][] = 'Value is mandatory for this action/event'; } if ( ($isMandatory === true && isset($allowedValues) && is_array($allowedValues)) || (is_array($isMandatory) && isset($allowedValues) && is_array($allowedValues)) ) { if (!in_array(trim((string) $col), $allowedValues, true)) { $result['error_summary'][] = 3; $result['error_data'][$rowKey][$keys[$colKey]]['col_name'] = $columnName; $result['error_data'][$rowKey][$keys[$colKey]]['col_idx'] = $columnIndex; $result['error_data'][$rowKey][$keys[$colKey]]['error'][] = 'Value not allowed'; } } } return $result; } $controller = new EmployeeServiceController(); $deletionColumns = getDeletionExcelColumns($controller); $claimStatusColumn = $deletionColumns['claim_status'] ?? []; $headerWithClaim = ['S.No', 'EMP ID', 'NAME OF EMP/DEP', 'Change event', 'Date of exit', 'Reason for exit', 'Claim status']; $headerWithoutClaim = ['S.No', 'EMP ID', 'NAME OF EMP/DEP', 'Change event', 'Date of exit', 'Reason for exit']; $sampleRowWithEmptyClaim = ['1', 'EMP001', 'Test Employee', 'deletion', '19-May-2026', 'Resigned', '']; $sampleRowWithoutClaimCol = ['1', 'EMP001', 'Test Employee', 'deletion', '19-May-2026', 'Resigned']; ok('claim_status is not mandatory', ($claimStatusColumn['is_mandatory'] ?? null) === false); ok('claim_status column is optional', !empty($claimStatusColumn['is_column_optional'])); ok( 'claim_status has no allowed_values constraint', !array_key_exists('allowed_values', $claimStatusColumn) || $claimStatusColumn['allowed_values'] === null ); ok('7-column header passes column count check', deletionColumnCountIsValid($deletionColumns, $headerWithClaim)); ok('6-column header passes column count check', deletionColumnCountIsValid($deletionColumns, $headerWithoutClaim)); ok('5-column header fails column count check', !deletionColumnCountIsValid($deletionColumns, array_slice($headerWithoutClaim, 0, 5))); ok('8-column header fails column count check', !deletionColumnCountIsValid($deletionColumns, array_merge($headerWithClaim, ['Extra']))); $mismatchWithoutClaim = check_columns_name($deletionColumns, $headerWithoutClaim); ok('header without Claim status has no column-name mismatch', count($mismatchWithoutClaim) === 0); $mismatchWithClaim = check_columns_name($deletionColumns, $headerWithClaim); ok('header with Claim status has no column-name mismatch', count($mismatchWithClaim) === 0); $wrongHeader = $headerWithoutClaim; $wrongHeader[5] = 'Wrong reason column'; $mismatchWrong = check_columns_name($deletionColumns, $wrongHeader); ok('wrong required header is still detected', count($mismatchWrong) > 0); $rowErrorsEmptyClaim = validateDeletionRowClaimStatus($deletionColumns, $sampleRowWithEmptyClaim); ok( 'empty Claim status value does not fail row validation', count($rowErrorsEmptyClaim['error_summary']) === 0, 'errors=' . count($rowErrorsEmptyClaim['error_summary']) ); $rowErrorsMissingClaimCol = validateDeletionRowClaimStatus($deletionColumns, $sampleRowWithoutClaimCol); ok( 'missing Claim status column does not fail row validation', count($rowErrorsMissingClaimCol['error_summary']) === 0, 'errors=' . count($rowErrorsMissingClaimCol['error_summary']) ); $tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR; $tempFileSixCols = $tempDir . 'smoke_deletion_6cols_' . date('Ymd_His') . '.xls'; $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); foreach ($headerWithoutClaim as $idx => $header) { $sheet->setCellValue(chr(65 + $idx) . '1', $header); } foreach ($sampleRowWithoutClaimCol as $idx => $value) { $sheet->setCellValue(chr(65 + $idx) . '2', $value); } $writer = new Xls($spreadsheet); $writer->save($tempFileSixCols); $loadedSpreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($tempFileSixCols); $loadedSheet = $loadedSpreadsheet->getActiveSheet(); $loadedHeader = $loadedSheet->rangeToArray('A1:F1')[0]; $loadedRow = $loadedSheet->rangeToArray('A2:F2')[0]; ok('generated 6-column xls header count is 6', count($loadedHeader) === 6); ok('generated 6-column xls passes column count rule', deletionColumnCountIsValid($deletionColumns, $loadedHeader)); ok('generated 6-column xls passes header-name check', count(check_columns_name($deletionColumns, $loadedHeader)) === 0); ok( 'generated 6-column xls row has no claim_status validation errors', count(validateDeletionRowClaimStatus($deletionColumns, $loadedRow)['error_summary']) === 0 ); @unlink($tempFileSixCols); echo PHP_EOL . implode(PHP_EOL, $results) . PHP_EOL; echo PHP_EOL . "Summary: {$pass} passed, {$fail} failed" . PHP_EOL; exit($fail > 0 ? 1 : 0);