shop product refactoring
This commit is contained in:
@@ -14,9 +14,9 @@ from sqlalchemy.orm import Session
|
||||
from app.core.database import get_db
|
||||
from middleware.auth import AuthManager
|
||||
from middleware.rate_limiter import RateLimiter
|
||||
from models.database.shop import Shop
|
||||
from models.database.vendor import Vendor
|
||||
from models.database.user import User
|
||||
from app.exceptions import (AdminRequiredException,ShopNotFoundException, UnauthorizedShopAccessException)
|
||||
from app.exceptions import (AdminRequiredException, VendorNotFoundException, UnauthorizedVendorAccessException)
|
||||
|
||||
# Set auto_error=False to prevent automatic 403 responses
|
||||
security = HTTPBearer(auto_error=False)
|
||||
@@ -43,18 +43,18 @@ def get_current_admin_user(current_user: User = Depends(get_current_user)):
|
||||
return auth_manager.require_admin(current_user)
|
||||
|
||||
|
||||
def get_user_shop(
|
||||
shop_code: str,
|
||||
def get_user_vendor(
|
||||
vendor_code: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get shop and verify user ownership."""
|
||||
shop = db.query(Shop).filter(Shop.shop_code == shop_code.upper()).first()
|
||||
if not shop:
|
||||
raise ShopNotFoundException(shop_code)
|
||||
"""Get vendor and verify user ownership."""
|
||||
vendor = db.query(Vendor).filter(Vendor.vendor_code == vendor_code.upper()).first()
|
||||
if not vendor:
|
||||
raise VendorNotFoundException(vendor_code)
|
||||
|
||||
if current_user.role != "admin" and shop.owner_id != current_user.id:
|
||||
raise UnauthorizedShopAccessException(shop_code, current_user.id)
|
||||
if current_user.role != "admin" and vendor.owner_id != current_user.id:
|
||||
raise UnauthorizedVendorAccessException(vendor_code, current_user.id)
|
||||
|
||||
return shop
|
||||
return vendor
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ This module provides classes and functions for:
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.api.v1 import admin, auth, marketplace, shop, stats, stock
|
||||
from app.api.v1 import admin, auth, marketplace, vendor, stats, stock
|
||||
|
||||
api_router = APIRouter()
|
||||
|
||||
@@ -17,6 +17,6 @@ api_router = APIRouter()
|
||||
api_router.include_router(admin.router, tags=["admin"])
|
||||
api_router.include_router(auth.router, tags=["authentication"])
|
||||
api_router.include_router(marketplace.router, tags=["marketplace"])
|
||||
api_router.include_router(shop.router, tags=["shop"])
|
||||
api_router.include_router(vendor.router, tags=["vendor"])
|
||||
api_router.include_router(stats.router, tags=["statistics"])
|
||||
api_router.include_router(stock.router, tags=["stock"])
|
||||
|
||||
@@ -4,7 +4,7 @@ Admin endpoints - simplified with service-level exception handling.
|
||||
|
||||
This module provides classes and functions for:
|
||||
- User management (view, toggle status)
|
||||
- Shop management (view, verify, toggle status)
|
||||
- Vendor management (view, verify, toggle status)
|
||||
- Marketplace import job monitoring
|
||||
- Admin dashboard statistics
|
||||
"""
|
||||
@@ -20,7 +20,7 @@ from app.core.database import get_db
|
||||
from app.services.admin_service import admin_service
|
||||
from models.schemas.auth import UserResponse
|
||||
from models.schemas.marketplace_import_job import MarketplaceImportJobResponse
|
||||
from models.schemas.shop import ShopListResponse
|
||||
from models.schemas.vendor import VendorListResponse
|
||||
from models.database.user import User
|
||||
|
||||
router = APIRouter()
|
||||
@@ -50,37 +50,37 @@ def toggle_user_status(
|
||||
return {"message": message}
|
||||
|
||||
|
||||
@router.get("/admin/shops", response_model=ShopListResponse)
|
||||
def get_all_shops_admin(
|
||||
@router.get("/admin/vendors", response_model=VendorListResponse)
|
||||
def get_all_vendors_admin(
|
||||
skip: int = Query(0, ge=0),
|
||||
limit: int = Query(100, ge=1, le=1000),
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: User = Depends(get_current_admin_user),
|
||||
):
|
||||
"""Get all shops with admin view (Admin only)."""
|
||||
shops, total = admin_service.get_all_shops(db=db, skip=skip, limit=limit)
|
||||
return ShopListResponse(shops=shops, total=total, skip=skip, limit=limit)
|
||||
"""Get all vendors with admin view (Admin only)."""
|
||||
vendors, total = admin_service.get_all_vendors(db=db, skip=skip, limit=limit)
|
||||
return VendorListResponse(vendors=vendors, total=total, skip=skip, limit=limit)
|
||||
|
||||
|
||||
@router.put("/admin/shops/{shop_id}/verify")
|
||||
def verify_shop(
|
||||
shop_id: int,
|
||||
@router.put("/admin/vendors/{vendor_id}/verify")
|
||||
def verify_vendor(
|
||||
vendor_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: User = Depends(get_current_admin_user),
|
||||
):
|
||||
"""Verify/unverify shop (Admin only)."""
|
||||
shop, message = admin_service.verify_shop(db, shop_id)
|
||||
"""Verify/unverify vendor (Admin only)."""
|
||||
vendor, message = admin_service.verify_vendor(db, vendor_id)
|
||||
return {"message": message}
|
||||
|
||||
|
||||
@router.put("/admin/shops/{shop_id}/status")
|
||||
def toggle_shop_status(
|
||||
shop_id: int,
|
||||
@router.put("/admin/vendors/{vendor_id}/status")
|
||||
def toggle_vendor_status(
|
||||
vendor_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: User = Depends(get_current_admin_user),
|
||||
):
|
||||
"""Toggle shop active status (Admin only)."""
|
||||
shop, message = admin_service.toggle_shop_status(db, shop_id)
|
||||
"""Toggle vendor active status (Admin only)."""
|
||||
vendor, message = admin_service.toggle_vendor_status(db, vendor_id)
|
||||
return {"message": message}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ def toggle_shop_status(
|
||||
)
|
||||
def get_all_marketplace_import_jobs(
|
||||
marketplace: Optional[str] = Query(None),
|
||||
shop_name: Optional[str] = Query(None),
|
||||
vendor_name: Optional[str] = Query(None),
|
||||
status: Optional[str] = Query(None),
|
||||
skip: int = Query(0, ge=0),
|
||||
limit: int = Query(100, ge=1, le=100),
|
||||
@@ -100,7 +100,7 @@ def get_all_marketplace_import_jobs(
|
||||
return admin_service.get_marketplace_import_jobs(
|
||||
db=db,
|
||||
marketplace=marketplace,
|
||||
shop_name=shop_name,
|
||||
vendor_name=vendor_name,
|
||||
status=status,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
@@ -116,10 +116,10 @@ def get_user_statistics(
|
||||
return admin_service.get_user_statistics(db)
|
||||
|
||||
|
||||
@router.get("/admin/stats/shops")
|
||||
def get_shop_statistics(
|
||||
@router.get("/admin/stats/vendors")
|
||||
def get_vendor_statistics(
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: User = Depends(get_current_admin_user),
|
||||
):
|
||||
"""Get shop statistics for admin dashboard (Admin only)."""
|
||||
return admin_service.get_shop_statistics(db)
|
||||
"""Get vendor statistics for admin dashboard (Admin only)."""
|
||||
return admin_service.get_vendor_statistics(db)
|
||||
|
||||
@@ -42,7 +42,7 @@ logger = logging.getLogger(__name__)
|
||||
@router.get("/marketplace/product/export-csv")
|
||||
async def export_csv(
|
||||
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
|
||||
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
|
||||
vendor_name: Optional[str] = Query(None, description="Filter by vendor name"),
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
@@ -50,14 +50,14 @@ async def export_csv(
|
||||
|
||||
def generate_csv():
|
||||
return marketplace_product_service.generate_csv_export(
|
||||
db=db, marketplace=marketplace, shop_name=shop_name
|
||||
db=db, marketplace=marketplace, vendor_name=vendor_name
|
||||
)
|
||||
|
||||
filename = "marketplace_products_export"
|
||||
if marketplace:
|
||||
filename += f"_{marketplace}"
|
||||
if shop_name:
|
||||
filename += f"_{shop_name}"
|
||||
if vendor_name:
|
||||
filename += f"_{vendor_name}"
|
||||
filename += ".csv"
|
||||
|
||||
return StreamingResponse(
|
||||
@@ -75,12 +75,12 @@ def get_products(
|
||||
category: Optional[str] = Query(None),
|
||||
availability: Optional[str] = Query(None),
|
||||
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
|
||||
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
|
||||
vendor_name: Optional[str] = Query(None, description="Filter by vendor name"),
|
||||
search: Optional[str] = Query(None),
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Get products with advanced filtering including marketplace and shop (Protected)."""
|
||||
"""Get products with advanced filtering including marketplace and vendor (Protected)."""
|
||||
products, total = marketplace_product_service.get_products_with_filters(
|
||||
db=db,
|
||||
skip=skip,
|
||||
@@ -89,7 +89,7 @@ def get_products(
|
||||
category=category,
|
||||
availability=availability,
|
||||
marketplace=marketplace,
|
||||
shop_name=shop_name,
|
||||
vendor_name=vendor_name,
|
||||
search=search,
|
||||
)
|
||||
|
||||
@@ -166,7 +166,7 @@ async def import_products_from_marketplace(
|
||||
):
|
||||
"""Import products from marketplace CSV with background processing (Protected)."""
|
||||
logger.info(
|
||||
f"Starting marketplace import: {request.marketplace} -> {request.shop_code} by user {current_user.username}"
|
||||
f"Starting marketplace import: {request.marketplace} -> {request.vendor_code} by user {current_user.username}"
|
||||
)
|
||||
|
||||
# Create import job through service
|
||||
@@ -178,7 +178,7 @@ async def import_products_from_marketplace(
|
||||
import_job.id,
|
||||
request.url,
|
||||
request.marketplace,
|
||||
request.shop_code,
|
||||
request.vendor_code,
|
||||
request.batch_size or 1000,
|
||||
)
|
||||
|
||||
@@ -186,9 +186,9 @@ async def import_products_from_marketplace(
|
||||
job_id=import_job.id,
|
||||
status="pending",
|
||||
marketplace=request.marketplace,
|
||||
shop_code=request.shop_code,
|
||||
shop_id=import_job.shop_id,
|
||||
shop_name=import_job.shop_name,
|
||||
vendor_code=request.vendor_code,
|
||||
vendor_id=import_job.vendor_id,
|
||||
vendor_name=import_job.vendor_name,
|
||||
message=f"Marketplace import started from {request.marketplace}. Check status with "
|
||||
f"/import-status/{import_job.id}",
|
||||
)
|
||||
@@ -212,7 +212,7 @@ def get_marketplace_import_status(
|
||||
)
|
||||
def get_marketplace_import_jobs(
|
||||
marketplace: Optional[str] = Query(None, description="Filter by marketplace"),
|
||||
shop_name: Optional[str] = Query(None, description="Filter by shop name"),
|
||||
vendor_name: Optional[str] = Query(None, description="Filter by vendor name"),
|
||||
skip: int = Query(0, ge=0),
|
||||
limit: int = Query(50, ge=1, le=100),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -223,7 +223,7 @@ def get_marketplace_import_jobs(
|
||||
db=db,
|
||||
user=current_user,
|
||||
marketplace=marketplace,
|
||||
shop_name=shop_name,
|
||||
vendor_name=vendor_name,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# app/api/v1/shop.py
|
||||
"""
|
||||
Shop endpoints - simplified with service-level exception handling.
|
||||
|
||||
This module provides classes and functions for:
|
||||
- Shop CRUD operations and management
|
||||
- Shop product catalog management
|
||||
- Shop filtering and verification
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_user, get_user_shop
|
||||
from app.core.database import get_db
|
||||
from app.services.shop_service import shop_service
|
||||
from models.schemas.shop import (ShopCreate, ShopListResponse,ShopResponse)
|
||||
from models.schemas.product import (ProductCreate,ProductResponse)
|
||||
from models.database.user import User
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@router.post("/shop", 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)."""
|
||||
shop = shop_service.create_shop(
|
||||
db=db, shop_data=shop_data, current_user=current_user
|
||||
)
|
||||
return ShopResponse.model_validate(shop)
|
||||
|
||||
|
||||
@router.get("/shop", 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)."""
|
||||
shops, total = shop_service.get_shops(
|
||||
db=db,
|
||||
current_user=current_user,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
active_only=active_only,
|
||||
verified_only=verified_only,
|
||||
)
|
||||
|
||||
return ShopListResponse(shops=shops, total=total, skip=skip, limit=limit)
|
||||
|
||||
|
||||
@router.get("/shop/{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 = shop_service.get_shop_by_code(
|
||||
db=db, shop_code=shop_code, current_user=current_user
|
||||
)
|
||||
return ShopResponse.model_validate(shop)
|
||||
|
||||
|
||||
@router.post("/shop/{shop_code}/products", response_model=ProductResponse)
|
||||
def add_product_to_shop(
|
||||
shop_code: str,
|
||||
product: ProductCreate,
|
||||
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 (using existing dependency)
|
||||
shop = get_user_shop(shop_code, current_user, db)
|
||||
|
||||
# Add product to shop
|
||||
new_product = shop_service.add_product_to_shop(
|
||||
db=db, shop=shop, product=product
|
||||
)
|
||||
|
||||
# Return with product details
|
||||
response = ProductResponse.model_validate(new_product)
|
||||
response.marketplace_product = new_product.marketplace_product
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/shop/{shop_code}/products")
|
||||
def get_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
|
||||
shop = shop_service.get_shop_by_code(
|
||||
db=db, shop_code=shop_code, current_user=current_user
|
||||
)
|
||||
|
||||
# Get shop products
|
||||
vendor_products, total = shop_service.get_products(
|
||||
db=db,
|
||||
shop=shop,
|
||||
current_user=current_user,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
active_only=active_only,
|
||||
featured_only=featured_only,
|
||||
)
|
||||
|
||||
# Format response
|
||||
products = []
|
||||
for vp in vendor_products:
|
||||
product_response = ProductResponse.model_validate(vp)
|
||||
product_response.marketplace_product = vp.marketplace_product
|
||||
products.append(product_response)
|
||||
|
||||
return {
|
||||
"products": products,
|
||||
"total": total,
|
||||
"skip": skip,
|
||||
"limit": limit,
|
||||
"shop": ShopResponse.model_validate(shop),
|
||||
}
|
||||
@@ -36,7 +36,7 @@ def get_stats(
|
||||
unique_brands=stats_data["unique_brands"],
|
||||
unique_categories=stats_data["unique_categories"],
|
||||
unique_marketplaces=stats_data["unique_marketplaces"],
|
||||
unique_shops=stats_data["unique_shops"],
|
||||
unique_vendors=stats_data["unique_vendors"],
|
||||
total_stock_entries=stats_data["total_stock_entries"],
|
||||
total_inventory_quantity=stats_data["total_inventory_quantity"],
|
||||
)
|
||||
@@ -87,7 +87,7 @@ def get_stats(
|
||||
unique_brands=stats_data["unique_brands"],
|
||||
unique_categories=stats_data["unique_categories"],
|
||||
unique_marketplaces=stats_data["unique_marketplaces"],
|
||||
unique_shops=stats_data["unique_shops"],
|
||||
unique_vendors=stats_data["unique_vendors"],
|
||||
total_stock_entries=stats_data["total_stock_entries"],
|
||||
total_inventory_quantity=stats_data["total_inventory_quantity"],
|
||||
)
|
||||
@@ -104,7 +104,7 @@ def get_marketplace_stats(
|
||||
MarketplaceStatsResponse(
|
||||
marketplace=stat["marketplace"],
|
||||
total_products=stat["total_products"],
|
||||
unique_shops=stat["unique_shops"],
|
||||
unique_vendors=stat["unique_vendors"],
|
||||
unique_brands=stat["unique_brands"],
|
||||
)
|
||||
for stat in marketplace_stats
|
||||
|
||||
137
app/api/v1/vendor.py
Normal file
137
app/api/v1/vendor.py
Normal file
@@ -0,0 +1,137 @@
|
||||
# app/api/v1/vendor.py
|
||||
"""
|
||||
Vendor endpoints - simplified with service-level exception handling.
|
||||
|
||||
This module provides classes and functions for:
|
||||
- Vendor CRUD operations and management
|
||||
- Vendor product catalog management
|
||||
- Vendor filtering and verification
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_user, get_user_vendor
|
||||
from app.core.database import get_db
|
||||
from app.services.vendor_service import vendor_service
|
||||
from models.schemas.vendor import (VendorCreate, VendorListResponse, VendorResponse)
|
||||
from models.schemas.product import (ProductCreate,ProductResponse)
|
||||
from models.database.user import User
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@router.post("/vendor", response_model=VendorResponse)
|
||||
def create_vendor(
|
||||
vendor_data: VendorCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Create a new vendor (Protected)."""
|
||||
vendor = vendor_service.create_vendor(
|
||||
db=db, vendor_data=vendor_data, current_user=current_user
|
||||
)
|
||||
return VendorResponse.model_validate(vendor)
|
||||
|
||||
|
||||
@router.get("/vendor", response_model=VendorListResponse)
|
||||
def get_vendors(
|
||||
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 vendors with filtering (Protected)."""
|
||||
vendors, total = vendor_service.get_vendors(
|
||||
db=db,
|
||||
current_user=current_user,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
active_only=active_only,
|
||||
verified_only=verified_only,
|
||||
)
|
||||
|
||||
return VendorListResponse(vendors=vendors, total=total, skip=skip, limit=limit)
|
||||
|
||||
|
||||
@router.get("/vendor/{vendor_code}", response_model=VendorResponse)
|
||||
def get_vendor(
|
||||
vendor_code: str,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Get vendor details (Protected)."""
|
||||
vendor = vendor_service.get_vendor_by_code(
|
||||
db=db, vendor_code=vendor_code, current_user=current_user
|
||||
)
|
||||
return VendorResponse.model_validate(vendor)
|
||||
|
||||
|
||||
@router.post("/vendor/{vendor_code}/products", response_model=ProductResponse)
|
||||
def add_product_to_catalog(
|
||||
vendor_code: str,
|
||||
product: ProductCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Add existing product to vendor catalog with vendor -specific settings (Protected)."""
|
||||
# Get and verify vendor (using existing dependency)
|
||||
vendor = get_user_vendor(vendor_code, current_user, db)
|
||||
|
||||
# Add product to vendor
|
||||
new_product = vendor_service.add_product_to_catalog(
|
||||
db=db, vendor=vendor, product=product
|
||||
)
|
||||
|
||||
# Return with product details
|
||||
response = ProductResponse.model_validate(new_product)
|
||||
response.marketplace_product = new_product.marketplace_product
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/vendor/{vendor_code}/products")
|
||||
def get_products(
|
||||
vendor_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 vendor catalog (Protected)."""
|
||||
# Get vendor
|
||||
vendor = vendor_service.get_vendor_by_code(
|
||||
db=db, vendor_code=vendor_code, current_user=current_user
|
||||
)
|
||||
|
||||
# Get vendor products
|
||||
vendor_products, total = vendor_service.get_products(
|
||||
db=db,
|
||||
vendor=vendor,
|
||||
current_user=current_user,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
active_only=active_only,
|
||||
featured_only=featured_only,
|
||||
)
|
||||
|
||||
# Format response
|
||||
products = []
|
||||
for vp in vendor_products:
|
||||
product_response = ProductResponse.model_validate(vp)
|
||||
product_response.marketplace_product = vp.marketplace_product
|
||||
products.append(product_response)
|
||||
|
||||
return {
|
||||
"products": products,
|
||||
"total": total,
|
||||
"skip": skip,
|
||||
"limit": limit,
|
||||
"vendor": VendorResponse.model_validate(vendor),
|
||||
}
|
||||
Reference in New Issue
Block a user