*/ public function toAttributes(EmployeeRowDto $dto): array { return [ 'employee_number' => $dto->employeeNumber !== '' ? $dto->employeeNumber : null, 'full_name' => $dto->fullName, 'national_id' => $this->resolveNationality($dto->nationalId), 'gender' => $this->resolveGender($dto->gender), 'birth_date' => $this->parseDate($dto->birthDate), 'phone' => $dto->phone ?? config('hr.default_phone'), 'address' => $dto->address, 'department_id' => $this->resolveDepartmentId($dto->department), 'position_id' => $this->resolvePositionId($dto->position), 'shift_id' => $this->resolveShiftId($dto->shift), 'employment_status' => $this->resolveEmploymentStatus($dto->employmentStatus), 'hire_date' => $this->parseDate($dto->hireDate), 'notes' => $dto->notes, ]; } /** * @return array */ public function validate(EmployeeRowDto $dto): array { $errors = []; if ($dto->fullName === '') { $errors[] = 'Full name is required.'; } if ($dto->department && $this->resolveDepartmentId($dto->department) === null) { $errors[] = "Department \"{$dto->department}\" was not found."; } if ($dto->position && $this->resolvePositionId($dto->position) === null) { $errors[] = "Position \"{$dto->position}\" was not found."; } if ($dto->shift && $this->resolveShiftId($dto->shift) === null) { $errors[] = "Shift \"{$dto->shift}\" was not found."; } if ($dto->nationalId && $this->resolveNationality($dto->nationalId) === null) { $errors[] = "Nationality \"{$dto->nationalId}\" was not found."; } return $errors; } public function isDuplicate(EmployeeRowDto $dto): bool { $hasEmployeeNumber = $dto->employeeNumber !== ''; $nationality = $this->resolveNationality($dto->nationalId); if (! $hasEmployeeNumber && $nationality === null) { return false; } return Employee::query() ->where(function ($query) use ($dto, $hasEmployeeNumber, $nationality): void { if ($hasEmployeeNumber) { $query->where('employee_number', $dto->employeeNumber); } if ($nationality !== null) { $hasEmployeeNumber ? $query->orWhere('national_id', $nationality) : $query->where('national_id', $nationality); } }) ->exists(); } private function resolveNationality(?string $value): ?string { return Countries::resolve($value); } private function resolveGender(?string $value): ?Gender { if ($value === null) { return null; } $normalized = Str::lower(trim($value)); return Gender::tryFrom($normalized) ?? match ($normalized) { 'm', 'man' => Gender::Male, 'f', 'woman' => Gender::Female, default => null, }; } private function resolveEmploymentStatus(?string $value): EmploymentStatus { if ($value === null || trim($value) === '') { return EmploymentStatus::Active; } $normalized = Str::lower(str_replace(' ', '_', trim($value))); return EmploymentStatus::tryFrom($normalized) ?? EmploymentStatus::Active; } private function resolveDepartmentId(?string $value): ?int { if ($value === null || trim($value) === '') { return null; } return Department::query() ->where('name', $value) ->orWhere('code', $value) ->value('id'); } private function resolvePositionId(?string $value): ?int { if ($value === null || trim($value) === '') { return null; } return Position::query()->where('name', $value)->value('id'); } private function resolveShiftId(?string $value): ?int { if ($value === null || trim($value) === '') { return null; } return Shift::query() ->where('name', $value) ->orWhere('code', $value) ->value('id'); } private function parseDate(?string $value): ?string { if ($value === null || trim($value) === '') { return null; } try { return Carbon::parse($value)->toDateString(); } catch (\Throwable) { return null; } } }