File: /home/xedaptot/ai.naniguide.com/app/Services/Customer/AssetStatsService.php
<?php
namespace App\Services\Customer;
use App\Model\Asset;
use App\Model\Customer;
class AssetStatsService
{
/**
* Compute KPI stats for the customer's hero strip on /rui/assets.
*
* @return array{
* totalFiles:int, imagesCount:int, otherCount:int, publicCount:int,
* storageUsedMb:float, storageMaxMb:?int, storageUnlimited:bool, storagePct:float,
* lastUploadAsset:?Asset
* }
*/
public function forCustomer(Customer $customer): array
{
$base = Asset::query()->where('customer_id', $customer->id);
$totalFiles = (clone $base)->count();
$imagesCount = (clone $base)->where('mime_type', 'like', 'image/%')->count();
$publicCount = (clone $base)->where('visibility', Asset::VISIBILITY_PUBLIC)->count();
$lastUploadAsset = (clone $base)
->orderBy('created_at', 'desc')
->first(['id', 'uid', 'original_name', 'filename', 'created_at']);
// Read the raw union directly — Customer::maxTotalUploadSize() returns a
// pre-formatted display string. AssetStats needs int for arithmetic, so
// bypass display formatter and consume the service helper.
$rawLimit = app(\App\Services\Plans\Quotas\QuotasService::class)
->limit($customer, \App\Services\Plans\Quotas\QuotaKey::MAX_UPLOAD_SIZE_TOTAL);
$storageUsedMb = (float) $customer->totalUploadSize();
$storageUnlimited = $rawLimit === null;
$storageMaxMb = is_int($rawLimit) ? $rawLimit : null; // false / 0 / N — null when not granted, int otherwise
$storagePct = $storageUnlimited ? 0.0 : (float) $customer->totalUploadSizeUsage();
return [
'totalFiles' => $totalFiles,
'imagesCount' => $imagesCount,
'otherCount' => max(0, $totalFiles - $imagesCount),
'publicCount' => $publicCount,
'storageUsedMb' => $storageUsedMb,
'storageMaxMb' => $storageMaxMb,
'storageUnlimited' => $storageUnlimited,
'storagePct' => $storagePct,
'lastUploadAsset' => $lastUploadAsset,
];
}
}