header('HX-Request')) { return response('', 200)->header('HX-Redirect', route('credit.usage.index')); } $user = auth()->user(); $selectedTenantId = session('selected_tenant_id'); $isHQ = $selectedTenantId == 1; // 본사(코드브릿지엑스) // 기간 필터 (기본값: 현재 월) $year = $request->input('year', date('Y')); $month = $request->input('month', date('m')); $viewType = $request->input('view_type', 'monthly'); // monthly, yearly, custom // 기간 설정 if ($viewType === 'yearly') { $startDate = "{$year}-01-01 00:00:00"; $endDate = "{$year}-12-31 23:59:59"; } elseif ($viewType === 'custom') { $startDate = $request->input('start_date', date('Y-m-01')) . ' 00:00:00'; $endDate = $request->input('end_date', date('Y-m-t')) . ' 23:59:59'; } else { $startDate = "{$year}-{$month}-01 00:00:00"; $endDate = date('Y-m-t 23:59:59', strtotime($startDate)); } // 본사는 전체 테넌트 조회, 일반 테넌트는 자기 것만 if ($isHQ) { $usageData = $this->getAllTenantsUsage($startDate, $endDate, $viewType, $year); $tenants = Tenant::whereNull('deleted_at') ->orderBy('company_name') ->get(['id', 'company_name', 'code']); } else { $usageData = $this->getSingleTenantUsage($selectedTenantId, $startDate, $endDate, $viewType, $year); $tenants = collect(); } // 선택된 테넌트 필터 $filterTenantId = $request->input('tenant_id'); if ($isHQ && $filterTenantId) { $usageData['details'] = collect($usageData['details'])->filter(function ($item) use ($filterTenantId) { return $item['tenant_id'] == $filterTenantId; })->values()->all(); } return view('credit.usage.index', [ 'isHQ' => $isHQ, 'usageData' => $usageData, 'tenants' => $tenants, 'filters' => [ 'year' => $year, 'month' => $month, 'view_type' => $viewType, 'start_date' => substr($startDate, 0, 10), 'end_date' => substr($endDate, 0, 10), 'tenant_id' => $filterTenantId, ], 'policy' => [ 'free_quota' => self::FREE_MONTHLY_QUOTA, 'additional_fee' => self::ADDITIONAL_FEE_PER_INQUIRY, ], ]); } /** * 전체 테넌트 사용량 조회 (본사용) */ private function getAllTenantsUsage(string $startDate, string $endDate, string $viewType, string $year): array { // 테넌트별 조회 건수 $query = CreditInquiry::select( 'tenant_id', DB::raw('COUNT(*) as total_count'), DB::raw('DATE_FORMAT(inquired_at, "%Y-%m") as month') ) ->whereBetween('inquired_at', [$startDate, $endDate]) ->whereNotNull('tenant_id') ->groupBy('tenant_id', DB::raw('DATE_FORMAT(inquired_at, "%Y-%m")')); $rawData = $query->get(); // 테넌트 정보 조회 $tenantIds = $rawData->pluck('tenant_id')->unique(); $tenants = Tenant::whereIn('id', $tenantIds)->get()->keyBy('id'); // 월별로 그룹화하여 계산 $monthlyData = []; foreach ($rawData as $row) { $tenantId = $row->tenant_id; $month = $row->month; if (!isset($monthlyData[$tenantId])) { $monthlyData[$tenantId] = []; } $monthlyData[$tenantId][$month] = $row->total_count; } // 결과 데이터 생성 $details = []; $totalCount = 0; $totalFee = 0; foreach ($monthlyData as $tenantId => $months) { $tenant = $tenants->get($tenantId); $tenantTotalCount = 0; $tenantTotalFee = 0; foreach ($months as $month => $count) { $fee = $this->calculateFee($count); $tenantTotalCount += $count; $tenantTotalFee += $fee; if ($viewType === 'yearly') { // 연간 조회 시 월별 상세 표시 $details[] = [ 'tenant_id' => $tenantId, 'tenant_name' => $tenant?->company_name ?? '(삭제됨)', 'tenant_code' => $tenant?->code ?? '-', 'month' => $month, 'count' => $count, 'free_count' => min($count, self::FREE_MONTHLY_QUOTA), 'paid_count' => max(0, $count - self::FREE_MONTHLY_QUOTA), 'fee' => $fee, ]; } } if ($viewType !== 'yearly') { // 월간/기간 조회 시 테넌트별 합계만 $totalMonthCount = array_sum($months); $fee = $this->calculateFee($totalMonthCount); $details[] = [ 'tenant_id' => $tenantId, 'tenant_name' => $tenant?->company_name ?? '(삭제됨)', 'tenant_code' => $tenant?->code ?? '-', 'count' => $totalMonthCount, 'free_count' => min($totalMonthCount, self::FREE_MONTHLY_QUOTA), 'paid_count' => max(0, $totalMonthCount - self::FREE_MONTHLY_QUOTA), 'fee' => $fee, ]; } $totalCount += $tenantTotalCount; $totalFee += $tenantTotalFee; } // 정렬: 조회 건수 내림차순 usort($details, fn($a, $b) => $b['count'] - $a['count']); return [ 'total_count' => $totalCount, 'total_fee' => $totalFee, 'details' => $details, ]; } /** * 단일 테넌트 사용량 조회 */ private function getSingleTenantUsage(int $tenantId, string $startDate, string $endDate, string $viewType, string $year): array { $tenant = Tenant::find($tenantId); // 월별 조회 건수 $query = CreditInquiry::select( DB::raw('COUNT(*) as total_count'), DB::raw('DATE_FORMAT(inquired_at, "%Y-%m") as month') ) ->where('tenant_id', $tenantId) ->whereBetween('inquired_at', [$startDate, $endDate]) ->groupBy(DB::raw('DATE_FORMAT(inquired_at, "%Y-%m")')) ->orderBy('month'); $rawData = $query->get(); $details = []; $totalCount = 0; $totalFee = 0; foreach ($rawData as $row) { $count = $row->total_count; $fee = $this->calculateFee($count); $details[] = [ 'tenant_id' => $tenantId, 'tenant_name' => $tenant?->company_name ?? '(삭제됨)', 'month' => $row->month, 'count' => $count, 'free_count' => min($count, self::FREE_MONTHLY_QUOTA), 'paid_count' => max(0, $count - self::FREE_MONTHLY_QUOTA), 'fee' => $fee, ]; $totalCount += $count; $totalFee += $fee; } // 연간 조회 시 없는 월도 표시 if ($viewType === 'yearly') { $existingMonths = collect($details)->pluck('month')->toArray(); for ($m = 1; $m <= 12; $m++) { $monthKey = sprintf('%s-%02d', $year, $m); if (!in_array($monthKey, $existingMonths)) { $details[] = [ 'tenant_id' => $tenantId, 'tenant_name' => $tenant?->company_name ?? '(삭제됨)', 'month' => $monthKey, 'count' => 0, 'free_count' => 0, 'paid_count' => 0, 'fee' => 0, ]; } } // 월 순서로 정렬 usort($details, fn($a, $b) => strcmp($a['month'], $b['month'])); } return [ 'total_count' => $totalCount, 'total_fee' => $totalFee, 'details' => $details, ]; } /** * 요금 계산 */ private function calculateFee(int $count): int { $paidCount = max(0, $count - self::FREE_MONTHLY_QUOTA); return $paidCount * self::ADDITIONAL_FEE_PER_INQUIRY; } }