Commit f61ceb27 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix(hr-seeds): fix department type constraint + create employee login accounts

- Phase_05_001: changed department_type from 'edara' to 'idara' (CHECK constraint only allows 'idara'/'qism')
- Phase_05_002: create employees table records before hr_employee_profiles to satisfy FK constraint
  - Generates unique usernames (emp0001, emp0002, ...)
  - Sets default password 'Club@2026' with force_password_change=1
  - Links hr_employee_profiles.employee_id to newly created employees.id
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 23dd0208
...@@ -29,7 +29,7 @@ return function (Database $db): void { ...@@ -29,7 +29,7 @@ return function (Database $db): void {
if (!$existing) { if (!$existing) {
$db->insert('hr_departments', [ $db->insert('hr_departments', [
'department_code' => $dept['code'], 'department_code' => $dept['code'],
'department_type' => 'edara', 'department_type' => 'idara',
'name_ar' => $dept['name_ar'], 'name_ar' => $dept['name_ar'],
'name_en' => $dept['name_en'], 'name_en' => $dept['name_en'],
'parent_id' => null, 'parent_id' => null,
......
...@@ -38,6 +38,9 @@ return function (Database $db): void { ...@@ -38,6 +38,9 @@ return function (Database $db): void {
$titleMap[$row['name_ar']] = (int) $row['id']; $titleMap[$row['name_ar']] = (int) $row['id'];
} }
// Default password hash (will force change on first login)
$defaultPassword = password_hash('Club@2026', PASSWORD_BCRYPT);
// Get next employee_number sequence // Get next employee_number sequence
$lastNum = $db->selectOne( $lastNum = $db->selectOne(
"SELECT employee_number FROM hr_employee_profiles ORDER BY CAST(SUBSTRING(employee_number, 4) AS UNSIGNED) DESC LIMIT 1", "SELECT employee_number FROM hr_employee_profiles ORDER BY CAST(SUBSTRING(employee_number, 4) AS UNSIGNED) DESC LIMIT 1",
...@@ -60,7 +63,7 @@ return function (Database $db): void { ...@@ -60,7 +63,7 @@ return function (Database $db): void {
continue; continue;
} }
// Skip if already exists by national_id or employee_code // Skip if already exists by national_id
if ($nationalId) { if ($nationalId) {
$exists = $db->selectOne( $exists = $db->selectOne(
"SELECT id FROM hr_employee_profiles WHERE national_id = ? AND is_archived = 0", "SELECT id FROM hr_employee_profiles WHERE national_id = ? AND is_archived = 0",
...@@ -74,14 +77,10 @@ return function (Database $db): void { ...@@ -74,14 +77,10 @@ return function (Database $db): void {
// Parse name (full name in one field) // Parse name (full name in one field)
$fullName = trim($emp['name']); $fullName = trim($emp['name']);
$nameParts = preg_split('/\s+/', $fullName, 2);
$firstName = $nameParts[0] ?? $fullName;
$lastName = $nameParts[1] ?? '';
// Clean leading title prefixes (ك/, ك /) // Clean leading title prefixes (ك/, ك /)
$firstName = preg_replace('/^ك\s*\/\s*/', '', $firstName);
$fullName = preg_replace('/^ك\s*\/\s*/', '', $fullName); $fullName = preg_replace('/^ك\s*\/\s*/', '', $fullName);
$nameParts = preg_split('/\s+/', trim($fullName), 2); $fullName = trim($fullName);
$nameParts = preg_split('/\s+/', $fullName, 2);
$firstName = $nameParts[0] ?? $fullName; $firstName = $nameParts[0] ?? $fullName;
$lastName = $nameParts[1] ?? ''; $lastName = $nameParts[1] ?? '';
...@@ -93,8 +92,29 @@ return function (Database $db): void { ...@@ -93,8 +92,29 @@ return function (Database $db): void {
// Employee number // Employee number
$employeeNumber = 'EMP' . str_pad((string) $nextSeq, 4, '0', STR_PAD_LEFT); $employeeNumber = 'EMP' . str_pad((string) $nextSeq, 4, '0', STR_PAD_LEFT);
// Generate unique username from employee code or number
$username = 'emp' . str_pad((string) $nextSeq, 4, '0', STR_PAD_LEFT);
$existingUser = $db->selectOne("SELECT id FROM employees WHERE username = ?", [$username]);
if ($existingUser) {
$username = 'emp' . $nextSeq . '_' . time();
}
$nextSeq++; $nextSeq++;
// Create system login account (employees table)
$employeeId = $db->insert('employees', [
'username' => $username,
'password_hash' => $defaultPassword,
'full_name_ar' => $fullName,
'phone' => $emp['phone'] ?: null,
'is_active' => 1,
'force_password_change' => 1,
'failed_login_count' => 0,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
// Workforce type mapping // Workforce type mapping
$workforceType = match ($emp['workforce_type']) { $workforceType = match ($emp['workforce_type']) {
'insured' => 'insured', 'insured' => 'insured',
...@@ -131,7 +151,7 @@ return function (Database $db): void { ...@@ -131,7 +151,7 @@ return function (Database $db): void {
} }
$data = [ $data = [
'employee_id' => 0, 'employee_id' => $employeeId,
'employee_number' => $employeeNumber, 'employee_number' => $employeeNumber,
'fingerprint_code' => $emp['employee_code'] ?: null, 'fingerprint_code' => $emp['employee_code'] ?: null,
'first_name_ar' => $firstName, 'first_name_ar' => $firstName,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment