diff --git a/app/Http/Controllers/Sales/SalesDashboardController.php b/app/Http/Controllers/Sales/SalesDashboardController.php index 0db5e311..36432edf 100644 --- a/app/Http/Controllers/Sales/SalesDashboardController.php +++ b/app/Http/Controllers/Sales/SalesDashboardController.php @@ -311,6 +311,149 @@ public function getManagers(Request $request): JsonResponse ]); } + /** + * 유치 파트너 활동 현황 (HTMX 탭 로드) + */ + public function partnerActivity(Request $request): View + { + $data = $this->getPartnerActivityData(); + + return view('sales.dashboard.partials.partner-activity', $data); + } + + /** + * 유치 파트너 활동 데이터 조회 + */ + private function getPartnerActivityData(): array + { + $currentUser = auth()->user(); + $currentUserId = $currentUser->id; + + // 직접 유치한 하위 파트너 목록 (parent_id가 현재 사용자인 사용자들) + $recruitedPartners = User::where('parent_id', $currentUserId) + ->where('is_active', true) + ->with(['userRoles.role']) + ->get(); + + $partnerIds = $recruitedPartners->pluck('id')->toArray(); + + // 요약 통계 계산 + $summaryStats = $this->calculatePartnerSummaryStats($partnerIds, $currentUserId); + + // 파트너별 상세 활동 데이터 + $partnerActivities = $this->getPartnerActivitiesDetail($recruitedPartners, $currentUserId); + + return [ + 'summaryStats' => $summaryStats, + 'partnerActivities' => $partnerActivities, + 'recruitedPartners' => $recruitedPartners, + ]; + } + + /** + * 유치 파트너 요약 통계 계산 + */ + private function calculatePartnerSummaryStats(array $partnerIds, int $currentUserId): array + { + // 유치 파트너 수 + $partnerCount = count($partnerIds); + + // 하위 파트너들이 등록한 총 영업권(명함) 수 + $totalProspects = TenantProspect::whereIn('registered_by', $partnerIds)->count(); + + // 하위 파트너들의 계약 성사 건수 + $totalConversions = TenantProspect::whereIn('registered_by', $partnerIds) + ->where('status', TenantProspect::STATUS_CONVERTED) + ->count(); + + // 매니저로서 받을 수당 (내가 매니저로 지정된 수당 중 하위 파트너 관련) + $expectedCommission = SalesCommission::where('manager_user_id', $currentUserId) + ->whereHas('partner', function ($query) use ($partnerIds) { + $query->whereIn('user_id', $partnerIds); + }) + ->sum('manager_commission'); + + return [ + 'partner_count' => $partnerCount, + 'total_prospects' => $totalProspects, + 'total_conversions' => $totalConversions, + 'expected_commission' => $expectedCommission, + ]; + } + + /** + * 파트너별 상세 활동 데이터 + */ + private function getPartnerActivitiesDetail($recruitedPartners, int $currentUserId): array + { + $activities = []; + + foreach ($recruitedPartners as $partner) { + // 파트너의 영업파트너 정보 + $salesPartner = SalesPartner::where('user_id', $partner->id)->first(); + + // 파트너가 등록한 영업권 수 + $prospectCount = TenantProspect::where('registered_by', $partner->id)->count(); + + // 진행 중인 영업권 (active 상태) + $activeProspects = TenantProspect::where('registered_by', $partner->id) + ->where('status', TenantProspect::STATUS_ACTIVE) + ->count(); + + // 계약 성사 건수 + $conversions = TenantProspect::where('registered_by', $partner->id) + ->where('status', TenantProspect::STATUS_CONVERTED) + ->count(); + + // 이 파트너로 인한 나의 매니저 수당 + $managerCommission = 0; + if ($salesPartner) { + $managerCommission = SalesCommission::where('manager_user_id', $currentUserId) + ->where('partner_id', $salesPartner->id) + ->sum('manager_commission'); + } + + // 최근 활동 내역 (최근 전환된 테넌트 5개) + $recentTenants = TenantProspect::where('registered_by', $partner->id) + ->where('status', TenantProspect::STATUS_CONVERTED) + ->with(['tenant']) + ->orderBy('converted_at', 'desc') + ->limit(5) + ->get(); + + // 활동 상태 판단 + $lastActivity = TenantProspect::where('registered_by', $partner->id) + ->orderBy('updated_at', 'desc') + ->first(); + $status = 'inactive'; + if ($lastActivity) { + $daysSinceActivity = now()->diffInDays($lastActivity->updated_at); + if ($daysSinceActivity <= 7) { + $status = 'active'; + } elseif ($daysSinceActivity <= 30) { + $status = 'moderate'; + } + } + + // 역할 정보 + $roles = $partner->userRoles->pluck('role.name')->filter()->toArray(); + $roleLabel = !empty($roles) ? implode(', ', $roles) : '영업'; + + $activities[] = [ + 'partner' => $partner, + 'role_label' => $roleLabel, + 'prospect_count' => $prospectCount, + 'active_prospects' => $activeProspects, + 'conversions' => $conversions, + 'manager_commission' => $managerCommission, + 'status' => $status, + 'recent_tenants' => $recentTenants, + ]; + } + + return $activities; + } + /** * 영업파트너 수당 정보 조회 */ diff --git a/resources/views/sales/dashboard/index.blade.php b/resources/views/sales/dashboard/index.blade.php index 266f22d1..bc8a8792 100644 --- a/resources/views/sales/dashboard/index.blade.php +++ b/resources/views/sales/dashboard/index.blade.php @@ -17,7 +17,7 @@ @endpush @section('content') -
+

영업관리 대시보드

@@ -38,9 +38,57 @@
- -
- @include('sales.dashboard.partials.data-container') + +
+ +
+ + +
+
+ @include('sales.dashboard.partials.data-container') +
+
+ + +
+
+ +
+ + + + + 로딩 중... +
+
diff --git a/resources/views/sales/dashboard/partials/partner-activity.blade.php b/resources/views/sales/dashboard/partials/partner-activity.blade.php new file mode 100644 index 00000000..7fd83d2d --- /dev/null +++ b/resources/views/sales/dashboard/partials/partner-activity.blade.php @@ -0,0 +1,210 @@ +{{-- 유치 파트너 활동 현황 --}} +
+ {{-- 요약 카드 섹션 --}} +
+ +
+
+ 유치 파트너 +
+ + + +
+
+

{{ $summaryStats['partner_count'] }}명

+

직접 유치한 파트너

+
+ + +
+
+ 총 영업권 +
+ + + +
+
+

{{ $summaryStats['total_prospects'] }}건

+

파트너들이 등록한 명함

+
+ + +
+
+ 총 계약 +
+ + + +
+
+

{{ $summaryStats['total_conversions'] }}건

+

계약 성사 건수

+
+ + +
+
+ 예상 수당 +
+ + + +
+
+

{{ number_format($summaryStats['expected_commission']) }}원

+

매니저 수당 합계

+
+
+ + {{-- 하위 파트너 활동 테이블 --}} +
+
+
+
+ + + +
+
+

유치 파트너 활동 현황

+

직접 유치한 파트너들의 영업 활동을 확인하세요

+
+
+
+ + @if(count($partnerActivities) === 0) +
+
+ + + +
+

유치한 파트너가 없습니다

+

파트너를 유치하면 이곳에서 활동 현황을 확인할 수 있습니다

+
+ @else +
+ + + + + + + + + + + + + + @foreach($partnerActivities as $activity) + @php + $statusColors = [ + 'active' => 'bg-green-100 text-green-800', + 'moderate' => 'bg-yellow-100 text-yellow-800', + 'inactive' => 'bg-gray-100 text-gray-800', + ]; + $statusLabels = [ + 'active' => '활동중', + 'moderate' => '보통', + 'inactive' => '비활동', + ]; + @endphp + + + + + + + + + + + + + + + + @endforeach + +
파트너역할영업권진행중성공예상수당상태
+
+ +
+

{{ $activity['partner']->name }}

+

{{ $activity['partner']->email }}

+
+
+
+ + {{ $activity['role_label'] }} + + + {{ $activity['prospect_count'] }} + + {{ $activity['active_prospects'] }} + + {{ $activity['conversions'] }} + + {{ number_format($activity['manager_commission']) }}원 + + + {{ $statusLabels[$activity['status']] ?? '비활동' }} + +
+ @if($activity['recent_tenants']->isEmpty()) +
+ 아직 계약 성사 내역이 없습니다 +
+ @else +
+

최근 계약 성사 내역

+ @foreach($activity['recent_tenants'] as $prospect) +
+
+
+
+

{{ $prospect->company_name }}

+

{{ $prospect->tenant?->company_name ?? '-' }}

+
+
+
+ {{-- 진행 단계 표시 --}} +
+ + + + +
+ + {{ $prospect->converted_at?->format('Y-m-d') ?? '-' }} + + + 계약완료 + +
+
+ @endforeach +
+ @endif +
+
+ @endif +
+
diff --git a/routes/web.php b/routes/web.php index e579567d..053ac84f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -880,6 +880,7 @@ Route::get('salesmanagement/dashboard', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'index'])->name('salesmanagement.dashboard'); Route::get('salesmanagement/dashboard/refresh', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'refresh'])->name('salesmanagement.dashboard.refresh'); Route::get('salesmanagement/dashboard/tenants', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'refreshTenantList'])->name('salesmanagement.dashboard.tenants'); + Route::get('salesmanagement/dashboard/partner-activity', [\App\Http\Controllers\Sales\SalesDashboardController::class, 'partnerActivity'])->name('salesmanagement.dashboard.partner-activity'); // 영업파트너 승인 (본사 관리자 전용) - resource 전에 정의해야 함 Route::get('managers/approvals', [\App\Http\Controllers\Sales\SalesManagerController::class, 'approvals'])->name('managers.approvals');