Files
sam-manage/app/Services/ConstructionSitePhotoService.php
김보곤 95fbbd4fff feat:공사현장 사진대지 GCS 업로드 시 AI 토큰 사용량 기록
AiTokenHelper::saveGcsStorageUsage 호출 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:41:32 +09:00

139 lines
4.1 KiB
PHP

<?php
namespace App\Services;
use App\Helpers\AiTokenHelper;
use App\Models\Juil\ConstructionSitePhoto;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class ConstructionSitePhotoService
{
public function __construct(
private readonly GoogleCloudService $googleCloudService
) {}
public function getList(array $params): LengthAwarePaginator
{
$query = ConstructionSitePhoto::with('user')
->orderBy('work_date', 'desc')
->orderBy('id', 'desc');
if (!empty($params['search'])) {
$search = $params['search'];
$query->where(function ($q) use ($search) {
$q->where('site_name', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
if (!empty($params['date_from'])) {
$query->where('work_date', '>=', $params['date_from']);
}
if (!empty($params['date_to'])) {
$query->where('work_date', '<=', $params['date_to']);
}
$perPage = (int) ($params['per_page'] ?? 12);
return $query->paginate($perPage);
}
public function create(array $data): ConstructionSitePhoto
{
return ConstructionSitePhoto::create([
'tenant_id' => session('selected_tenant_id'),
'user_id' => Auth::id(),
'site_name' => $data['site_name'],
'work_date' => $data['work_date'],
'description' => $data['description'] ?? null,
]);
}
public function uploadPhoto(ConstructionSitePhoto $photo, $file, string $type): bool
{
if (!in_array($type, ['before', 'during', 'after'])) {
return false;
}
$extension = $file->getClientOriginalExtension();
$timestamp = now()->format('Ymd_His');
$objectName = "construction-site-photos/{$photo->tenant_id}/{$photo->id}/{$timestamp}_{$type}.{$extension}";
// 기존 사진이 있으면 GCS에서 삭제
$oldPath = $photo->{$type . '_photo_path'};
if ($oldPath) {
$this->googleCloudService->deleteFromStorage($oldPath);
}
// 임시 파일로 저장 후 GCS 업로드
$tempPath = $file->getRealPath();
$result = $this->googleCloudService->uploadToStorage($tempPath, $objectName);
if (!$result) {
Log::error('ConstructionSitePhoto: GCS 업로드 실패', [
'photo_id' => $photo->id,
'type' => $type,
]);
return false;
}
$photo->update([
$type . '_photo_path' => $objectName,
$type . '_photo_gcs_uri' => $result['uri'],
$type . '_photo_size' => $result['size'],
]);
AiTokenHelper::saveGcsStorageUsage('공사현장사진대지-GCS저장', $result['size']);
return true;
}
public function update(ConstructionSitePhoto $photo, array $data): ConstructionSitePhoto
{
$photo->update([
'site_name' => $data['site_name'],
'work_date' => $data['work_date'],
'description' => $data['description'] ?? null,
]);
return $photo->fresh();
}
public function delete(ConstructionSitePhoto $photo): bool
{
// GCS에서 모든 사진 삭제
foreach (['before', 'during', 'after'] as $type) {
$path = $photo->{$type . '_photo_path'};
if ($path) {
$this->googleCloudService->deleteFromStorage($path);
}
}
return $photo->delete();
}
public function deletePhotoByType(ConstructionSitePhoto $photo, string $type): bool
{
if (!in_array($type, ['before', 'during', 'after'])) {
return false;
}
$path = $photo->{$type . '_photo_path'};
if ($path) {
$this->googleCloudService->deleteFromStorage($path);
}
$photo->update([
$type . '_photo_path' => null,
$type . '_photo_gcs_uri' => null,
$type . '_photo_size' => null,
]);
return true;
}
}