diff --git a/app/Enums/EmployeeStatus.php b/app/Enums/EmployeeStatus.php deleted file mode 100644 index a9b7025..0000000 --- a/app/Enums/EmployeeStatus.php +++ /dev/null @@ -1,23 +0,0 @@ - 'Aktif', - self::INACTIVE => 'Tidak Aktif', - self::RESIGNED => 'Resign', - }; - } -} diff --git a/app/Http/Controllers/Admin/Hr/EmployeeController.php b/app/Http/Controllers/Admin/Hr/EmployeeController.php index bc8d4b0..c7c8784 100644 --- a/app/Http/Controllers/Admin/Hr/EmployeeController.php +++ b/app/Http/Controllers/Admin/Hr/EmployeeController.php @@ -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 + */ + 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 */ @@ -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, diff --git a/app/Http/Requests/Admin/Hr/EmployeeRequest.php b/app/Http/Requests/Admin/Hr/EmployeeRequest.php index 383092e..c271b1f 100644 --- a/app/Http/Requests/Admin/Hr/EmployeeRequest.php +++ b/app/Http/Requests/Admin/Hr/EmployeeRequest.php @@ -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 */ diff --git a/app/Models/Employee.php b/app/Models/Employee.php index e885d30..2d4f0f3 100644 --- a/app/Models/Employee.php +++ b/app/Models/Employee.php @@ -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, ',', '.'), ); } diff --git a/app/Models/User.php b/app/Models/User.php index 66ec32e..c93b8dc 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -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); diff --git a/app/Observers/EmployeeObserver.php b/app/Observers/EmployeeObserver.php deleted file mode 100644 index 5e029e6..0000000 --- a/app/Observers/EmployeeObserver.php +++ /dev/null @@ -1,35 +0,0 @@ -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); - }); - } -} diff --git a/database/migrations/2026_06_09_112737_create_employees_table.php b/database/migrations/2026_06_09_112737_create_employees_table.php index 00d6537..eb91d06 100644 --- a/database/migrations/2026_06_09_112737_create_employees_table.php +++ b/database/migrations/2026_06_09_112737_create_employees_table.php @@ -1,6 +1,5 @@ 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(); diff --git a/resources/js/components/hr/employees/columns.ts b/resources/js/components/hr/employees/columns.ts index 291d710..38f82c1 100644 --- a/resources/js/components/hr/employees/columns.ts +++ b/resources/js/components/hr/employees/columns.ts @@ -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[] = [ - { - 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[] = [ 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', diff --git a/resources/js/components/hr/employees/employee-status-toggle.vue b/resources/js/components/hr/employees/employee-status-toggle.vue index cc24b9c..1c54505 100644 --- a/resources/js/components/hr/employees/employee-status-toggle.vue +++ b/resources/js/components/hr/employees/employee-status-toggle.vue @@ -42,11 +42,7 @@ function toggleStatus(checked: boolean) {