# app/modules/catalog/routes/api/admin.py """ Admin vendor product catalog endpoints. Provides management of vendor-specific product catalogs: - Browse products in vendor catalogs - View product details with override info - Create/update/remove products from catalog All routes require module access control for the 'catalog' module. """ import logging from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api, require_module_access from app.core.database import get_db from app.services.subscription_service import subscription_service from app.services.vendor_product_service import vendor_product_service from models.schema.auth import UserContext from app.modules.catalog.schemas import ( CatalogVendor, CatalogVendorsResponse, RemoveProductResponse, VendorProductCreate, VendorProductCreateResponse, VendorProductDetail, VendorProductListItem, VendorProductListResponse, VendorProductStats, VendorProductUpdate, ) admin_router = APIRouter( prefix="/vendor-products", dependencies=[Depends(require_module_access("catalog"))], ) logger = logging.getLogger(__name__) # ============================================================================ # Endpoints # ============================================================================ @admin_router.get("", response_model=VendorProductListResponse) def get_vendor_products( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=500), search: str | None = Query(None, description="Search by title or SKU"), vendor_id: int | None = Query(None, description="Filter by vendor"), is_active: bool | None = Query(None, description="Filter by active status"), is_featured: bool | None = Query(None, description="Filter by featured status"), language: str = Query("en", description="Language for title lookup"), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """ Get all products in vendor catalogs with filtering. This endpoint allows admins to browse products that have been copied to vendor catalogs from the marketplace repository. """ products, total = vendor_product_service.get_products( db=db, skip=skip, limit=limit, search=search, vendor_id=vendor_id, is_active=is_active, is_featured=is_featured, language=language, ) return VendorProductListResponse( products=[VendorProductListItem(**p) for p in products], total=total, skip=skip, limit=limit, ) @admin_router.get("/stats", response_model=VendorProductStats) def get_vendor_product_stats( vendor_id: int | None = Query(None, description="Filter stats by vendor ID"), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Get vendor product statistics for admin dashboard.""" stats = vendor_product_service.get_product_stats(db, vendor_id=vendor_id) return VendorProductStats(**stats) @admin_router.get("/vendors", response_model=CatalogVendorsResponse) def get_catalog_vendors( db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of vendors with products in their catalogs.""" vendors = vendor_product_service.get_catalog_vendors(db) return CatalogVendorsResponse(vendors=[CatalogVendor(**v) for v in vendors]) @admin_router.get("/{product_id}", response_model=VendorProductDetail) def get_vendor_product_detail( product_id: int, db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Get detailed vendor product information including override info.""" product = vendor_product_service.get_product_detail(db, product_id) return VendorProductDetail(**product) @admin_router.post("", response_model=VendorProductCreateResponse) def create_vendor_product( data: VendorProductCreate, db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Create a new vendor product.""" # Check product limit before creating subscription_service.check_product_limit(db, data.vendor_id) product = vendor_product_service.create_product(db, data.model_dump()) db.commit() return VendorProductCreateResponse( id=product.id, message="Product created successfully" ) @admin_router.patch("/{product_id}", response_model=VendorProductDetail) def update_vendor_product( product_id: int, data: VendorProductUpdate, db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Update a vendor product.""" # Only include fields that were explicitly set update_data = data.model_dump(exclude_unset=True) vendor_product_service.update_product(db, product_id, update_data) db.commit() # Return the updated product detail product = vendor_product_service.get_product_detail(db, product_id) return VendorProductDetail(**product) @admin_router.delete("/{product_id}", response_model=RemoveProductResponse) def remove_vendor_product( product_id: int, db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Remove a product from vendor catalog.""" result = vendor_product_service.remove_product(db, product_id) db.commit() return RemoveProductResponse(**result)