boolean('all_tenants', false); $isHeadquarters = $tenantId == self::HEADQUARTERS_TENANT_ID; // 날짜 파라미터 (기본: 이번 달) $startDate = $request->input('start_date', now()->startOfMonth()->format('Y-m-d')); $endDate = $request->input('end_date', now()->format('Y-m-d')); // 바로빌 API 형식으로 변환 (YYYYMMDD) $apiStartDate = str_replace('-', '', $startDate); $apiEndDate = str_replace('-', '', $endDate); // 테넌트 필터링 $filterTenantId = (! $isHeadquarters && ! $allTenants && $tenantId) ? $tenantId : null; // 사용량 목록 조회 $usageList = $this->usageService->getUsageList($apiStartDate, $apiEndDate, $filterTenantId); // 통계 집계 $stats = $this->usageService->aggregateStats($usageList); // 합계 행 추가 $totalRow = [ 'member_id' => null, 'tenant_id' => null, 'tenant_name' => '합계', 'biz_no' => '', 'formatted_biz_no' => '', 'corp_name' => '', 'barobill_id' => '', 'tax_invoice_count' => $stats['total_tax_invoice'], 'bank_account_count' => $stats['total_bank_account'], 'card_count' => $stats['total_card'], 'hometax_count' => $stats['total_hometax'], 'total_amount' => $stats['total_amount'], 'is_total_row' => true, ]; // 본사이거나 전체 테넌트 모드면 테넌트 컬럼 표시 $showAllTenants = $isHeadquarters || $allTenants; // HTMX 요청 시 HTML 반환 if ($request->header('HX-Request')) { return response( view('barobill.usage.partials.table', [ 'usageList' => $usageList, 'totalRow' => $totalRow, 'allTenants' => $showAllTenants, 'startDate' => $startDate, 'endDate' => $endDate, ])->render(), 200, ['Content-Type' => 'text/html'] ); } return response()->json([ 'success' => true, 'data' => $usageList, 'total' => $totalRow, 'meta' => [ 'start_date' => $startDate, 'end_date' => $endDate, 'all_tenants' => $showAllTenants, ], ]); } /** * 통계 카드 데이터 조회 */ public function stats(Request $request): JsonResponse|Response { $tenantId = session('selected_tenant_id'); $allTenants = $request->boolean('all_tenants', false); $isHeadquarters = $tenantId == self::HEADQUARTERS_TENANT_ID; // 날짜 파라미터 $startDate = $request->input('start_date', now()->startOfMonth()->format('Y-m-d')); $endDate = $request->input('end_date', now()->format('Y-m-d')); // 바로빌 API 형식으로 변환 $apiStartDate = str_replace('-', '', $startDate); $apiEndDate = str_replace('-', '', $endDate); // 테넌트 필터링 $filterTenantId = (! $isHeadquarters && ! $allTenants && $tenantId) ? $tenantId : null; // 사용량 목록 조회 및 통계 집계 $usageList = $this->usageService->getUsageList($apiStartDate, $apiEndDate, $filterTenantId); $stats = $this->usageService->aggregateStats($usageList); // HTMX 요청 시 HTML 반환 if ($request->header('HX-Request')) { return response( view('barobill.usage.partials.stats', compact('stats'))->render(), 200, ['Content-Type' => 'text/html'] ); } return response()->json([ 'success' => true, 'data' => $stats, ]); } /** * 단일 회원사 상세 사용량 조회 */ public function show(Request $request, int $memberId): JsonResponse|Response { $member = BarobillMember::with('tenant:id,company_name')->find($memberId); if (! $member) { return response()->json([ 'success' => false, 'message' => '회원사를 찾을 수 없습니다.', ], 404); } // 날짜 파라미터 $startDate = $request->input('start_date', now()->startOfMonth()->format('Y-m-d')); $endDate = $request->input('end_date', now()->format('Y-m-d')); // 바로빌 API 형식으로 변환 $apiStartDate = str_replace('-', '', $startDate); $apiEndDate = str_replace('-', '', $endDate); // 사용량 조회 $usage = $this->usageService->getMemberUsage($member, $apiStartDate, $apiEndDate); // 서비스별 단가 정보 $priceInfo = BarobillUsageService::getPriceInfo(); // HTMX 요청 시 모달 HTML 반환 if ($request->header('HX-Request')) { return response( view('barobill.usage.partials.detail-modal', [ 'member' => $member, 'usage' => $usage, 'priceInfo' => $priceInfo, 'startDate' => $startDate, 'endDate' => $endDate, ])->render(), 200, ['Content-Type' => 'text/html'] ); } return response()->json([ 'success' => true, 'data' => [ 'member' => $member, 'usage' => $usage, 'price_info' => $priceInfo, ], ]); } /** * 엑셀 다운로드 */ public function export(Request $request) { $tenantId = session('selected_tenant_id'); $allTenants = $request->boolean('all_tenants', false); $isHeadquarters = $tenantId == self::HEADQUARTERS_TENANT_ID; // 날짜 파라미터 $startDate = $request->input('start_date', now()->startOfMonth()->format('Y-m-d')); $endDate = $request->input('end_date', now()->format('Y-m-d')); // 바로빌 API 형식으로 변환 $apiStartDate = str_replace('-', '', $startDate); $apiEndDate = str_replace('-', '', $endDate); // 테넌트 필터링 $filterTenantId = (! $isHeadquarters && ! $allTenants && $tenantId) ? $tenantId : null; // 사용량 목록 조회 $usageList = $this->usageService->getUsageList($apiStartDate, $apiEndDate, $filterTenantId); $stats = $this->usageService->aggregateStats($usageList); // CSV 생성 $filename = "barobill_usage_{$startDate}_{$endDate}.csv"; $headers = [ 'Content-Type' => 'text/csv; charset=UTF-8', 'Content-Disposition' => "attachment; filename=\"{$filename}\"", ]; $callback = function () use ($usageList, $stats, $isHeadquarters, $allTenants) { $file = fopen('php://output', 'w'); // BOM for Excel UTF-8 fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF)); // 헤더 $headerRow = ['사업자번호', '상호', '바로빌ID', '세금계산서(건)', '계좌조회(건)', '카드내역(건)', '홈텍스(건)', '과금액(원)']; if ($isHeadquarters || $allTenants) { array_unshift($headerRow, 'T-ID', '테넌트'); } fputcsv($file, $headerRow); // 데이터 foreach ($usageList as $usage) { $row = [ $usage['formatted_biz_no'], $usage['corp_name'], $usage['barobill_id'], $usage['tax_invoice_count'], $usage['bank_account_count'], $usage['card_count'], $usage['hometax_count'], $usage['total_amount'], ]; if ($isHeadquarters || $allTenants) { array_unshift($row, $usage['tenant_id'], $usage['tenant_name']); } fputcsv($file, $row); } // 합계 $totalRow = ['', '', '합계', $stats['total_tax_invoice'], $stats['total_bank_account'], $stats['total_card'], $stats['total_hometax'], $stats['total_amount']]; if ($isHeadquarters || $allTenants) { array_unshift($totalRow, '', ''); } fputcsv($file, $totalRow); fclose($file); }; return response()->stream($callback, 200, $headers); } }