diff --git a/app/api/v1/admin/vendor_domains.py b/app/api/v1/admin/vendor_domains.py index c3c00755..733cee87 100644 --- a/app/api/v1/admin/vendor_domains.py +++ b/app/api/v1/admin/vendor_domains.py @@ -5,7 +5,7 @@ Admin endpoints for managing vendor custom domains. Follows the architecture pattern: - Endpoints only handle HTTP layer - Business logic in service layer -- Proper exception handling +- Domain exceptions bubble up to global handler - Pydantic schemas for validation """ @@ -16,10 +16,9 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db -from app.exceptions import VendorNotFoundException from app.services.vendor_domain_service import vendor_domain_service +from app.services.vendor_service import vendor_service from models.database.user import User -from models.database.vendor import Vendor from models.schema.vendor_domain import ( DomainDeletionResponse, DomainVerificationInstructions, @@ -34,26 +33,6 @@ router = APIRouter(prefix="/vendors") logger = logging.getLogger(__name__) -def _get_vendor_by_id(db: Session, vendor_id: int) -> Vendor: - """ - Helper to get vendor by ID. - - Args: - db: Database session - vendor_id: Vendor ID - - Returns: - Vendor object - - Raises: - VendorNotFoundException: If vendor not found - """ - vendor = db.query(Vendor).filter(Vendor.id == vendor_id).first() - if not vendor: - raise VendorNotFoundException(str(vendor_id), identifier_type="id") - return vendor - - @router.post("/{vendor_id}/domains", response_model=VendorDomainResponse) def add_vendor_domain( vendor_id: int = Path(..., description="Vendor ID", gt=0), @@ -122,8 +101,8 @@ def list_vendor_domains( **Raises:** - 404: Vendor not found """ - # Verify vendor exists - _get_vendor_by_id(db, vendor_id) + # Verify vendor exists (raises VendorNotFoundException if not found) + vendor_service.get_vendor_by_id(db, vendor_id) domains = vendor_domain_service.get_vendor_domains(db, vendor_id) diff --git a/app/api/v1/admin/vendor_themes.py b/app/api/v1/admin/vendor_themes.py index 6c45c590..677bff90 100644 --- a/app/api/v1/admin/vendor_themes.py +++ b/app/api/v1/admin/vendor_themes.py @@ -21,7 +21,9 @@ from app.api.deps import get_current_admin_api, get_db from app.services.vendor_theme_service import vendor_theme_service from models.database.user import User from models.schema.vendor_theme import ( + ThemeDeleteResponse, ThemePresetListResponse, + ThemePresetResponse, VendorThemeResponse, VendorThemeUpdate, ) @@ -51,7 +53,7 @@ async def get_theme_presets(current_admin: User = Depends(get_current_admin_api) logger.info("Getting theme presets") presets = vendor_theme_service.get_available_presets() - return {"presets": presets} + return ThemePresetListResponse(presets=presets) # ============================================================================ @@ -134,7 +136,7 @@ async def update_vendor_theme( # Service handles all validation and raises appropriate exceptions # Global exception handler converts them to proper HTTP responses theme = vendor_theme_service.update_theme(db, vendor_code, theme_data) - return theme.to_dict() + return VendorThemeResponse(**theme.to_dict()) # ============================================================================ @@ -142,7 +144,7 @@ async def update_vendor_theme( # ============================================================================ -@router.post("/{vendor_code}/preset/{preset_name}") +@router.post("/{vendor_code}/preset/{preset_name}", response_model=ThemePresetResponse) async def apply_theme_preset( vendor_code: str = Path(..., description="Vendor code"), preset_name: str = Path(..., description="Preset name"), @@ -184,10 +186,10 @@ async def apply_theme_preset( # Global exception handler converts to HTTP 404 theme = vendor_theme_service.apply_theme_preset(db, vendor_code, preset_name) - return { - "message": f"Applied {preset_name} preset successfully", - "theme": theme.to_dict(), - } + return ThemePresetResponse( + message=f"Applied {preset_name} preset successfully", + theme=VendorThemeResponse(**theme.to_dict()), + ) # ============================================================================ @@ -195,7 +197,7 @@ async def apply_theme_preset( # ============================================================================ -@router.delete("/{vendor_code}") +@router.delete("/{vendor_code}", response_model=ThemeDeleteResponse) async def delete_vendor_theme( vendor_code: str = Path(..., description="Vendor code"), db: Session = Depends(get_db), @@ -224,4 +226,4 @@ async def delete_vendor_theme( # Service handles deletion and raises exceptions if needed # Global exception handler converts them to proper HTTP responses result = vendor_theme_service.delete_theme(db, vendor_code) - return result + return ThemeDeleteResponse(message=result.get("message", "Theme deleted successfully")) diff --git a/models/schema/vendor_theme.py b/models/schema/vendor_theme.py index 76d823d1..42f8cae9 100644 --- a/models/schema/vendor_theme.py +++ b/models/schema/vendor_theme.py @@ -100,3 +100,9 @@ class ThemePresetListResponse(BaseModel): """List of available theme presets.""" presets: list[ThemePresetPreview] = Field(..., description="Available presets") + + +class ThemeDeleteResponse(BaseModel): + """Response after deleting a theme.""" + + message: str = Field(..., description="Success message")