from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, BackgroundTasks from sqlalchemy.orm import Session from app.core.database import get_db from app.api.deps import get_current_user from app.tasks.background_tasks import process_marketplace_import from middleware.decorators import rate_limit from models.api_models import MarketplaceImportJobResponse, MarketplaceImportRequest from models.database_models import User, MarketplaceImportJob, Shop from datetime import datetime import logging router = APIRouter() logger = logging.getLogger(__name__) # Shop Management Routes @router.post("/shops", response_model=ShopResponse) def create_shop( shop_data: ShopCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """Create a new shop (Protected)""" # Check if shop code already exists existing_shop = db.query(Shop).filter(Shop.shop_code == shop_data.shop_code).first() if existing_shop: raise HTTPException(status_code=400, detail="Shop code already exists") # Create shop new_shop = Shop( **shop_data.dict(), owner_id=current_user.id, is_active=True, is_verified=(current_user.role == "admin") # Auto-verify if admin creates shop ) db.add(new_shop) db.commit() db.refresh(new_shop) logger.info(f"New shop created: {new_shop.shop_code} by {current_user.username}") return new_shop @router.get("/shops", response_model=ShopListResponse) def get_shops( skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), active_only: bool = Query(True), verified_only: bool = Query(False), db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """Get shops with filtering (Protected)""" query = db.query(Shop) # Non-admin users can only see active and verified shops, plus their own if current_user.role != "admin": query = query.filter( (Shop.is_active == True) & ((Shop.is_verified == True) | (Shop.owner_id == current_user.id)) ) else: # Admin can apply filters if active_only: query = query.filter(Shop.is_active == True) if verified_only: query = query.filter(Shop.is_verified == True) total = query.count() shops = query.offset(skip).limit(limit).all() return ShopListResponse( shops=shops, total=total, skip=skip, limit=limit ) @router.get("/shops/{shop_code}", response_model=ShopResponse) def get_shop(shop_code: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): """Get shop details (Protected)""" shop = db.query(Shop).filter(Shop.shop_code == shop_code.upper()).first() if not shop: raise HTTPException(status_code=404, detail="Shop not found") # Non-admin users can only see active verified shops or their own shops if current_user.role != "admin": if not shop.is_active or (not shop.is_verified and shop.owner_id != current_user.id): raise HTTPException(status_code=404, detail="Shop not found") return shop # Shop Product Management @router.post("/shops/{shop_code}/products", response_model=ShopProductResponse) def add_product_to_shop( shop_code: str, shop_product: ShopProductCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """Add existing product to shop catalog with shop-specific settings (Protected)""" # Get and verify shop shop = get_user_shop(shop_code, current_user, db) # Check if product exists product = db.query(Product).filter(Product.product_id == shop_product.product_id).first() if not product: raise HTTPException(status_code=404, detail="Product not found in marketplace catalog") # Check if product already in shop existing_shop_product = db.query(ShopProduct).filter( ShopProduct.shop_id == shop.id, ShopProduct.product_id == product.id ).first() if existing_shop_product: raise HTTPException(status_code=400, detail="Product already in shop catalog") # Create shop-product association new_shop_product = ShopProduct( shop_id=shop.id, product_id=product.id, **shop_product.dict(exclude={'product_id'}) ) db.add(new_shop_product) db.commit() db.refresh(new_shop_product) # Return with product details response = ShopProductResponse.model_validate(new_shop_product) response.product = product return response @router.get("/shops/{shop_code}/products") def get_shop_products( shop_code: str, skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), active_only: bool = Query(True), featured_only: bool = Query(False), db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """Get products in shop catalog (Protected)""" # Get shop (public can view active/verified shops) shop = db.query(Shop).filter(Shop.shop_code == shop_code.upper()).first() if not shop: raise HTTPException(status_code=404, detail="Shop not found") # Non-owners can only see active verified shops if current_user.role != "admin" and shop.owner_id != current_user.id: if not shop.is_active or not shop.is_verified: raise HTTPException(status_code=404, detail="Shop not found") # Query shop products query = db.query(ShopProduct).filter(ShopProduct.shop_id == shop.id) if active_only: query = query.filter(ShopProduct.is_active == True) if featured_only: query = query.filter(ShopProduct.is_featured == True) total = query.count() shop_products = query.offset(skip).limit(limit).all() # Format response products = [] for sp in shop_products: product_response = ShopProductResponse.model_validate(sp) product_response.product = sp.product products.append(product_response) return { "products": products, "total": total, "skip": skip, "limit": limit, "shop": ShopResponse.model_validate(shop) }