189 lines
6.2 KiB
Python
189 lines
6.2 KiB
Python
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)
|
|
}
|