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');
+});
+