store/app/Services/Hr/EmployeeService.php

213 lines
6.9 KiB
PHP

<?php
namespace App\Services\Hr;
use App\Models\Employee;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
class EmployeeService
{
/**
* @param array{search: string, sort: string, direction: 'asc'|'desc'} $tableQuery
*/
public function paginateForIndex(
array $tableQuery,
string $role = '',
string $gender = '',
string $employmentStatus = '',
string $isActive = '',
): LengthAwarePaginator {
$query = User::query()
->with(['profile', 'employee', 'roles'])
->when($tableQuery['search'] !== '', function ($query) use ($tableQuery): void {
$search = $tableQuery['search'];
$query->where(function ($query) use ($search): void {
$query->where('email', 'like', "%{$search}%")
->orWhere('username', 'like', "%{$search}%")
->orWhereHas('profile', function ($query) use ($search): void {
$query->where('full_name', 'like', "%{$search}%")
->orWhere('phone_number', 'like', "%{$search}%");
});
});
})
->when(
$role !== '',
fn ($query) => $query->whereHas('roles', fn ($query) => $query->where('name', $role))
)
->when(
$gender !== '',
fn ($query) => $query->whereHas('profile', fn ($query) => $query->where('gender', $gender))
)
->when(
$employmentStatus !== '',
fn ($query) => $query->whereHas('employee', fn ($query) => $query->where('employment_status', $employmentStatus))
)
->when(
$isActive !== '',
fn ($query) => $query->where('is_active', $isActive === '1')
);
$this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']);
return $query
->paginate(10)
->withQueryString();
}
/**
* @param array<string, mixed> $validated
*/
public function create(array $validated): void
{
DB::transaction(function () use ($validated): void {
$user = User::create([
'email' => $validated['email'],
'username' => $validated['username'],
'password' => Hash::make(config('auth.password_default')),
]);
UserProfile::create([
'user_id' => $user->id,
'full_name' => $validated['full_name'],
'phone_number' => $validated['phone_number'],
'gender' => $validated['gender'],
'birth_date' => $validated['birth_date'],
'address' => $validated['address'],
]);
$hasEmployee = ! empty($validated['join_date']) && ! empty($validated['employment_status']) && ! empty($validated['base_salary']);
if ($hasEmployee) {
Employee::create([
'user_id' => $user->id,
'join_date' => $validated['join_date'],
'employment_status' => $validated['employment_status'],
'base_salary' => $validated['base_salary'],
]);
}
$user->syncRoles([$validated['role']]);
});
}
/**
* @param array<string, mixed> $validated
*/
public function update(User $user, array $validated): void
{
$employee = $user->employee;
DB::transaction(function () use ($validated, $user, $employee): void {
$user->email = $validated['email'];
$user->username = $validated['username'];
$user->save();
$user->profile()->updateOrCreate(
['user_id' => $user->id],
[
'full_name' => $validated['full_name'],
'phone_number' => $validated['phone_number'],
'gender' => $validated['gender'],
'birth_date' => $validated['birth_date'],
'address' => $validated['address'],
],
);
$hasEmployee = ! empty($validated['join_date']) && ! empty($validated['employment_status']) && ! empty($validated['base_salary']);
if ($hasEmployee) {
if ($employee) {
$employee->join_date = $validated['join_date'];
$employee->employment_status = $validated['employment_status'];
$employee->base_salary = $validated['base_salary'];
$employee->save();
} else {
Employee::create([
'user_id' => $user->id,
'join_date' => $validated['join_date'],
'employment_status' => $validated['employment_status'],
'base_salary' => $validated['base_salary'],
]);
}
} else {
if ($employee) {
$employee->delete();
}
}
$user->syncRoles([$validated['role']]);
});
}
public function toggleStatus(User $user, bool $isActive): void
{
$user->is_active = $isActive;
$user->save();
if (! $isActive) {
DB::table('sessions')->where('user_id', $user->id)->delete();
}
}
public function resetPassword(User $user): void
{
$user->password = config('auth.password_default');
$user->save();
DB::table('sessions')->where('user_id', $user->id)->delete();
}
public function delete(User $user): void
{
DB::transaction(function () use ($user): void {
$user->employee?->delete();
$user->profile?->delete();
$user->delete();
});
}
private function applySorting(Builder $query, string $sort, string $direction): void
{
$employeeSorts = [
'join_date',
'base_salary',
'employment_status',
];
if (in_array($sort, $employeeSorts, true)) {
$query->orderBy(
Employee::select($sort)
->whereColumn('employees.user_id', 'users.id')
->limit(1),
$direction
);
return;
}
if ($sort === 'full_name') {
$query->orderBy(
UserProfile::select('full_name')
->whereColumn('user_profiles.user_id', 'users.id')
->limit(1),
$direction
);
return;
}
if ($sort === 'email') {
$query->orderBy('email', $direction);
return;
}
$query->latest();
}
}