Remove EmployeeStatus enum and related references from the codebase. Update Employee and User models to eliminate employee status handling. Refactor EmployeeController and related components to remove employee status filtering and display. Adjust EmployeeRequest and migration files accordingly.
This commit is contained in:
parent
926da48a8e
commit
184b012fd9
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Traits\ProvidesEnumOptions;
|
||||
|
||||
enum EmployeeStatus: string
|
||||
{
|
||||
use ProvidesEnumOptions;
|
||||
|
||||
case ACTIVE = 'active';
|
||||
case INACTIVE = 'inactive';
|
||||
case RESIGNED = 'resigned';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::ACTIVE => 'Aktif',
|
||||
self::INACTIVE => 'Tidak Aktif',
|
||||
self::RESIGNED => 'Resign',
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers\Admin\Hr;
|
||||
|
||||
use App\Enums\EmployeeStatus;
|
||||
use App\Enums\EmploymentStatus;
|
||||
use App\Enums\Gender;
|
||||
use App\Http\Controllers\Concerns\ParsesDataTableQuery;
|
||||
@ -31,7 +30,6 @@ public function index(Request $request): Response
|
||||
$direction = $tableQuery['direction'];
|
||||
|
||||
$employmentStatus = $request->string('employment_status')->toString();
|
||||
$employeeStatus = $request->string('employee_status')->toString();
|
||||
|
||||
$query = User::query()
|
||||
->with(['profile', 'employee'])
|
||||
@ -43,19 +41,12 @@ public function index(Request $request): Response
|
||||
->orWhereHas('profile', function ($query) use ($search): void {
|
||||
$query->where('full_name', 'like', "%{$search}%")
|
||||
->orWhere('phone_number', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('employee', function ($query) use ($search): void {
|
||||
$query->where('employee_code', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
})
|
||||
->when(
|
||||
$employmentStatus !== '',
|
||||
fn ($query) => $query->whereHas('employee', fn ($query) => $query->where('employment_status', $employmentStatus))
|
||||
)
|
||||
->when(
|
||||
$employeeStatus !== '',
|
||||
fn ($query) => $query->whereHas('employee', fn ($query) => $query->where('employee_status', $employeeStatus))
|
||||
);
|
||||
|
||||
$this->applySorting($query, $sort, $direction);
|
||||
@ -69,10 +60,8 @@ public function index(Request $request): Response
|
||||
'employees' => $employees,
|
||||
'filters' => $this->dataTableFilters($tableQuery, [
|
||||
'employment_status' => $employmentStatus,
|
||||
'employee_status' => $employeeStatus,
|
||||
]),
|
||||
'employmentStatuses' => EmploymentStatus::selectOptions(),
|
||||
'employeeStatuses' => EmployeeStatus::selectOptions(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -124,7 +113,7 @@ public function edit(User $user): Response
|
||||
return Inertia::render('admin/hr/employees/Edit', [
|
||||
'genders' => Gender::selectOptions(),
|
||||
'employmentStatuses' => EmploymentStatus::selectOptions(),
|
||||
'employee' => $this->transformEmployee($user),
|
||||
'employee' => $this->transformEmployeeForForm($user),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -203,11 +192,9 @@ public function destroy(User $user): RedirectResponse
|
||||
private function applySorting(Builder $query, string $sort, string $direction): void
|
||||
{
|
||||
$employeeSorts = [
|
||||
'employee_code',
|
||||
'join_date',
|
||||
'base_salary',
|
||||
'employment_status',
|
||||
'employee_status',
|
||||
];
|
||||
|
||||
if (in_array($sort, $employeeSorts, true)) {
|
||||
@ -241,6 +228,29 @@ private function applySorting(Builder $query, string $sort, string $direction):
|
||||
$query->latest();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function transformEmployeeForForm(User $user): array
|
||||
{
|
||||
$employee = $user->employee;
|
||||
$profile = $user->profile;
|
||||
|
||||
return [
|
||||
'id' => $user->id,
|
||||
'email' => $user->email,
|
||||
'username' => $user->username,
|
||||
'full_name' => $profile->full_name,
|
||||
'phone_number' => $profile->phone_number,
|
||||
'gender' => $profile->gender?->value,
|
||||
'birth_date' => $profile->birth_date?->format('Y-m-d'),
|
||||
'address' => $profile->address,
|
||||
'join_date' => $employee->join_date?->format('Y-m-d'),
|
||||
'employment_status' => $employee->employment_status?->value,
|
||||
'base_salary' => $employee->base_salary,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
@ -251,13 +261,10 @@ private function transformEmployee(User $user): array
|
||||
|
||||
return [
|
||||
'id' => $user->id,
|
||||
'employee_code' => $employee->employee_code,
|
||||
'join_date' => $employee->join_date_formatted,
|
||||
'resign_date' => $employee->resign_date_formatted,
|
||||
'employment_status' => $employee->employment_status?->value,
|
||||
'employment_status_label' => $employee->employment_status?->label(),
|
||||
'employee_status' => $employee->employee_status?->value,
|
||||
'employee_status_label' => $employee->employee_status?->label(),
|
||||
'base_salary' => $employee->base_salary,
|
||||
'base_salary_formatted' => $employee->base_salary_formatted,
|
||||
'email' => $user->email,
|
||||
|
||||
@ -14,13 +14,6 @@ public function authorize(): bool
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'base_salary' => $this->integer('base_salary'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
|
||||
@ -2,13 +2,10 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\EmployeeStatus;
|
||||
use App\Enums\EmploymentStatus;
|
||||
use App\Observers\EmployeeObserver;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Attributes\Appends;
|
||||
use Illuminate\Database\Eloquent\Attributes\Guarded;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
@ -18,7 +15,6 @@
|
||||
|
||||
#[Guarded(['id'])]
|
||||
#[Appends(['base_salary_formatted', 'join_date_formatted', 'resign_date_formatted'])]
|
||||
#[ObservedBy([EmployeeObserver::class])]
|
||||
class Employee extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
@ -29,29 +25,10 @@ protected function casts(): array
|
||||
'join_date' => 'date',
|
||||
'resign_date' => 'date',
|
||||
'employment_status' => EmploymentStatus::class,
|
||||
'employee_status' => EmployeeStatus::class,
|
||||
'base_salary' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function active(Builder $query): void
|
||||
{
|
||||
$query->where('employee_status', EmployeeStatus::ACTIVE->value);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function inactive(Builder $query): void
|
||||
{
|
||||
$query->where('employee_status', EmployeeStatus::INACTIVE->value);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function resigned(Builder $query): void
|
||||
{
|
||||
$query->where('employee_status', EmployeeStatus::RESIGNED->value);
|
||||
}
|
||||
|
||||
public function fullTime(Builder $query): void
|
||||
{
|
||||
$query->where('employment_status', EmploymentStatus::FULL_TIME->value);
|
||||
@ -60,25 +37,25 @@ public function fullTime(Builder $query): void
|
||||
#[Scope]
|
||||
public function partTime(Builder $query): void
|
||||
{
|
||||
$query->where('employee_status', EmploymentStatus::PART_TIME->value);
|
||||
$query->where('employment_status', EmploymentStatus::PART_TIME->value);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function contract(Builder $query): void
|
||||
{
|
||||
$query->where('employee_status', EmploymentStatus::CONTRACT->value);
|
||||
$query->where('employment_status', EmploymentStatus::CONTRACT->value);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function temporary(Builder $query): void
|
||||
{
|
||||
$query->where('employee_status', EmploymentStatus::TEMPORARY->value);
|
||||
$query->where('employment_status', EmploymentStatus::TEMPORARY->value);
|
||||
}
|
||||
|
||||
public function baseSalaryFormatted(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => number_format($this->base_salary, 0, ',', '.'),
|
||||
get: fn () => 'Rp '.number_format($this->base_salary, 0, ',', '.'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Guarded;
|
||||
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@ -25,6 +27,18 @@ protected function casts(): array
|
||||
];
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function active(Builder $query): void
|
||||
{
|
||||
$query->where('is_active', true);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
public function inactive(Builder $query): void
|
||||
{
|
||||
$query->where('is_active', false);
|
||||
}
|
||||
|
||||
public function profile(): HasOne
|
||||
{
|
||||
return $this->hasOne(UserProfile::class);
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Employee;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class EmployeeObserver
|
||||
{
|
||||
public function creating(Employee $employee): void
|
||||
{
|
||||
if (filled($employee->employee_code)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$year = now()->format('Y');
|
||||
$prefix = "EMP-{$year}-";
|
||||
|
||||
$employee->employee_code = DB::transaction(function () use ($prefix): string {
|
||||
$latestCode = Employee::withTrashed()
|
||||
->where('employee_code', 'like', $prefix.'%')
|
||||
->lockForUpdate()
|
||||
->orderByDesc('employee_code')
|
||||
->value('employee_code');
|
||||
|
||||
$sequence = 1;
|
||||
|
||||
if ($latestCode !== null) {
|
||||
$sequence = (int) substr($latestCode, strlen($prefix)) + 1;
|
||||
}
|
||||
|
||||
return $prefix.str_pad((string) $sequence, 4, '0', STR_PAD_LEFT);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\EmployeeStatus;
|
||||
use App\Enums\EmploymentStatus;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
@ -18,11 +17,9 @@ public function up(): void
|
||||
|
||||
$table->foreignId('user_id')->constrained()->cascadeOnDelete()->unique();
|
||||
|
||||
$table->string('employee_code', 20)->unique();
|
||||
$table->date('join_date');
|
||||
$table->date('resign_date')->nullable();
|
||||
$table->enum('employment_status', array_column(EmploymentStatus::cases(), 'value'))->default(EmploymentStatus::FULL_TIME->value);
|
||||
$table->enum('employee_status', array_column(EmployeeStatus::cases(), 'value'))->default(EmployeeStatus::ACTIVE->value);
|
||||
$table->unsignedInteger('base_salary');
|
||||
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
|
||||
@ -3,21 +3,8 @@ import { h } from 'vue';
|
||||
import { DataTableColumnHeader } from '@/components/data-table';
|
||||
import DataTableActions from '@/components/hr/employees/data-table-actions.vue';
|
||||
import EmployeeStatusToggle from '@/components/hr/employees/employee-status-toggle.vue';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import type { EmployeeListItem } from '@/types/employee';
|
||||
|
||||
function employeeStatusVariant(status: string): 'default' | 'secondary' | 'destructive' {
|
||||
if (status === 'active') {
|
||||
return 'default';
|
||||
}
|
||||
|
||||
if (status === 'resigned') {
|
||||
return 'destructive';
|
||||
}
|
||||
|
||||
return 'secondary';
|
||||
}
|
||||
|
||||
function formatDate(value: string | null): string {
|
||||
if (!value) {
|
||||
return '-';
|
||||
@ -37,12 +24,6 @@ function formatDate(value: string | null): string {
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<EmployeeListItem>[] = [
|
||||
{
|
||||
accessorKey: 'employee_code',
|
||||
enableSorting: true,
|
||||
header: () => h(DataTableColumnHeader, { title: 'Kode', column: 'employee_code' }),
|
||||
cell: ({ row }) => h('span', { class: 'font-medium' }, row.getValue('employee_code')),
|
||||
},
|
||||
{
|
||||
accessorKey: 'full_name',
|
||||
enableSorting: true,
|
||||
@ -107,29 +88,14 @@ export const columns: ColumnDef<EmployeeListItem>[] = [
|
||||
enableSorting: true,
|
||||
header: () => h(DataTableColumnHeader, { title: 'Status Kepegawaian', column: 'employment_status' }),
|
||||
},
|
||||
{
|
||||
accessorKey: 'employee_status_label',
|
||||
enableSorting: true,
|
||||
header: () => h(DataTableColumnHeader, { title: 'Status Pegawai', column: 'employee_status' }),
|
||||
cell: ({ row }) => h(
|
||||
Badge,
|
||||
{ variant: employeeStatusVariant(row.original.employee_status) },
|
||||
() => row.original.employee_status_label,
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'base_salary_formatted',
|
||||
enableSorting: true,
|
||||
header: () => h(DataTableColumnHeader, {
|
||||
title: 'Gaji Pokok',
|
||||
column: 'base_salary',
|
||||
class: 'justify-end',
|
||||
}),
|
||||
cell: ({ row }) => h(
|
||||
'div',
|
||||
{ class: 'text-right' },
|
||||
`Rp ${row.original.base_salary_formatted}`,
|
||||
),
|
||||
cell: ({ row }) => row.original.base_salary_formatted,
|
||||
},
|
||||
{
|
||||
id: 'status_toggle',
|
||||
|
||||
@ -42,11 +42,7 @@ function toggleStatus(checked: boolean) {
|
||||
|
||||
<template>
|
||||
<div class="flex items-center gap-2">
|
||||
<Switch
|
||||
:model-value="isActive"
|
||||
:disabled="processing || employee.employee_status === 'resigned'"
|
||||
@update:model-value="toggleStatus"
|
||||
/>
|
||||
<Switch :model-value="isActive" :disabled="processing" @update:model-value="toggleStatus" />
|
||||
<Badge :variant="isActive ? 'default' : 'secondary'">
|
||||
{{ isActive ? 'Aktif' : 'Nonaktif' }}
|
||||
</Badge>
|
||||
|
||||
@ -5,10 +5,10 @@ import { computed } from 'vue';
|
||||
import EmployeeForm from '@/components/hr/EmployeeForm.vue';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||
import type { EmployeeListItem, EnumOption } from '@/types/employee';
|
||||
import type { EmployeeEditItem, EnumOption } from '@/types/employee';
|
||||
|
||||
const props = defineProps<{
|
||||
employee: EmployeeListItem;
|
||||
employee: EmployeeEditItem;
|
||||
genders: EnumOption[];
|
||||
employmentStatuses: EnumOption[];
|
||||
}>();
|
||||
@ -22,8 +22,8 @@ const initialData = computed(() => ({
|
||||
birth_date: props.employee.birth_date ?? '',
|
||||
address: props.employee.address ?? '',
|
||||
join_date: props.employee.join_date ?? '',
|
||||
employment_status: props.employee.employment_status,
|
||||
base_salary: String(props.employee.base_salary),
|
||||
employment_status: props.employee.employment_status ?? 'full_time',
|
||||
base_salary: props.employee.base_salary != null ? String(props.employee.base_salary) : '',
|
||||
}));
|
||||
</script>
|
||||
|
||||
|
||||
@ -18,10 +18,8 @@ const props = defineProps<{
|
||||
sort?: string;
|
||||
direction?: 'asc' | 'desc';
|
||||
employment_status?: string;
|
||||
employee_status?: string;
|
||||
};
|
||||
employmentStatuses: EnumOption[];
|
||||
employeeStatuses: EnumOption[];
|
||||
}>();
|
||||
|
||||
const search = ref(props.filters.search ?? '');
|
||||
@ -29,7 +27,7 @@ const search = ref(props.filters.search ?? '');
|
||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } = useDataTableQuery({
|
||||
url: '/admin/hr/employees',
|
||||
initial: { ...props.filters },
|
||||
filterKeys: ['employment_status', 'employee_status'],
|
||||
filterKeys: ['employment_status'],
|
||||
});
|
||||
|
||||
useDataTableQuerySync(() => props.filters, syncFromServer);
|
||||
@ -41,17 +39,10 @@ const filterDefs = computed<DataTableFilterDef[]>(() => [
|
||||
type: 'select',
|
||||
options: props.employmentStatuses,
|
||||
},
|
||||
{
|
||||
key: 'employee_status',
|
||||
label: 'Status Pegawai',
|
||||
type: 'select',
|
||||
options: props.employeeStatuses,
|
||||
},
|
||||
]);
|
||||
|
||||
const filterValues = computed(() => ({
|
||||
employment_status: query.value.employment_status ?? '',
|
||||
employee_status: query.value.employee_status ?? '',
|
||||
}));
|
||||
|
||||
const currentSort = computed<DataTableSort | null>(() => {
|
||||
|
||||
@ -3,15 +3,26 @@ export type EnumOption = {
|
||||
label: string;
|
||||
};
|
||||
|
||||
export type EmployeeEditItem = {
|
||||
id: number;
|
||||
email: string | null;
|
||||
username: string | null;
|
||||
full_name: string | null;
|
||||
phone_number: string | null;
|
||||
gender: string | null;
|
||||
birth_date: string | null;
|
||||
address: string | null;
|
||||
join_date: string | null;
|
||||
employment_status: string | null;
|
||||
base_salary: number | null;
|
||||
};
|
||||
|
||||
export type EmployeeListItem = {
|
||||
id: number;
|
||||
employee_code: string;
|
||||
join_date: string | null;
|
||||
resign_date: string | null;
|
||||
employment_status: string;
|
||||
employment_status_label: string;
|
||||
employee_status: string;
|
||||
employee_status_label: string;
|
||||
base_salary: number;
|
||||
base_salary_formatted: string;
|
||||
email: string | null;
|
||||
@ -43,7 +54,6 @@ export type EmployeeFilters = {
|
||||
sort?: string;
|
||||
direction?: 'asc' | 'desc' | null;
|
||||
employment_status?: string;
|
||||
employee_status?: string;
|
||||
};
|
||||
|
||||
export type PaginatedEmployees = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user