264 lines
9.1 KiB
PHP
264 lines
9.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Credit;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Credit\CreditInquiry;
|
|
use App\Models\Tenants\Tenant;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\View\View;
|
|
|
|
/**
|
|
* 신용평가 조회회수 집계 컨트롤러
|
|
*/
|
|
class CreditUsageController extends Controller
|
|
{
|
|
// 과금 정책: 월 기본 무료 제공 건수
|
|
const FREE_MONTHLY_QUOTA = 5;
|
|
|
|
// 과금 정책: 추가 건당 요금 (원)
|
|
const ADDITIONAL_FEE_PER_INQUIRY = 2000;
|
|
|
|
/**
|
|
* 조회회수 집계 페이지
|
|
*/
|
|
public function index(Request $request): View|Response
|
|
{
|
|
if ($request->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;
|
|
}
|
|
}
|