From adbcee4ce3cb4665aba561fc9576be8333fe0b9a Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Sun, 9 Nov 2025 18:47:53 +0100 Subject: [PATCH] middleware fix for path-based vendor url --- .env | 2 +- Makefile | 27 +- app/exceptions/error_renderer.py | 2 +- app/routes/shop_pages.py | 486 ++++++-- create_project_structure.bat | 355 ------ docs/development/synology-github-repo.md | 2 +- main.py | 124 +- middleware/context_middleware.py | 101 +- middleware/path_rewrite_middleware.py | 63 + middleware/theme_context.py | 92 +- middleware/vendor_context.py | 197 +-- models/database/vendor.py | 1 - scripts/seed_database.py | 1436 +++++++++++++++++++--- 13 files changed, 2078 insertions(+), 810 deletions(-) delete mode 100644 create_project_structure.bat create mode 100644 middleware/path_rewrite_middleware.py diff --git a/.env b/.env index 4b92403e..01271fbb 100644 --- a/.env +++ b/.env @@ -34,7 +34,7 @@ RATE_LIMIT_REQUESTS=100 RATE_LIMIT_WINDOW=3600 # Logging -LOG_LEVEL=INFO +LOG_LEVEL=DEBUG LOG_FILE=log/app.log # Platform domain configuration diff --git a/Makefile b/Makefile index 76b4c629..21ab040f 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,31 @@ backup-db: @echo Creating database backup... @$(PYTHON) scripts/backup_database.py +# Add these commands to the DATABASE section after backup-db: + +seed: + @echo Seeding database with comprehensive test data... + $(PYTHON) scripts/seed_database.py + @echo Seeding completed successfully + +seed-minimal: + @echo Seeding database with minimal data (admin + 1 vendor)... + $(PYTHON) scripts/seed_database.py --minimal + @echo Minimal seeding completed + +seed-reset: + @echo WARNING: This will DELETE ALL existing data! + $(PYTHON) scripts/seed_database.py --reset + @echo Database reset and seeded + +# Complete database setup (migrate + seed) +db-setup: migrate-up seed + @echo Database setup complete! + @echo Run 'make dev' to start development server + +db-reset: migrate-down migrate-up seed-reset + @echo Database completely reset! + # ============================================================================= # TESTING # ============================================================================= @@ -295,4 +320,4 @@ help-db: @echo 1. Edit your SQLAlchemy models @echo 2. make migrate-create message="add_new_feature" @echo 3. Review the generated migration file - @echo 4. make migrate-up \ No newline at end of file + @echo 4. make migrate-up diff --git a/app/exceptions/error_renderer.py b/app/exceptions/error_renderer.py index 74608742..27874ad5 100644 --- a/app/exceptions/error_renderer.py +++ b/app/exceptions/error_renderer.py @@ -344,4 +344,4 @@ class ErrorPageRenderer: """ - return HTMLResponse(content=html_content, status_code=status_code) \ No newline at end of file + return HTMLResponse(content=html_content, status_code=status_code) diff --git a/app/routes/shop_pages.py b/app/routes/shop_pages.py index 5a300860..bed982ee 100644 --- a/app/routes/shop_pages.py +++ b/app/routes/shop_pages.py @@ -29,6 +29,7 @@ Routes: - GET /shop/account/addresses → Address management (auth required) """ +import logging from fastapi import APIRouter, Request, Depends, Path from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates @@ -40,59 +41,144 @@ from models.database.user import User router = APIRouter() templates = Jinja2Templates(directory="app/templates") +logger = logging.getLogger(__name__) + + +# ============================================================================ +# HELPER: Build Shop Template Context +# ============================================================================ + +def get_shop_context(request: Request, **extra_context) -> dict: + """ + Build template context for shop pages. + + Automatically includes vendor and theme from middleware request.state. + Additional context can be passed as keyword arguments. + + Args: + request: FastAPI request object with vendor/theme in state + **extra_context: Additional variables for template (user, product_id, etc.) + + Returns: + Dictionary with request, vendor, theme, and extra context + + Example: + # Simple usage + get_shop_context(request) + + # With extra data + get_shop_context(request, user=current_user, product_id=123) + """ + # Extract from middleware state + vendor = getattr(request.state, 'vendor', None) + theme = getattr(request.state, 'theme', None) + clean_path = getattr(request.state, 'clean_path', request.url.path) + + if vendor is None: + logger.warning( + "[SHOP_CONTEXT] Vendor not found in request.state", + extra={ + "path": request.url.path, + "host": request.headers.get("host", ""), + "has_vendor": False, + } + ) + + context = { + "request": request, + "vendor": vendor, + "theme": theme, + "clean_path": clean_path, + } + + # Add any extra context (user, product_id, category_slug, etc.) + if extra_context: + context.update(extra_context) + + logger.debug( + f"[SHOP_CONTEXT] Context built", + extra={ + "vendor_id": vendor.id if vendor else None, + "vendor_name": vendor.name if vendor else None, + "has_theme": theme is not None, + "extra_keys": list(extra_context.keys()) if extra_context else [], + } + ) + + return context + # ============================================================================ # PUBLIC SHOP ROUTES (No Authentication Required) # ============================================================================ -@router.get("/shop/", response_class=HTMLResponse, include_in_schema=False) -@router.get("/shop/products", response_class=HTMLResponse, include_in_schema=False) +@router.get("/", response_class=HTMLResponse, include_in_schema=False) +@router.get("/products", response_class=HTMLResponse, include_in_schema=False) async def shop_products_page(request: Request): """ Render shop homepage / product catalog. Shows featured products and categories. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/products.html", - { - "request": request, - } + get_shop_context(request) ) @router.get("/shop/products/{product_id}", response_class=HTMLResponse, include_in_schema=False) async def shop_product_detail_page( - request: Request, - product_id: int = Path(..., description="Product ID") + request: Request, + product_id: int = Path(..., description="Product ID") ): """ Render product detail page. Shows product information, images, reviews, and buy options. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/product.html", - { - "request": request, - "product_id": product_id, - } + get_shop_context(request, product_id=product_id) ) @router.get("/shop/categories/{category_slug}", response_class=HTMLResponse, include_in_schema=False) async def shop_category_page( - request: Request, - category_slug: str = Path(..., description="Category slug") + request: Request, + category_slug: str = Path(..., description="Category slug") ): """ Render category products page. Shows all products in a specific category. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/category.html", - { - "request": request, - "category_slug": category_slug, - } + get_shop_context(request, category_slug=category_slug) ) @@ -102,11 +188,18 @@ async def shop_cart_page(request: Request): Render shopping cart page. Shows cart items and allows quantity updates. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/cart.html", - { - "request": request, - } + get_shop_context(request) ) @@ -116,11 +209,18 @@ async def shop_checkout_page(request: Request): Render checkout page. Handles shipping, payment, and order confirmation. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/checkout.html", - { - "request": request, - } + get_shop_context(request) ) @@ -130,11 +230,18 @@ async def shop_search_page(request: Request): Render search results page. Shows products matching search query. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/search.html", - { - "request": request, - } + get_shop_context(request) ) @@ -148,11 +255,18 @@ async def shop_register_page(request: Request): Render customer registration page. No authentication required. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/register.html", - { - "request": request, - } + get_shop_context(request) ) @@ -162,11 +276,18 @@ async def shop_login_page(request: Request): Render customer login page. No authentication required. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/login.html", - { - "request": request, - } + get_shop_context(request) ) @@ -176,11 +297,18 @@ async def shop_forgot_password_page(request: Request): Render forgot password page. Allows customers to reset their password. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/forgot-password.html", - { - "request": request, - } + get_shop_context(request) ) @@ -193,148 +321,198 @@ async def shop_account_root(): """ Redirect /shop/account/ to dashboard. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return RedirectResponse(url="/shop/account/dashboard", status_code=302) @router.get("/shop/account/dashboard", response_class=HTMLResponse, include_in_schema=False) async def shop_account_dashboard_page( - request: Request, - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer account dashboard. Shows account overview, recent orders, and quick links. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/dashboard.html", - { - "request": request, - "user": current_user, - } + get_shop_context(request, user=current_user) ) @router.get("/shop/account/orders", response_class=HTMLResponse, include_in_schema=False) async def shop_orders_page( - request: Request, - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer orders history page. Shows all past and current orders. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/orders.html", - { - "request": request, - "user": current_user, - } + get_shop_context(request, user=current_user) ) @router.get("/shop/account/orders/{order_id}", response_class=HTMLResponse, include_in_schema=False) async def shop_order_detail_page( - request: Request, - order_id: int = Path(..., description="Order ID"), - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + order_id: int = Path(..., description="Order ID"), + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer order detail page. Shows detailed order information and tracking. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/order-detail.html", - { - "request": request, - "user": current_user, - "order_id": order_id, - } + get_shop_context(request, user=current_user, order_id=order_id) ) @router.get("/shop/account/profile", response_class=HTMLResponse, include_in_schema=False) async def shop_profile_page( - request: Request, - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer profile page. Edit personal information and preferences. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/profile.html", - { - "request": request, - "user": current_user, - } + get_shop_context(request, user=current_user) ) @router.get("/shop/account/addresses", response_class=HTMLResponse, include_in_schema=False) async def shop_addresses_page( - request: Request, - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer addresses management page. Manage shipping and billing addresses. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/addresses.html", - { - "request": request, - "user": current_user, - } + get_shop_context(request, user=current_user) ) @router.get("/shop/account/wishlist", response_class=HTMLResponse, include_in_schema=False) async def shop_wishlist_page( - request: Request, - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer wishlist page. View and manage saved products. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/wishlist.html", - { - "request": request, - "user": current_user, - } + get_shop_context(request, user=current_user) ) @router.get("/shop/account/settings", response_class=HTMLResponse, include_in_schema=False) async def shop_settings_page( - request: Request, - current_user: User = Depends(get_current_customer_from_cookie_or_header), - db: Session = Depends(get_db) + request: Request, + current_user: User = Depends(get_current_customer_from_cookie_or_header), + db: Session = Depends(get_db) ): """ Render customer account settings page. Configure notifications, privacy, and preferences. Requires customer authentication. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/account/settings.html", - { - "request": request, - "user": current_user, - } + get_shop_context(request, user=current_user) ) @@ -347,11 +525,18 @@ async def shop_about_page(request: Request): """ Render about us page. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/about.html", - { - "request": request, - } + get_shop_context(request) ) @@ -360,11 +545,18 @@ async def shop_contact_page(request: Request): """ Render contact us page. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/contact.html", - { - "request": request, - } + get_shop_context(request) ) @@ -373,11 +565,18 @@ async def shop_faq_page(request: Request): """ Render FAQ page. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/faq.html", - { - "request": request, - } + get_shop_context(request) ) @@ -386,11 +585,18 @@ async def shop_privacy_page(request: Request): """ Render privacy policy page. """ + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), + } + ) + return templates.TemplateResponse( "shop/privacy.html", - { - "request": request, - } + get_shop_context(request) ) @@ -399,9 +605,85 @@ async def shop_terms_page(request: Request): """ Render terms and conditions page. """ - return templates.TemplateResponse( - "shop/terms.html", - { - "request": request, + logger.debug( + f"[SHOP_HANDLER] shop_products_page REACHED", + extra={ + "path": request.url.path, + "vendor": getattr(request.state, 'vendor', 'NOT SET'), + "context": getattr(request.state, 'context_type', 'NOT SET'), } ) + + return templates.TemplateResponse( + "shop/terms.html", + get_shop_context(request) + ) + + +# ============================================================================ +# DEBUG ENDPOINTS - For troubleshooting context issues +# ============================================================================ + +@router.get("/debug/context", response_class=HTMLResponse, include_in_schema=False) +async def debug_context(request: Request): + """ + DEBUG ENDPOINT: Display request context. + + Shows what's available in request.state. + Useful for troubleshooting template variable issues. + + URL: /shop/debug/context + """ + vendor = getattr(request.state, 'vendor', None) + theme = getattr(request.state, 'theme', None) + + debug_info = { + "path": request.url.path, + "host": request.headers.get("host", ""), + "vendor": { + "found": vendor is not None, + "id": vendor.id if vendor else None, + "name": vendor.name if vendor else None, + "subdomain": vendor.subdomain if vendor else None, + "is_active": vendor.is_active if vendor else None, + }, + "theme": { + "found": theme is not None, + "name": theme.get("theme_name") if theme else None, + }, + "clean_path": getattr(request.state, 'clean_path', 'NOT SET'), + "context_type": str(getattr(request.state, 'context_type', 'NOT SET')), + } + + # Return as JSON-like HTML for easy reading + import json + html_content = f""" + + + + Debug Context + + + +

Request Context Debug

+
{json.dumps(debug_info, indent=2)}
+ +

Status

+

+ Vendor: {'✓ Found' if vendor else '✗ Not Found'} +

+

+ Theme: {'✓ Found' if theme else '✗ Not Found'} +

+

+ Context Type: {str(getattr(request.state, 'context_type', 'NOT SET'))} +

+ + + """ + return HTMLResponse(content=html_content) diff --git a/create_project_structure.bat b/create_project_structure.bat deleted file mode 100644 index af48bbab..00000000 --- a/create_project_structure.bat +++ /dev/null @@ -1,355 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -echo ======================================== -echo FastAPI Project Structure Builder -echo (Safe Mode - Won't Override Existing Files) -echo ======================================== -echo. - -:: Create root directories -call :CreateDir "app" -call :CreateDir "app\api" -call :CreateDir "app\api\v1" -call :CreateDir "app\api\v1\admin" -call :CreateDir "app\api\v1\vendor" -call :CreateDir "app\api\v1\public" -call :CreateDir "app\api\v1\public\vendors" -call :CreateDir "app\api\v1\shared" -call :CreateDir "app\core" -call :CreateDir "app\exceptions" -call :CreateDir "app\services" - -call :CreateDir "tasks" - -call :CreateDir "models" -call :CreateDir "models\database" -call :CreateDir "models\schema" - -call :CreateDir "middleware" -call :CreateDir "storage" - -call :CreateDir "static" -call :CreateDir "static\admin" -call :CreateDir "static\vendor" -call :CreateDir "static\vendor\admin" -call :CreateDir "static\vendor\admin\marketplace" -call :CreateDir "static\shop" -call :CreateDir "static\shop\account" -call :CreateDir "static\css" -call :CreateDir "static\css\admin" -call :CreateDir "static\css\vendor" -call :CreateDir "static\css\shop" -call :CreateDir "static\css\shared" -call :CreateDir "static\css\themes" -call :CreateDir "static\js" -call :CreateDir "static\js\shared" -call :CreateDir "static\js\admin" -call :CreateDir "static\js\vendor" -call :CreateDir "static\js\shop" - -echo. -echo Creating Python files... -echo. - -:: Root files -call :CreatePyFile "main.py" "FastAPI application entry point" - -:: API files -call :CreatePyFile "app\api\deps.py" "Common dependencies" -call :CreatePyFile "app\api\main.py" "API router setup" -call :CreatePyFile "app\api\__init__.py" "" -call :CreatePyFile "app\api\v1\__init__.py" "" - -:: Admin API files -call :CreatePyFile "app\api\v1\admin\__init__.py" "" -call :CreatePyFile "app\api\v1\admin\auth.py" "Admin authentication" -call :CreatePyFile "app\api\v1\admin\vendors.py" "Vendor management - CRUD and bulk import" -call :CreatePyFile "app\api\v1\admin\dashboard.py" "Admin dashboard and statistics" -call :CreatePyFile "app\api\v1\admin\users.py" "User management across vendors" -call :CreatePyFile "app\api\v1\admin\marketplace.py" "System-wide marketplace monitoring" -call :CreatePyFile "app\api\v1\admin\monitoring.py" "Platform monitoring and alerts" - -:: Vendor API files -call :CreatePyFile "app\api\v1\vendor\__init__.py" "" -call :CreatePyFile "app\api\v1\vendor\auth.py" "Vendor team authentication" -call :CreatePyFile "app\api\v1\vendor\dashboard.py" "Vendor dashboard and statistics" -call :CreatePyFile "app\api\v1\vendor\products.py" "Vendor catalog management - Product table" -call :CreatePyFile "app\api\v1\vendor\marketplace.py" "Marketplace import and selection - MarketplaceProduct table" -call :CreatePyFile "app\api\v1\vendor\orders.py" "Vendor order management" -call :CreatePyFile "app\api\v1\vendor\customers.py" "Vendor customer management" -call :CreatePyFile "app\api\v1\vendor\teams.py" "Team member management" -call :CreatePyFile "app\api\v1\vendor\inventory.py" "Inventory operations - vendor catalog products" -call :CreatePyFile "app\api\v1\vendor\payments.py" "Payment configuration and processing" -call :CreatePyFile "app\api\v1\vendor\media.py" "File and media management" -call :CreatePyFile "app\api\v1\vendor\notifications.py" "Notification management" -call :CreatePyFile "app\api\v1\vendor\settings.py" "Vendor settings and configuration" - -:: Public API files -call :CreatePyFile "app\api\v1\public\__init__.py" "" -call :CreatePyFile "app\api\v1\public\vendors\shop.py" "Public shop info" -call :CreatePyFile "app\api\v1\public\vendors\products.py" "Public product catalog - Product table only" -call :CreatePyFile "app\api\v1\public\vendors\search.py" "Product search functionality" -call :CreatePyFile "app\api\v1\public\vendors\cart.py" "Shopping cart operations" -call :CreatePyFile "app\api\v1\public\vendors\orders.py" "Order placement" -call :CreatePyFile "app\api\v1\public\vendors\payments.py" "Payment processing" -call :CreatePyFile "app\api\v1\public\vendors\auth.py" "Customer authentication" - -:: Shared API files -call :CreatePyFile "app\api\v1\shared\health.py" "Health checks" -call :CreatePyFile "app\api\v1\shared\webhooks.py" "External webhooks - Stripe, etc" -call :CreatePyFile "app\api\v1\shared\uploads.py" "File upload handling" - -:: Core files -call :CreatePyFile "app\core\__init__.py" "" -call :CreatePyFile "app\core\config.py" "Configuration settings" -call :CreatePyFile "app\core\database.py" "Database setup" -call :CreatePyFile "app\core\lifespan.py" "App lifecycle management" - -:: Exception files -call :CreatePyFile "app\exceptions\__init__.py" "All exception exports" -call :CreatePyFile "app\exceptions\base.py" "Base exception classes" -call :CreatePyFile "app\exceptions\handler.py" "Unified FastAPI exception handlers" -call :CreatePyFile "app\exceptions\auth.py" "Authentication and authorization exceptions" -call :CreatePyFile "app\exceptions\admin.py" "Admin operation exceptions" -call :CreatePyFile "app\exceptions\marketplace.py" "Import and marketplace exceptions" -call :CreatePyFile "app\exceptions\marketplace_product.py" "Marketplace staging exceptions" -call :CreatePyFile "app\exceptions\product.py" "Vendor catalog exceptions" -call :CreatePyFile "app\exceptions\vendor.py" "Vendor management exceptions" -call :CreatePyFile "app\exceptions\customer.py" "Customer management exceptions" -call :CreatePyFile "app\exceptions\order.py" "Order management exceptions" -call :CreatePyFile "app\exceptions\payment.py" "Payment processing exceptions" -call :CreatePyFile "app\exceptions\inventory.py" "Inventory management exceptions" -call :CreatePyFile "app\exceptions\media.py" "Media and file management exceptions" -call :CreatePyFile "app\exceptions\notification.py" "Notification exceptions" -call :CreatePyFile "app\exceptions\search.py" "Search exceptions" -call :CreatePyFile "app\exceptions\monitoring.py" "Monitoring exceptions" -call :CreatePyFile "app\exceptions\backup.py" "Backup and recovery exceptions" - -:: Service files -call :CreatePyFile "app\services\__init__.py" "" -call :CreatePyFile "app\services\auth_service.py" "Authentication and authorization services" -call :CreatePyFile "app\services\admin_service.py" "Admin services" -call :CreatePyFile "app\services\vendor_service.py" "Vendor management services" -call :CreatePyFile "app\services\customer_service.py" "Customer services - vendor-scoped" -call :CreatePyFile "app\services\team_service.py" "Team management services" -call :CreatePyFile "app\services\marketplace_service.py" "Marketplace import services - MarketplaceProduct" -call :CreatePyFile "app\services\marketplace_product_service.py" "Marketplace staging services" -call :CreatePyFile "app\services\product_service.py" "Vendor catalog services - Product" -call :CreatePyFile "app\services\order_service.py" "Order services - vendor-scoped" -call :CreatePyFile "app\services\payment_service.py" "Payment processing services" -call :CreatePyFile "app\services\inventory_service.py" "Inventory services - vendor catalog" -call :CreatePyFile "app\services\media_service.py" "File and media management services" -call :CreatePyFile "app\services\notification_service.py" "Email and notification services" -call :CreatePyFile "app\services\search_service.py" "Search and indexing services" -call :CreatePyFile "app\services\cache_service.py" "Caching services" -call :CreatePyFile "app\services\audit_service.py" "Audit logging services" -call :CreatePyFile "app\services\monitoring_service.py" "Application monitoring services" -call :CreatePyFile "app\services\backup_service.py" "Backup and recovery services" -call :CreatePyFile "app\services\configuration_service.py" "Configuration management services" -call :CreatePyFile "app\services\stats_service.py" "Statistics services - vendor-aware" - -:: Task files -call :CreatePyFile "tasks\__init__.py" "" -call :CreatePyFile "tasks\task_manager.py" "Celery configuration and task management" -call :CreatePyFile "tasks\marketplace_import.py" "Marketplace CSV import tasks" -call :CreatePyFile "tasks\email_tasks.py" "Email sending tasks" -call :CreatePyFile "tasks\media_processing.py" "Image processing and optimization tasks" -call :CreatePyFile "tasks\search_indexing.py" "Search index maintenance tasks" -call :CreatePyFile "tasks\analytics_tasks.py" "Analytics and reporting tasks" -call :CreatePyFile "tasks\cleanup_tasks.py" "Data cleanup and maintenance tasks" -call :CreatePyFile "tasks\backup_tasks.py" "Backup and recovery tasks" - -:: Database model files -call :CreatePyFile "models\__init__.py" "" -call :CreatePyFile "models\database\__init__.py" "Import all models for easy access" -call :CreatePyFile "models\database\base.py" "Base model class and common mixins" -call :CreatePyFile "models\database\user.py" "User model - with vendor relationships" -call :CreatePyFile "models\database\vendor.py" "Vendor, VendorUser, Role models" -call :CreatePyFile "models\database\customer.py" "Customer, CustomerAddress models - vendor-scoped" -call :CreatePyFile "models\database\marketplace_product.py" "MarketplaceProduct model - staging data" -call :CreatePyFile "models\database\product.py" "Product model - vendor catalog" -call :CreatePyFile "models\database\order.py" "Order, OrderItem models - vendor-scoped" -call :CreatePyFile "models\database\payment.py" "Payment, PaymentMethod, VendorPaymentConfig models" -call :CreatePyFile "models\database\inventory.py" "Inventory, InventoryMovement models - catalog products" -call :CreatePyFile "models\database\marketplace.py" "MarketplaceImportJob model" -call :CreatePyFile "models\database\media.py" "MediaFile, ProductMedia models" -call :CreatePyFile "models\database\notification.py" "NotificationTemplate, NotificationQueue, NotificationLog models" -call :CreatePyFile "models\database\search.py" "SearchIndex, SearchQuery models" -call :CreatePyFile "models\database\audit.py" "AuditLog, DataExportLog models" -call :CreatePyFile "models\database\monitoring.py" "PerformanceMetric, ErrorLog, SystemAlert models" -call :CreatePyFile "models\database\backup.py" "BackupLog, RestoreLog models" -call :CreatePyFile "models\database\configuration.py" "PlatformConfig, VendorConfig, FeatureFlag models" -call :CreatePyFile "models\database\task.py" "TaskLog model" -call :CreatePyFile "models\database\admin.py" "Admin-specific models" - -:: Schema model files -call :CreatePyFile "models\schema\__init__.py" "Common imports" -call :CreatePyFile "models\schema\base.py" "Base Pydantic models" -call :CreatePyFile "models\schema\auth.py" "Login, Token, User response models" -call :CreatePyFile "models\schema\vendor.py" "Vendor management models" -call :CreatePyFile "models\schema\customer.py" "Customer request and response models" -call :CreatePyFile "models\schema\team.py" "Team management models" -call :CreatePyFile "models\schema\marketplace_product.py" "Marketplace staging models" -call :CreatePyFile "models\schema\product.py" "Vendor catalog models" -call :CreatePyFile "models\schema\order.py" "Order models - vendor-scoped" -call :CreatePyFile "models\schema\payment.py" "Payment models" -call :CreatePyFile "models\schema\inventory.py" "Inventory operation models" -call :CreatePyFile "models\schema\marketplace.py" "Marketplace import job models" -call :CreatePyFile "models\schema\media.py" "Media and file management models" -call :CreatePyFile "models\schema\notification.py" "Notification models" -call :CreatePyFile "models\schema\search.py" "Search models" -call :CreatePyFile "models\schema\monitoring.py" "Monitoring models" -call :CreatePyFile "models\schema\admin.py" "Admin operation models" -call :CreatePyFile "models\schema\stats.py" "Statistics response models" - -:: Middleware files -call :CreatePyFile "middleware\__init__.py" "" -call :CreatePyFile "middleware\auth.py" "JWT authentication" -call :CreatePyFile "middleware\vendor_context.py" "Vendor context detection and injection" -call :CreatePyFile "middleware\rate_limiter.py" "Rate limiting" -call :CreatePyFile "middleware\logging_middleware.py" "Request logging" -call :CreatePyFile "middleware\decorators.py" "Cross-cutting concern decorators" - -:: Storage files -call :CreatePyFile "storage\__init__.py" "" -call :CreatePyFile "storage\backends.py" "Storage backend implementations" -call :CreatePyFile "storage\utils.py" "Storage utilities" - -echo. -echo Creating HTML files... -echo. - -:: HTML files - Admin -call :CreateHtmlFile "static\admin\login.html" "Admin login page" -call :CreateHtmlFile "static\admin\dashboard.html" "Admin dashboard" -call :CreateHtmlFile "static\admin\vendors.html" "Vendor management" -call :CreateHtmlFile "static\admin\users.html" "User management" -call :CreateHtmlFile "static\admin\marketplace.html" "System-wide marketplace monitoring" -call :CreateHtmlFile "static\admin\monitoring.html" "System monitoring" - -:: HTML files - Vendor -call :CreateHtmlFile "static\vendor\login.html" "Vendor team login" -call :CreateHtmlFile "static\vendor\dashboard.html" "Vendor dashboard" -call :CreateHtmlFile "static\vendor\admin\products.html" "Catalog management - Product table" -call :CreateHtmlFile "static\vendor\admin\marketplace\imports.html" "Import jobs and history" -call :CreateHtmlFile "static\vendor\admin\marketplace\browse.html" "Browse marketplace products - staging" -call :CreateHtmlFile "static\vendor\admin\marketplace\selected.html" "Selected products - pre-publish" -call :CreateHtmlFile "static\vendor\admin\marketplace\config.html" "Marketplace configuration" -call :CreateHtmlFile "static\vendor\admin\orders.html" "Order management" -call :CreateHtmlFile "static\vendor\admin\customers.html" "Customer management" -call :CreateHtmlFile "static\vendor\admin\teams.html" "Team management" -call :CreateHtmlFile "static\vendor\admin\inventory.html" "Inventory management - catalog products" -call :CreateHtmlFile "static\vendor\admin\payments.html" "Payment configuration" -call :CreateHtmlFile "static\vendor\admin\media.html" "Media library" -call :CreateHtmlFile "static\vendor\admin\notifications.html" "Notification templates and logs" -call :CreateHtmlFile "static\vendor\admin\settings.html" "Vendor settings" - -:: HTML files - Shop -call :CreateHtmlFile "static\shop\home.html" "Shop homepage" -call :CreateHtmlFile "static\shop\products.html" "Product catalog - Product table only" -call :CreateHtmlFile "static\shop\product.html" "Product detail page" -call :CreateHtmlFile "static\shop\search.html" "Search results page" -call :CreateHtmlFile "static\shop\cart.html" "Shopping cart" -call :CreateHtmlFile "static\shop\checkout.html" "Checkout process" -call :CreateHtmlFile "static\shop\account\login.html" "Customer login" -call :CreateHtmlFile "static\shop\account\register.html" "Customer registration" -call :CreateHtmlFile "static\shop\account\profile.html" "Customer profile" -call :CreateHtmlFile "static\shop\account\orders.html" "Order history" -call :CreateHtmlFile "static\shop\account\addresses.html" "Address management" - -echo. -echo Creating JavaScript files... -echo. - -:: JavaScript files - Shared -call :CreateJsFile "static\js\shared\vendor-context.js" "Vendor context detection and management" -call :CreateJsFile "static\js\shared\api-client.js" "API communication utilities" -call :CreateJsFile "static\js\shared\notification.js" "Notification handling" -call :CreateJsFile "static\js\shared\media-upload.js" "File upload utilities" -call :CreateJsFile "static\js\shared\search.js" "Search functionality" - -:: JavaScript files - Admin -call :CreateJsFile "static\js\admin\dashboard.js" "Admin dashboard" -call :CreateJsFile "static\js\admin\vendors.js" "Vendor management" -call :CreateJsFile "static\js\admin\monitoring.js" "System monitoring" -call :CreateJsFile "static\js\admin\analytics.js" "Admin analytics" - -:: JavaScript files - Vendor -call :CreateJsFile "static\js\vendor\products.js" "Catalog management" -call :CreateJsFile "static\js\vendor\marketplace.js" "Marketplace integration" -call :CreateJsFile "static\js\vendor\orders.js" "Order management" -call :CreateJsFile "static\js\vendor\payments.js" "Payment configuration" -call :CreateJsFile "static\js\vendor\media.js" "Media management" -call :CreateJsFile "static\js\vendor\dashboard.js" "Vendor dashboard" - -:: JavaScript files - Shop -call :CreateJsFile "static\js\shop\catalog.js" "Product browsing" -call :CreateJsFile "static\js\shop\search.js" "Product search" -call :CreateJsFile "static\js\shop\cart.js" "Shopping cart" -call :CreateJsFile "static\js\shop\checkout.js" "Checkout process" -call :CreateJsFile "static\js\shop\account.js" "Customer account" - -echo. -echo ======================================== -echo Build Complete! -echo ======================================== -echo. - -goto :eof - -:: Function to create directory if it doesn't exist -:CreateDir -if not exist "%~1" ( - mkdir "%~1" - echo [CREATED] Directory: %~1 -) else ( - echo [EXISTS] Directory: %~1 -) -goto :eof - -:: Function to create Python file if it doesn't exist -:CreatePyFile -if not exist "%~1" ( - if "%~2"=="" ( - echo. > "%~1" - ) else ( - echo # %~2 > "%~1" - ) - echo [CREATED] File: %~1 -) else ( - echo [SKIPPED] File: %~1 - already exists -) -goto :eof - -:: Function to create HTML file if it doesn't exist -:CreateHtmlFile -if not exist "%~1" ( - ( - echo ^ - echo ^ - echo ^ - echo ^ - echo ^ - echo ^%~2^ - echo ^ - echo ^ - echo ^