Files
sam-manage/app/Services/ConstructionSitePhotoService.php
김보곤 beff95b4e1 feat:공사현장 사진대지 기능 추가
모델, 서비스, 컨트롤러, React SPA 뷰, 라우트 추가
GCS 업로드/다운로드, 드래그앤드롭 사진 관리

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

136 lines
4.0 KiB
PHP

<?php
namespace App\Services;
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' => Auth::user()->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'],
]);
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;
}
}