100 lines
2.6 KiB
PHP
100 lines
2.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\Import;
|
|
|
|
use App\DTOs\Import\BonusRowDto;
|
|
use App\Enums\BonusType;
|
|
use App\Models\Bonus;
|
|
use App\Models\Employee;
|
|
use Illuminate\Support\Str;
|
|
|
|
class BonusImportTransformer
|
|
{
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function toAttributes(BonusRowDto $dto): array
|
|
{
|
|
return [
|
|
'employee_id' => $this->resolveEmployeeId($dto->employeeNumber),
|
|
'bonus_date' => $this->parseDate($dto->bonusDate),
|
|
'bonus_type' => $this->resolveBonusType($dto->bonusType),
|
|
'amount' => $dto->amount ?? 0,
|
|
'reason' => $dto->reason,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
public function validate(BonusRowDto $dto): array
|
|
{
|
|
$errors = [];
|
|
|
|
if ($dto->employeeNumber === '') {
|
|
$errors[] = 'Employee number is required.';
|
|
} elseif ($this->resolveEmployeeId($dto->employeeNumber) === null) {
|
|
$errors[] = "Employee \"{$dto->employeeNumber}\" was not found.";
|
|
}
|
|
|
|
if ($dto->bonusDate === null) {
|
|
$errors[] = 'Bonus date is required.';
|
|
}
|
|
|
|
if ($dto->amount === null) {
|
|
$errors[] = 'Amount is required.';
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
public function isDuplicate(BonusRowDto $dto): bool
|
|
{
|
|
$employeeId = $this->resolveEmployeeId($dto->employeeNumber);
|
|
$bonusDate = $this->parseDate($dto->bonusDate);
|
|
|
|
if ($employeeId === null || $bonusDate === null || $dto->amount === null) {
|
|
return false;
|
|
}
|
|
|
|
return Bonus::query()
|
|
->where('employee_id', $employeeId)
|
|
->whereDate('bonus_date', $bonusDate)
|
|
->where('amount', $dto->amount)
|
|
->exists();
|
|
}
|
|
|
|
private function resolveEmployeeId(string $employeeNumber): ?int
|
|
{
|
|
return Employee::query()
|
|
->where('employee_number', $employeeNumber)
|
|
->value('id');
|
|
}
|
|
|
|
private function resolveBonusType(?string $value): BonusType
|
|
{
|
|
if ($value === null || trim($value) === '') {
|
|
return BonusType::Other;
|
|
}
|
|
|
|
$normalized = Str::lower(trim($value));
|
|
|
|
return BonusType::tryFrom($normalized) ?? BonusType::Other;
|
|
}
|
|
|
|
private function parseDate(?string $value): ?string
|
|
{
|
|
if ($value === null || trim($value) === '') {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return \Carbon\Carbon::parse($value)->toDateString();
|
|
} catch (\Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|