refactor:영업파트너 역할 2개로 단순화 (recruiter 제거)

- 역할: sales(영업파트너), manager(상담매니저) 2개만 유지
- recruiter(유치담당) 역할 완전 제거
- 역할 레이블 변경: 영업→영업파트너, 매니저→상담매니저
- 통계, 필터, 역할관리 UI 모두 업데이트

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
김보곤
2026-02-02 16:43:02 +09:00
parent 32c00d8522
commit ced9110f3b
8 changed files with 35 additions and 64 deletions

View File

@@ -82,7 +82,7 @@ private function getIndexData(Request $request): array
// 영업 역할을 가진 사용자 목록 (영업파트너)
$salesPartners = User::whereHas('userRoles', function ($q) {
$q->whereHas('role', function ($rq) {
$rq->whereIn('name', ['sales', 'manager', 'recruiter']);
$rq->whereIn('name', ['sales', 'manager']);
});
})->orderBy('name')->get();

View File

@@ -261,7 +261,7 @@ public function delegateRole(Request $request, int $id)
{
$validated = $request->validate([
'to_user_id' => 'required|exists:users,id',
'role_name' => 'required|string|in:manager,recruiter',
'role_name' => 'required|string|in:manager',
]);
$fromUser = User::findOrFail($id);
@@ -270,7 +270,7 @@ public function delegateRole(Request $request, int $id)
try {
$this->service->delegateRole($fromUser, $toUser, $validated['role_name']);
$roleLabel = $validated['role_name'] === 'manager' ? '매니저' : '유치담당';
$roleLabel = '상담매니저';
return redirect()->back()
->with('success', "{$roleLabel} 역할이 {$toUser->name}님에게 위임되었습니다.");
} catch (\InvalidArgumentException $e) {
@@ -285,13 +285,13 @@ public function delegateRole(Request $request, int $id)
public function assignRole(Request $request, int $id)
{
$validated = $request->validate([
'role_name' => 'required|string|in:sales,manager,recruiter',
'role_name' => 'required|string|in:sales,manager',
]);
$partner = User::findOrFail($id);
$this->service->assignRole($partner, $validated['role_name']);
$roleLabels = ['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'];
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
return redirect()->back()
->with('success', "{$roleLabels[$validated['role_name']]} 역할이 부여되었습니다.");
}
@@ -302,13 +302,13 @@ public function assignRole(Request $request, int $id)
public function removeRole(Request $request, int $id)
{
$validated = $request->validate([
'role_name' => 'required|string|in:sales,manager,recruiter',
'role_name' => 'required|string|in:sales,manager',
]);
$partner = User::findOrFail($id);
$this->service->removeRole($partner, $validated['role_name']);
$roleLabels = ['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'];
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
return redirect()->back()
->with('success', "{$roleLabels[$validated['role_name']]} 역할이 제거되었습니다.");
}

View File

@@ -19,7 +19,7 @@ class SalesManagerService
/**
* 영업파트너 역할 이름 목록
*/
public const SALES_ROLES = ['sales', 'manager', 'recruiter'];
public const SALES_ROLES = ['sales', 'manager'];
/**
* 영업파트너 생성
@@ -510,9 +510,6 @@ public function getStats(?int $parentId = null): array
'manager' => (clone $baseQuery)
->whereHas('userRoles.role', fn($q) => $q->where('name', 'manager'))
->count(),
'recruiter' => (clone $baseQuery)
->whereHas('userRoles.role', fn($q) => $q->where('name', 'recruiter'))
->count(),
];
}

View File

@@ -20,15 +20,11 @@ public function run(): void
$roles = [
[
'name' => 'sales',
'description' => '영업 - 가망고객 발굴, 상담, 계약 체결',
'description' => '영업파트너 - 고객 발굴, 계약 체결',
],
[
'name' => 'manager',
'description' => '매니저 - 하위 파트너 관리, 실적 취합, 승인 처리',
],
[
'name' => 'recruiter',
'description' => '유치담당 - 새로운 영업파트너 유치 활동',
'description' => '상담매니저 - 고객 상담, 인터뷰 정리',
],
];
@@ -45,6 +41,6 @@ public function run(): void
);
}
$this->command->info('영업파트너 역할이 생성되었습니다: sales, manager, recruiter');
$this->command->info('영업파트너 역할이 생성되었습니다: sales, manager');
}
}

View File

@@ -80,13 +80,11 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
$roleColor = match($userRole->role->name ?? '') {
'sales' => 'bg-blue-100 text-blue-800',
'manager' => 'bg-purple-100 text-purple-800',
'recruiter' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
$roleLabel = match($userRole->role->name ?? '') {
'sales' => '영업',
'manager' => '매니저',
'recruiter' => '유치담당',
'sales' => '영업파트너',
'manager' => '상담매니저',
default => $userRole->role->name ?? '-',
};
@endphp
@@ -177,13 +175,11 @@ class="px-2 py-1 bg-gray-400 hover:bg-gray-500 text-white text-xs font-medium ro
$roleColor = match($userRole->role->name ?? '') {
'sales' => 'bg-blue-100 text-blue-800',
'manager' => 'bg-purple-100 text-purple-800',
'recruiter' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
$roleLabel = match($userRole->role->name ?? '') {
'sales' => '영업',
'manager' => '매니저',
'recruiter' => '유치담당',
'sales' => '영업파트너',
'manager' => '상담매니저',
default => $userRole->role->name ?? '-',
};
@endphp

View File

@@ -20,7 +20,7 @@ class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition
</div>
<!-- 통계 카드 -->
<div class="grid grid-cols-2 md:grid-cols-6 gap-4 mb-4 flex-shrink-0">
<div class="grid grid-cols-2 md:grid-cols-5 gap-4 mb-4 flex-shrink-0">
<div class="bg-white rounded-lg shadow-sm p-4">
<div class="text-sm text-gray-500">전체</div>
<div class="text-2xl font-bold text-gray-800">{{ number_format($stats['total']) }}</div>
@@ -34,17 +34,13 @@ class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition
<div class="text-2xl font-bold text-emerald-800">{{ number_format($stats['approved']) }}</div>
</div>
<div class="bg-blue-50 rounded-lg shadow-sm p-4">
<div class="text-sm text-blue-600">영업</div>
<div class="text-sm text-blue-600">영업파트너</div>
<div class="text-2xl font-bold text-blue-800">{{ number_format($stats['sales']) }}</div>
</div>
<div class="bg-purple-50 rounded-lg shadow-sm p-4">
<div class="text-sm text-purple-600">매니저</div>
<div class="text-sm text-purple-600">상담매니저</div>
<div class="text-2xl font-bold text-purple-800">{{ number_format($stats['manager']) }}</div>
</div>
<div class="bg-green-50 rounded-lg shadow-sm p-4">
<div class="text-sm text-green-600">유치담당</div>
<div class="text-2xl font-bold text-green-800">{{ number_format($stats['recruiter']) }}</div>
</div>
</div>
<!-- 필터 영역 ( ) -->
@@ -87,9 +83,8 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none foc
<div class="w-32 flex-shrink-0">
<select name="role" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm">
<option value="">전체 역할</option>
<option value="sales" {{ request('role') === 'sales' ? 'selected' : '' }}>영업</option>
<option value="manager" {{ request('role') === 'manager' ? 'selected' : '' }}>매니저</option>
<option value="recruiter" {{ request('role') === 'recruiter' ? 'selected' : '' }}>유치담당</option>
<option value="sales" {{ request('role') === 'sales' ? 'selected' : '' }}>영업파트너</option>
<option value="manager" {{ request('role') === 'manager' ? 'selected' : '' }}>상담매니저</option>
</select>
</div>
@@ -135,13 +130,11 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none foc
$roleColor = match($userRole->role->name ?? '') {
'sales' => 'bg-blue-100 text-blue-800',
'manager' => 'bg-purple-100 text-purple-800',
'recruiter' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
$roleLabel = match($userRole->role->name ?? '') {
'sales' => '영업',
'manager' => '매니저',
'recruiter' => '유치담당',
'sales' => '영업파트너',
'manager' => '상담매니저',
default => $userRole->role->name ?? '-',
};
@endphp

View File

@@ -151,11 +151,10 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-
<h3 class="text-sm font-semibold text-gray-800 mb-3">역할 관리</h3>
@php
$currentRoles = $partner->userRoles->pluck('role.name')->toArray();
$roleLabels = ['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'];
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
$roleColors = [
'sales' => 'bg-blue-100 text-blue-800 border-blue-200',
'manager' => 'bg-purple-100 text-purple-800 border-purple-200',
'recruiter' => 'bg-green-100 text-green-800 border-green-200',
];
@endphp
<div class="flex flex-wrap gap-2 mb-3">
@@ -180,7 +179,7 @@ class="ml-1 text-gray-400 hover:text-red-500">
@endforelse
</div>
<div class="flex flex-wrap gap-2">
@foreach(['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'] as $roleName => $label)
@foreach(['sales' => '영업파트너', 'manager' => '상담매니저'] as $roleName => $label)
@if(!in_array($roleName, $currentRoles))
<form action="{{ route('sales.managers.assign-role', $partner->id) }}" method="POST" class="inline">
@csrf
@@ -229,13 +228,11 @@ class="text-xs text-blue-600 hover:underline">다운로드</a>
$roleColor = match($userRole->role->name ?? '') {
'sales' => 'bg-blue-100 text-blue-800',
'manager' => 'bg-purple-100 text-purple-800',
'recruiter' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
$roleLabel = match($userRole->role->name ?? '') {
'sales' => '영업',
'manager' => '매니저',
'recruiter' => '유치담당',
'sales' => '영업파트너',
'manager' => '상담매니저',
default => $userRole->role->name ?? '-',
};
@endphp

View File

@@ -21,13 +21,11 @@
$roleColor = match($userRole->role->name ?? '') {
'sales' => 'bg-blue-100 text-blue-800',
'manager' => 'bg-purple-100 text-purple-800',
'recruiter' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
$roleLabel = match($userRole->role->name ?? '') {
'sales' => '영업',
'manager' => '매니저',
'recruiter' => '유치담당',
'sales' => '영업파트너',
'manager' => '상담매니저',
default => $userRole->role->name ?? '-',
};
@endphp
@@ -169,11 +167,10 @@ class="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition te
<div class="flex flex-wrap gap-2">
@php
$currentRoles = $partner->userRoles->pluck('role.name')->toArray();
$roleLabels = ['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'];
$roleLabels = ['sales' => '영업파트너', 'manager' => '상담매니저'];
$roleColors = [
'sales' => 'bg-blue-100 text-blue-800 border-blue-200',
'manager' => 'bg-purple-100 text-purple-800 border-purple-200',
'recruiter' => 'bg-green-100 text-green-800 border-green-200',
];
@endphp
@forelse($currentRoles as $roleName)
@@ -202,7 +199,7 @@ class="ml-1 text-gray-400 hover:text-red-500">
<div class="mb-6">
<h3 class="text-sm font-medium text-gray-700 mb-2">역할 부여</h3>
<div class="flex flex-wrap gap-2">
@foreach(['sales' => '영업', 'manager' => '매니저', 'recruiter' => '유치담당'] as $roleName => $label)
@foreach(['sales' => '영업파트너', 'manager' => '상담매니저'] as $roleName => $label)
@if(!in_array($roleName, $currentRoles))
<form action="{{ route('sales.managers.assign-role', $partner->id) }}" method="POST" class="inline">
@csrf
@@ -217,8 +214,8 @@ class="px-3 py-1 text-sm border border-gray-300 rounded-full hover:bg-gray-50 tr
</div>
</div>
<!-- 역할 위임 (manager 또는 recruiter 역할이 있고 위임 가능한 하위 파트너가 있을 ) -->
@if((in_array('manager', $currentRoles) || in_array('recruiter', $currentRoles)) && $delegationCandidates->isNotEmpty())
<!-- 역할 위임 (manager 역할이 있고 위임 가능한 하위 파트너가 있을 ) -->
@if(in_array('manager', $currentRoles) && $delegationCandidates->isNotEmpty())
<div class="border-t border-gray-200 pt-6">
<h3 class="text-sm font-medium text-gray-700 mb-3">역할 위임</h3>
<p class="text-xs text-gray-500 mb-3">보유 중인 역할을 하위 파트너에게 위임할 있습니다. 위임하면 해당 역할이 제거됩니다.</p>
@@ -230,10 +227,7 @@ class="px-3 py-1 text-sm border border-gray-300 rounded-full hover:bg-gray-50 tr
<label class="block text-sm text-gray-600 mb-1">위임할 역할</label>
<select name="role_name" required class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm">
@if(in_array('manager', $currentRoles))
<option value="manager">매니저</option>
@endif
@if(in_array('recruiter', $currentRoles))
<option value="recruiter">유치담당</option>
<option value="manager">상담매니저</option>
@endif
</select>
</div>
@@ -322,13 +316,11 @@ class="text-sm text-blue-600 hover:underline">다운로드</a>
$roleColor = match($userRole->role->name ?? '') {
'sales' => 'bg-blue-100 text-blue-800',
'manager' => 'bg-purple-100 text-purple-800',
'recruiter' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
$roleLabel = match($userRole->role->name ?? '') {
'sales' => '영업',
'manager' => '매니저',
'recruiter' => '유치담당',
'sales' => '영업파트너',
'manager' => '상담매니저',
default => $userRole->role->name ?? '-',
};
@endphp