185 lines
5.7 KiB
PHP
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,
|
|
]);
|
|
}
|
|
} |