getEquipment($equipmentId); return $equipment->photos->map(fn ($file) => $this->formatFileResponse($file))->values()->toArray(); } /** * @param UploadedFile[] $files */ public function store(int $equipmentId, array $files): array { $equipment = $this->getEquipment($equipmentId); $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $currentCount = File::where('document_id', $equipmentId) ->where('document_type', 'equipment') ->whereNull('deleted_at') ->count(); if ($currentCount + count($files) > self::MAX_PHOTOS) { throw new \Exception(__('error.equipment.photo_limit_exceeded')); } $uploaded = []; foreach ($files as $uploadedFile) { $extension = $uploadedFile->getClientOriginalExtension(); $storedName = bin2hex(random_bytes(8)).'.'.$extension; $displayName = $uploadedFile->getClientOriginalName(); $year = date('Y'); $month = date('m'); $directory = sprintf('%d/equipment/%s/%s', $tenantId, $year, $month); $filePath = $directory.'/'.$storedName; Storage::disk('r2')->putFileAs($directory, $uploadedFile, $storedName); $mimeType = $uploadedFile->getMimeType(); $file = File::create([ 'tenant_id' => $tenantId, 'display_name' => $displayName, 'stored_name' => $storedName, 'file_path' => $filePath, 'file_size' => $uploadedFile->getSize(), 'mime_type' => $mimeType, 'file_type' => 'image', 'document_id' => $equipmentId, 'document_type' => 'equipment', 'is_temp' => false, 'uploaded_by' => $userId, 'created_by' => $userId, ]); $uploaded[] = $this->formatFileResponse($file); } return $uploaded; } public function destroy(int $equipmentId, int $fileId): array { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $file = File::where('tenant_id', $tenantId) ->where('document_id', $equipmentId) ->where('document_type', 'equipment') ->where('id', $fileId) ->first(); if (! $file) { throw new NotFoundHttpException(__('error.file.not_found')); } $file->softDeleteFile($userId); return [ 'file_id' => $fileId, 'deleted' => true, ]; } private function getEquipment(int $equipmentId): Equipment { $equipment = Equipment::find($equipmentId); if (! $equipment) { throw new NotFoundHttpException(__('error.equipment.not_found')); } return $equipment; } private function formatFileResponse(File $file): array { return [ 'id' => $file->id, 'file_name' => $file->display_name, 'file_path' => $file->file_path, 'file_url' => url("/api/v1/files/{$file->id}/download"), 'file_size' => $file->file_size, 'mime_type' => $file->mime_type, 'created_at' => $file->created_at?->format('Y-m-d H:i:s'), ]; } }