2026-05-11 13:30:24 +03:00

185 lines
5.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Repositories;
use App\Models\Leave;
use App\Models\LeaveHistory;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Collection;
class LeaveRepository extends BaseRepository implements LeaveRepositoryInterface
{
public function __construct(Leave $model)
{
parent::__construct($model);
}
public function all(array $columns = ['*']): Collection
{
return $this->model->newQuery()
->with(['employee', 'approver', 'histories.user'])
->orderByDesc('start_date')
->get($columns);
}
public function find(int|string $id, array $columns = ['*']): ?Model
{
return $this->model->newQuery()
->with(['employee', 'approver', 'histories.user'])
->find($id, $columns);
}
public function create(array $attributes): Model
{
try {
DB::beginTransaction();
/** @var Leave $leave */
$leave = $this->model->newQuery()->create($attributes);
$this->recordHistory(
$leave,
null,
$leave->status,
$attributes['approved_by'] ?? null,
$attributes['notes'] ?? null
);
DB::commit();
return $leave->load(['employee', 'approver', 'histories.user']);
} catch (Exception $e) {
DB::rollBack();
Log::error('Error creating leave: ' . $e->getMessage(), [
'attributes' => $attributes,
'exception' => $e,
]);
throw $e;
}
}
public function update(int|string $id, array $attributes): bool
{
try {
DB::beginTransaction();
/** @var Leave|null $leave */
$leave = $this->model->newQuery()->find($id);
if (!$leave) {
DB::rollBack();
return false;
}
$oldStatus = $leave->status;
$result = $leave->fill($attributes)->save();
if (array_key_exists('status', $attributes) && $attributes['status'] !== $oldStatus) {
$this->recordHistory(
$leave,
$oldStatus,
$leave->status,
$attributes['approved_by'] ?? $leave->approved_by,
$attributes['notes'] ?? null
);
}
DB::commit();
return $result;
} catch (Exception $e) {
DB::rollBack();
Log::error('Error updating leave with ID ' . $id . ': ' . $e->getMessage(), [
'id' => $id,
'attributes' => $attributes,
'exception' => $e,
]);
throw $e;
}
}
public function getPaginated(int $perPage = 10, array $filters = []): array
{
$query = $this->model->newQuery()->with(['employee', 'approver', 'histories.user']);
if (!empty($filters['employee_id'])) {
$query->where('employee_id', (int) $filters['employee_id']);
}
if (!empty($filters['type'])) {
$query->where('type', $filters['type']);
}
if (!empty($filters['status'])) {
$query->where('status', $filters['status']);
}
if (!empty($filters['start_date'])) {
$query->whereDate('start_date', '>=', $filters['start_date']);
}
if (!empty($filters['end_date'])) {
$query->whereDate('end_date', '<=', $filters['end_date']);
}
if (!empty($filters['search'])) {
$search = (string) $filters['search'];
$query->where(function ($subQuery) use ($search) {
$subQuery->where('reason', 'like', '%' . $search . '%')
->orWhere('notes', 'like', '%' . $search . '%')
->orWhereHas('employee', function ($employeeQuery) use ($search) {
$employeeQuery->where('first_name', 'like', '%' . $search . '%')
->orWhere('last_name', 'like', '%' . $search . '%')
->orWhere('email', 'like', '%' . $search . '%');
});
});
}
$sortField = $filters['sort_by'] ?? 'start_date';
$sortDirection = $filters['sort_direction'] ?? 'desc';
$allowedSortFields = ['start_date', 'end_date', 'status', 'type', 'created_at'];
if (!in_array($sortField, $allowedSortFields, true)) {
$sortField = 'start_date';
}
$sortDirection = strtolower((string) $sortDirection) === 'asc' ? 'asc' : 'desc';
$paginator = $query
->orderBy($sortField, $sortDirection)
->paginate($perPage);
return [
'leaves' => $paginator->getCollection(),
'pagination' => [
'current_page' => $paginator->currentPage(),
'last_page' => $paginator->lastPage(),
'per_page' => $paginator->perPage(),
'total' => $paginator->total(),
'from' => $paginator->firstItem(),
'to' => $paginator->lastItem(),
],
];
}
private function recordHistory(
Leave $leave,
?string $oldStatus,
string $newStatus,
int|string|null $changedBy = null,
?string $comment = null
): void {
LeaveHistory::query()->create([
'leave_id' => $leave->id,
'old_status' => $oldStatus,
'new_status' => $newStatus,
'changed_by' => $changedBy,
'changed_at' => now(),
'comment' => $comment,
]);
}
}