diff --git a/app/Http/Controllers/Api/Admin/HR/EmployeeController.php b/app/Http/Controllers/Api/Admin/HR/EmployeeController.php index 85252b8f..600db986 100644 --- a/app/Http/Controllers/Api/Admin/HR/EmployeeController.php +++ b/app/Http/Controllers/Api/Admin/HR/EmployeeController.php @@ -170,4 +170,27 @@ public function destroy(Request $request, int $id): JsonResponse|Response 'message' => '퇴직 처리되었습니다.', ]); } + + /** + * 직급/직책 추가 + */ + public function storePosition(Request $request): JsonResponse + { + $validated = $request->validate([ + 'type' => 'required|string|in:rank,title', + 'name' => 'required|string|max:50', + ]); + + $position = $this->employeeService->createPosition($validated['type'], $validated['name']); + + return response()->json([ + 'success' => true, + 'message' => ($validated['type'] === 'rank' ? '직급' : '직책').'이 추가되었습니다.', + 'data' => [ + 'id' => $position->id, + 'key' => $position->key, + 'name' => $position->name, + ], + ], 201); + } } diff --git a/app/Services/HR/EmployeeService.php b/app/Services/HR/EmployeeService.php index d0afbc7a..7661b31a 100644 --- a/app/Services/HR/EmployeeService.php +++ b/app/Services/HR/EmployeeService.php @@ -235,7 +235,7 @@ public function getDepartments(): \Illuminate\Database\Eloquent\Collection } /** - * 직급 목록 (드롭다운용) + * 직급/직책 목록 (드롭다운용) */ public function getPositions(string $type = 'rank'): \Illuminate\Database\Eloquent\Collection { @@ -246,4 +246,41 @@ public function getPositions(string $type = 'rank'): \Illuminate\Database\Eloque ->ordered() ->get(['id', 'key', 'name']); } + + /** + * 직급/직책 추가 + */ + public function createPosition(string $type, string $name): Position + { + $tenantId = session('selected_tenant_id'); + + // key 생성: 이름을 소문자+언더스코어로 변환, 한글은 그대로 + $key = str_replace(' ', '_', mb_strtolower(trim($name))); + + // 중복 체크 후 존재하면 기존 반환 + $existing = Position::query() + ->forTenant() + ->where('type', $type) + ->where('key', $key) + ->first(); + + if ($existing) { + return $existing; + } + + // 다음 sort_order + $maxSort = Position::query() + ->forTenant() + ->where('type', $type) + ->max('sort_order') ?? 0; + + return Position::create([ + 'tenant_id' => $tenantId, + 'type' => $type, + 'key' => $key, + 'name' => trim($name), + 'sort_order' => $maxSort + 1, + 'is_active' => true, + ]); + } } diff --git a/resources/views/hr/employees/create.blade.php b/resources/views/hr/employees/create.blade.php index 9def6fc0..3916cc12 100644 --- a/resources/views/hr/employees/create.blade.php +++ b/resources/views/hr/employees/create.blade.php @@ -98,24 +98,42 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin {{-- 직급 / 직책 --}}
- - + +
+ + +
- - + +
+ + +
@@ -167,6 +185,8 @@ class="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition- +{{-- 직급/직책 추가 모달 --}} +@include('hr.employees.partials.position-add-modal') @endsection @push('scripts') diff --git a/resources/views/hr/employees/edit.blade.php b/resources/views/hr/employees/edit.blade.php index 9f11c2fc..0b3f4649 100644 --- a/resources/views/hr/employees/edit.blade.php +++ b/resources/views/hr/employees/edit.blade.php @@ -96,28 +96,46 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:rin {{-- 직급 / 직책 --}}
- - + +
+ + +
- - + +
+ + +
@@ -170,6 +188,9 @@ class="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition- + +{{-- 직급/직책 추가 모달 --}} +@include('hr.employees.partials.position-add-modal') @endsection @push('scripts') diff --git a/resources/views/hr/employees/partials/position-add-modal.blade.php b/resources/views/hr/employees/partials/position-add-modal.blade.php new file mode 100644 index 00000000..be2bc28f --- /dev/null +++ b/resources/views/hr/employees/partials/position-add-modal.blade.php @@ -0,0 +1,132 @@ +{{-- 직급/직책 추가 모달 --}} + + + diff --git a/routes/api.php b/routes/api.php index 51fa040a..cf5d4fb8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1049,3 +1049,8 @@ Route::delete('/{id}', [\App\Http\Controllers\Api\Admin\HR\EmployeeController::class, 'destroy'])->name('destroy'); }); +// 직급/직책 관리 API +Route::middleware(['web', 'auth', 'hq.member'])->prefix('admin/hr/positions')->name('api.admin.hr.positions.')->group(function () { + Route::post('/', [\App\Http\Controllers\Api\Admin\HR\EmployeeController::class, 'storePosition'])->name('store'); +}); +