Files
hr/app/Services/Import/EmployeeImportTransformer.php
2026-07-30 17:24:40 +05:00

157 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Import;
use App\DTOs\Import\EmployeeRowDto;
use App\Enums\EmploymentStatus;
use App\Enums\Gender;
use App\Models\Department;
use App\Models\Employee;
use App\Models\Position;
use App\Models\Shift;
use Carbon\Carbon;
use Illuminate\Support\Str;
class EmployeeImportTransformer
{
/**
* @return array<string, mixed>
*/
public function toAttributes(EmployeeRowDto $dto): array
{
return [
'employee_number' => $dto->employeeNumber,
'full_name' => $dto->fullName,
'national_id' => $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<int, string>
*/
public function validate(EmployeeRowDto $dto): array
{
$errors = [];
if ($dto->employeeNumber === '') {
$errors[] = 'Employee number is required.';
}
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.";
}
return $errors;
}
public function isDuplicate(EmployeeRowDto $dto): bool
{
return Employee::query()
->where(function ($query) use ($dto): void {
$query->where('employee_number', $dto->employeeNumber);
if ($dto->nationalId) {
$query->orWhere('national_id', $dto->nationalId);
}
})
->exists();
}
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;
}
}
}