refactor: move business logic to service layer for architecture compliance
- images.py: delegate file validation (size, type, extension) to image_service - platform_health.py: extract all database queries to platform_health_service - Fixes 13 architecture validation errors (API-002, API-003) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,21 +12,26 @@ Provides:
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from app.exceptions import ValidationException
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Maximum upload size (10MB)
|
||||
MAX_UPLOAD_SIZE = 10 * 1024 * 1024
|
||||
|
||||
|
||||
class ImageService:
|
||||
"""Service for image upload and management."""
|
||||
|
||||
# Supported image formats
|
||||
ALLOWED_EXTENSIONS = {"jpg", "jpeg", "png", "gif", "webp"}
|
||||
ALLOWED_CONTENT_TYPES = {"image/jpeg", "image/png", "image/gif", "image/webp"}
|
||||
|
||||
# Size variants to generate
|
||||
SIZES = {
|
||||
@@ -57,6 +62,7 @@ class ImageService:
|
||||
filename: str,
|
||||
vendor_id: int,
|
||||
product_id: int | None = None,
|
||||
content_type: str | None = None,
|
||||
) -> dict:
|
||||
"""Upload and process a product image.
|
||||
|
||||
@@ -65,14 +71,30 @@ class ImageService:
|
||||
filename: Original filename
|
||||
vendor_id: Vendor ID for path generation
|
||||
product_id: Optional product ID
|
||||
content_type: MIME type of the uploaded file
|
||||
|
||||
Returns:
|
||||
Dict with image info and URLs
|
||||
|
||||
Raises:
|
||||
ValidationException: If file is too large or invalid type
|
||||
"""
|
||||
# Validate file size
|
||||
if len(file_content) > MAX_UPLOAD_SIZE:
|
||||
raise ValidationException(
|
||||
f"File too large. Maximum size: {MAX_UPLOAD_SIZE // (1024*1024)}MB"
|
||||
)
|
||||
|
||||
# Validate content type
|
||||
if not content_type or not content_type.startswith("image/"):
|
||||
raise ValidationException("Invalid file type. Only images are allowed.")
|
||||
|
||||
# Validate file extension
|
||||
ext = self._get_extension(filename)
|
||||
if ext not in self.ALLOWED_EXTENSIONS:
|
||||
raise ValueError(f"Invalid file type: {ext}. Allowed: {self.ALLOWED_EXTENSIONS}")
|
||||
raise ValidationException(
|
||||
f"Invalid file type: {ext}. Allowed: {', '.join(self.ALLOWED_EXTENSIONS)}"
|
||||
)
|
||||
|
||||
# Generate unique hash for this image
|
||||
image_hash = self._generate_hash(vendor_id, product_id, filename)
|
||||
|
||||
Reference in New Issue
Block a user