header('HX-Request') && !$request->header('HX-Boosted')) { return response('', 200)->header('HX-Redirect', route('finance.settlement')); } $initialTab = $request->input('tab', 'commission'); // 수당 정산 탭 데이터 (기본 탭이므로 즉시 로드) $year = $request->input('year', now()->year); $month = $request->input('month', now()->month); $filters = [ 'scheduled_year' => $year, 'scheduled_month' => $month, 'status' => $request->input('status'), 'payment_type' => $request->input('payment_type'), 'partner_id' => $request->input('partner_id'), 'commission_type' => $request->input('commission_type'), 'search' => $request->input('search'), ]; $commissions = $this->service->getCommissions($filters); $stats = $this->service->getSettlementStats($year, $month); $partners = SalesPartner::with('user') ->active() ->orderBy('partner_code') ->get(); $pendingTenants = $this->service->getPendingPaymentTenants(); // 통합 통계 (페이지 상단) $summaryStats = $this->getSummaryStats(); return view('finance.settlement.index', compact( 'initialTab', 'commissions', 'stats', 'partners', 'pendingTenants', 'year', 'month', 'filters', 'summaryStats' )); } /** * 수당 통계카드 HTMX 갱신 */ public function commissionStats(Request $request): View { $year = $request->input('year', now()->year); $month = $request->input('month', now()->month); $stats = $this->service->getSettlementStats($year, $month); return view('finance.settlement.partials.commission.stats-cards', compact('stats', 'year', 'month')); } /** * 수당 테이블 HTMX 갱신 */ public function commissionTable(Request $request): View { $year = $request->input('year', now()->year); $month = $request->input('month', now()->month); $filters = [ 'scheduled_year' => $year, 'scheduled_month' => $month, 'status' => $request->input('status'), 'payment_type' => $request->input('payment_type'), 'partner_id' => $request->input('partner_id'), 'commission_type' => $request->input('commission_type'), 'search' => $request->input('search'), ]; $commissions = $this->service->getCommissions($filters); return view('finance.settlement.partials.commission.table', compact('commissions')); } /** * 파트너별 현황 탭 */ public function partnerSummary(Request $request): View { $query = SalesPartner::with('user'); // 검색 if ($search = $request->input('search')) { $query->where(function ($q) use ($search) { $q->where('partner_code', 'like', "%{$search}%") ->orWhereHas('user', function ($uq) use ($search) { $uq->where('name', 'like', "%{$search}%"); }); }); } // 유형 필터 if ($type = $request->input('type')) { if ($type === 'individual') { $query->where('partner_type', '!=', 'corporate'); } elseif ($type === 'corporate') { $query->where('partner_type', 'corporate'); } } // 상태 필터 if ($request->input('status', 'active') === 'active') { $query->active(); } $partners = $query->orderBy('partner_code')->paginate(20); // 각 파트너별 수당 집계 $partnerIds = $partners->pluck('id')->toArray(); if (!empty($partnerIds)) { $commissionStats = SalesCommission::selectRaw(' partner_id, SUM(CASE WHEN status = "paid" THEN partner_commission ELSE 0 END) as paid_total, SUM(CASE WHEN status IN ("pending", "approved") THEN partner_commission ELSE 0 END) as unpaid_total, COUNT(*) as total_count, MAX(CASE WHEN status = "paid" THEN actual_payment_date ELSE NULL END) as last_paid_date ') ->whereIn('partner_id', $partnerIds) ->groupBy('partner_id') ->get() ->keyBy('partner_id'); } else { $commissionStats = collect(); } return view('finance.settlement.partials.partner-summary', compact('partners', 'commissionStats')); } /** * 컨설팅비용 탭 */ public function consultingTab(Request $request): View { return view('finance.settlement.partials.consulting-tab'); } /** * 고객사정산 탭 */ public function customerTab(Request $request): View { return view('finance.settlement.partials.customer-tab'); } /** * 구독관리 탭 */ public function subscriptionTab(Request $request): View { return view('finance.settlement.partials.subscription-tab'); } /** * 수당 지급 탭 (파트너별 그룹핑) */ public function paymentTab(Request $request): View { // approved 상태 수당을 partner_id 기준 GROUP BY $partnerPayments = SalesCommission::where('status', SalesCommission::STATUS_APPROVED) ->selectRaw(' partner_id, GROUP_CONCAT(id) as commission_ids, COUNT(*) as count, SUM(partner_commission) as partner_total, SUM(manager_commission) as manager_total, SUM(COALESCE(referrer_commission, 0)) as referrer_total ') ->groupBy('partner_id') ->get(); // 파트너 정보 eager load $partners = SalesPartner::with('user') ->whereIn('id', $partnerPayments->pluck('partner_id')) ->get() ->keyBy('id'); // 통계 카드 데이터 $now = now(); $paymentStats = [ 'waiting_count' => $partnerPayments->sum('count'), 'waiting_amount' => $partnerPayments->sum(fn ($p) => $p->partner_total + $p->manager_total + $p->referrer_total), 'this_month_paid_count' => SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $now->year) ->whereMonth('actual_payment_date', $now->month) ->count(), 'this_month_paid_amount' => SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $now->year) ->whereMonth('actual_payment_date', $now->month) ->selectRaw('SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total') ->value('total') ?? 0, 'partner_total' => $partnerPayments->sum('partner_total'), 'manager_referrer_total' => $partnerPayments->sum('manager_total') + $partnerPayments->sum('referrer_total'), ]; return view('finance.settlement.partials.payment-tab', compact('partnerPayments', 'partners', 'paymentStats')); } /** * 파트너별 수당 건 상세 (HTMX partial) */ public function paymentPartnerDetail(int $partnerId): View { $commissions = SalesCommission::where('status', SalesCommission::STATUS_APPROVED) ->where('partner_id', $partnerId) ->with(['management.tenant', 'manager']) ->orderBy('scheduled_payment_date') ->get(); return view('finance.settlement.partials.payment-partner-detail', compact('commissions', 'partnerId')); } /** * 수당지급현황통계 페이지 */ public function paymentStats(Request $request): View|Response { if ($request->header('HX-Request') && !$request->header('HX-Boosted')) { return response('', 200)->header('HX-Redirect', route('finance.settlement.payment-stats')); } $year = (int) $request->input('year', now()->year); // 통계 카드 $totalPaidAmount = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $year) ->selectRaw('SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total') ->value('total') ?? 0; $totalPaidCount = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $year) ->count(); $activePartners = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $year) ->distinct('partner_id') ->count('partner_id'); $avgCommission = $totalPaidCount > 0 ? round($totalPaidAmount / $totalPaidCount) : 0; $statsCards = [ 'total_paid_amount' => $totalPaidAmount, 'total_paid_count' => $totalPaidCount, 'active_partners' => $activePartners, 'avg_commission' => $avgCommission, ]; // 차트 1 & 4: 월별 지급 추이 (해당 연도) $monthlyTrend = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $year) ->selectRaw(" DATE_FORMAT(actual_payment_date, '%Y-%m') as month, SUM(partner_commission) as partner_total, SUM(manager_commission) as manager_total, SUM(COALESCE(referrer_commission, 0)) as referrer_total, COUNT(*) as count ") ->groupByRaw("DATE_FORMAT(actual_payment_date, '%Y-%m')") ->orderBy('month') ->get(); // 차트 2: 수당 유형별 비율 $typeRatio = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $year) ->selectRaw(" SUM(partner_commission) as partner_total, SUM(manager_commission) as manager_total, SUM(COALESCE(referrer_commission, 0)) as referrer_total ") ->first(); // 차트 3: 파트너별 수당 Top 10 $topPartners = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->whereYear('actual_payment_date', $year) ->selectRaw('partner_id, SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total') ->groupBy('partner_id') ->orderByDesc('total') ->limit(10) ->get(); $topPartnerNames = SalesPartner::with('user') ->whereIn('id', $topPartners->pluck('partner_id')) ->get() ->keyBy('id'); return view('finance.settlement.payment-stats', compact( 'year', 'statsCards', 'monthlyTrend', 'typeRatio', 'topPartners', 'topPartnerNames' )); } /** * 통합 통계 데이터 */ private function getSummaryStats(): array { $now = now(); // 미지급 수당 (pending + approved) $unpaidAmount = SalesCommission::whereIn('status', [ SalesCommission::STATUS_PENDING, SalesCommission::STATUS_APPROVED, ])->selectRaw('SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total') ->value('total') ?? 0; // 승인 대기 건수 $pendingCount = SalesCommission::where('status', SalesCommission::STATUS_PENDING)->count(); // 이번달 지급예정 $thisMonthScheduled = SalesCommission::whereIn('status', [ SalesCommission::STATUS_PENDING, SalesCommission::STATUS_APPROVED, ]) ->whereYear('scheduled_payment_date', $now->year) ->whereMonth('scheduled_payment_date', $now->month) ->selectRaw('SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total') ->value('total') ?? 0; // 누적 지급완료 $totalPaid = SalesCommission::where('status', SalesCommission::STATUS_PAID) ->selectRaw('SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total') ->value('total') ?? 0; return [ 'unpaid_amount' => $unpaidAmount, 'pending_count' => $pendingCount, 'this_month_scheduled' => $thisMonthScheduled, 'total_paid' => $totalPaid, ]; } }