Renaming models/api/ folder to models/schemas/

This commit is contained in:
2025-09-21 21:02:05 +02:00
parent ed775b9822
commit 2db03b20c5
32 changed files with 63 additions and 181 deletions

8
.env
View File

@@ -10,6 +10,14 @@ VERSION=0.0.1
# For development, you can use SQLite:
DATABASE_URL=sqlite:///./ecommerce.db
# Documentation
# .env.development
DOCUMENTATION_URL=http://localhost:8001
# .env.production
# DOCUMENTATION_URL=https://yourdomain.com/docs
# .env.staging
# DOCUMENTATION_URL=https://staging-docs.yourdomain.com
# JWT Configuration
JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production
JWT_EXPIRE_HOURS=24

29
TODO
View File

@@ -1,29 +0,0 @@
Best Practice Recommendation
For production applications, consider using database migrations (like Alembic) to manage schema changes including index
creation, rather than creating them programmatically at startup. This provides better control and tracking of database changes.
https://letzshop-google-shopping-product-exports-production.s3.eu-west-1.amazonaws.com/city_zones/strassen/vendors/wizard-cloud-marketing-s-a-r-l/google_shopping/products_fr.csv
what are those?
INFO: ('192.168.1.125', 53912) - "WebSocket /" 403
INFO: connection rejected (403 Forbidden)
INFO: connection closed
INFO: 192.168.1.125:53913 - "GET /loginMsg.js HTTP/1.1" 404 Not Found
INFO: 192.168.1.125:53914 - "GET /cgi/get.cgi?cmd=home_login HTTP/1.1" 404 Not Found
INFO: 192.168.1.125:53915 - "POST /boaform/admin/formTracert HTTP/1.1" 404 Not Found
when creating a stock the gtin has to exist inthe product table
FAILED tests\test_admin.py::TestAdminAPI::test_admin_endpoints_require_authentication - assert 403 == 401
FAILED tests\test_background_tasks.py::TestBackgroundTasks::test_marketplace_import_success - AssertionError: assert 'pending' == 'completed'
FAILED tests\test_background_tasks.py::TestBackgroundTasks::test_marketplace_import_failure - AssertionError: assert 'pending' == 'failed'
FAILED tests\test_error_handling.py::TestErrorHandling::test_invalid_authentication - assert 401 == 403
FAILED tests\test_error_handling.py::TestErrorHandling::test_duplicate_resource_creation - assert 500 == 400
FAILED tests\test_marketplace.py::TestMarketplaceAPI::test_import_from_marketplace - sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 1 - probably unsupported type.
FAILED tests\test_product.py::TestProductsAPI::test_get_products_empty - assert 404 == 200
FAILED tests\test_product.py::TestProductsAPI::test_create_product_duplicate_id - assert 500 == 400
FAILED tests\test_security.py::TestSecurity::test_protected_endpoint_with_invalid_token - assert 401 == 403
FAILED tests\test_security.py::TestSecurity::test_input_validation - assert '<script>' not in "<script>ale...s')</script>"

View File

@@ -16,9 +16,9 @@ from sqlalchemy.orm import Session
from app.api.deps import get_current_admin_user
from app.core.database import get_db
from app.services.admin_service import admin_service
from models.api.auth import UserResponse
from models.api.marketplace import MarketplaceImportJobResponse
from models.api.shop import ShopListResponse
from models.schemas.auth import UserResponse
from models.schemas.marketplace import MarketplaceImportJobResponse
from models.schemas.shop import ShopListResponse
from models.database.user import User
router = APIRouter()

View File

@@ -15,8 +15,8 @@ from sqlalchemy.orm import Session
from app.api.deps import get_current_user
from app.core.database import get_db
from app.services.auth_service import auth_service
from models.api.auth import (LoginResponse, UserLogin, UserRegister,
UserResponse)
from models.schemas.auth import (LoginResponse, UserLogin, UserRegister,
UserResponse)
from models.database.user import User
router = APIRouter()

View File

@@ -18,8 +18,8 @@ from app.core.database import get_db
from app.services.marketplace_service import marketplace_service
from app.tasks.background_tasks import process_marketplace_import
from middleware.decorators import rate_limit
from models.api.marketplace import (MarketplaceImportJobResponse,
MarketplaceImportRequest)
from models.schemas.marketplace import (MarketplaceImportJobResponse,
MarketplaceImportRequest)
from models.database.user import User
router = APIRouter()

View File

@@ -17,9 +17,9 @@ from sqlalchemy.orm import Session
from app.api.deps import get_current_user
from app.core.database import get_db
from app.services.product_service import product_service
from models.api.product import (ProductCreate, ProductDetailResponse,
ProductListResponse, ProductResponse,
ProductUpdate)
from models.schemas.product import (ProductCreate, ProductDetailResponse,
ProductListResponse, ProductResponse,
ProductUpdate)
from models.database.user import User
router = APIRouter()

View File

@@ -15,8 +15,8 @@ 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.api.shop import (ShopCreate, ShopListResponse, ShopProductCreate,
ShopProductResponse, ShopResponse)
from models.schemas.shop import (ShopCreate, ShopListResponse, ShopProductCreate,
ShopProductResponse, ShopResponse)
from models.database.user import User
router = APIRouter()

View File

@@ -16,7 +16,7 @@ from sqlalchemy.orm import Session
from app.api.deps import get_current_user
from app.core.database import get_db
from app.services.stats_service import stats_service
from models.api.stats import MarketplaceStatsResponse, StatsResponse
from models.schemas.stats import MarketplaceStatsResponse, StatsResponse
from models.database.user import User
router = APIRouter()

View File

@@ -16,8 +16,8 @@ from sqlalchemy.orm import Session
from app.api.deps import get_current_user
from app.core.database import get_db
from app.services.stock_service import stock_service
from models.api.stock import (StockAdd, StockCreate, StockResponse,
StockSummaryResponse, StockUpdate)
from models.schemas.stock import (StockAdd, StockCreate, StockResponse,
StockSummaryResponse, StockUpdate)
from models.database.user import User
router = APIRouter()

View File

@@ -18,42 +18,21 @@ class Settings(BaseSettings):
# Project information
project_name: str = "Ecommerce Backend API with Marketplace Support"
# Documentation
documentation_url: str = "http://localhost:8001" # Development default
# Clean description without HTML
description: str = """
## 🚀 Letzshop Import API
Complete marketplace product import and management system built with FastAPI.
### 📚 Documentation Links
- **[Complete Documentation Site](#)** - Full project documentation
- **[Getting Started Guide](#)** - Installation and setup
- **[User Guides](#)** - How-to guides and tutorials
- **[API Authentication Guide](#)** - Security and authentication
- **[Testing Documentation](#)** - Test suite and conventions
### 🔗 Quick Links
- **[Alternative API Docs](/redoc)** - ReDoc interface
- **[Health Check](/health)** - System status
- **[OpenAPI Spec](/openapi.json)** - Machine-readable API spec
### 📖 Key Features
- **Product Management** - Complete CRUD operations with validation
- **Multi-Shop Support** - Independent shop configurations
- **CSV Import System** - Bulk import from various marketplace formats
- **Stock Management** - Inventory tracking across locations
- **User Management** - Role-based access control
- **Marketplace Integration** - Import from multiple platforms
### 🏗️ Architecture
Built with modern Python stack:
- **FastAPI** - High-performance async API framework
- **SQLAlchemy** - Powerful ORM with PostgreSQL
- **Pydantic** - Data validation and serialization
- **JWT Authentication** - Secure token-based auth
- **pytest** - Comprehensive test suite
Marketplace product import and management system with multi-shop support.
**Features:**
- JWT Authentication with role-based access
- Multi-marketplace product import (CSV processing)
- Inventory management across multiple locations
- Shop management with individual configurations
**Documentation:** Visit /documentation for complete guides
**API Testing:** Use /docs for interactive API exploration
"""
version: str = "2.2.0"

View File

@@ -14,7 +14,7 @@ from typing import List, Optional, Tuple
from fastapi import HTTPException
from sqlalchemy.orm import Session
from models.api.marketplace import MarketplaceImportJobResponse
from models.schemas.marketplace import MarketplaceImportJobResponse
from models.database.marketplace import MarketplaceImportJob
from models.database.shop import Shop
from models.database.user import User

View File

@@ -14,7 +14,7 @@ from fastapi import HTTPException
from sqlalchemy.orm import Session
from middleware.auth import AuthManager
from models.api.auth import UserLogin, UserRegister
from models.schemas.auth import UserLogin, UserRegister
from models.database.user import User
logger = logging.getLogger(__name__)

View File

@@ -14,8 +14,8 @@ from typing import List, Optional
from sqlalchemy import func
from sqlalchemy.orm import Session
from models.api.marketplace import (MarketplaceImportJobResponse,
MarketplaceImportRequest)
from models.schemas.marketplace import (MarketplaceImportJobResponse,
MarketplaceImportRequest)
from models.database.marketplace import MarketplaceImportJob
from models.database.shop import Shop
from models.database.user import User

View File

@@ -14,8 +14,8 @@ from typing import Generator, List, Optional
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
from models.api.product import ProductCreate, ProductUpdate
from models.api.stock import StockLocationResponse, StockSummaryResponse
from models.schemas.product import ProductCreate, ProductUpdate
from models.schemas.stock import StockLocationResponse, StockSummaryResponse
from models.database.product import Product
from models.database.stock import Stock
from utils.data_processing import GTINProcessor, PriceProcessor

View File

@@ -14,7 +14,7 @@ from fastapi import HTTPException
from sqlalchemy import func
from sqlalchemy.orm import Session
from models.api.shop import ShopCreate, ShopProductCreate
from models.schemas.shop import ShopCreate, ShopProductCreate
from models.database.product import Product
from models.database.shop import Shop, ShopProduct
from models.database.user import User

View File

@@ -13,8 +13,8 @@ from typing import List, Optional
from sqlalchemy.orm import Session
from models.api.stock import (StockAdd, StockCreate, StockLocationResponse,
StockSummaryResponse, StockUpdate)
from models.schemas.stock import (StockAdd, StockCreate, StockLocationResponse,
StockSummaryResponse, StockUpdate)
from models.database.product import Product
from models.database.stock import Stock
from utils.data_processing import GTINProcessor

92
main.py
View File

@@ -57,7 +57,7 @@ def health_check(db: Session = Depends(get_db)):
"swagger": "/docs",
"redoc": "/redoc",
"openapi": "/openapi.json",
"complete": "Documentation site URL here",
"complete": "/documentation",
},
"features": [
"JWT Authentication",
@@ -79,89 +79,13 @@ def health_check(db: Session = Depends(get_db)):
# Documentation redirect endpoints
@app.get("/documentation", response_class=HTMLResponse, include_in_schema=False)
async def documentation_page():
"""Enhanced documentation hub page"""
return """
<!DOCTYPE html>
<html>
<head>
<title>Letzshop Import - Documentation</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 800px;
margin: 40px auto;
padding: 20px;
line-height: 1.6;
}
.header { text-align: center; margin-bottom: 40px; }
.logo { font-size: 2em; margin-bottom: 10px; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 30px 0; }
.card {
border: 1px solid #e1e5e9;
border-radius: 8px;
padding: 20px;
transition: box-shadow 0.2s;
text-decoration: none;
color: inherit;
}
.card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
.card h3 { margin-top: 0; color: #1976d2; }
.badge {
display: inline-block;
background: #1976d2;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.8em;
margin-left: 10px;
}
</style>
</head>
<body>
<div class="header">
<div class="logo">📚 Letzshop Import Documentation</div>
<p>Choose your documentation experience</p>
</div>
<div class="cards">
<a href="/docs" class="card">
<h3>🔧 Interactive API Docs <span class="badge">LIVE</span></h3>
<p>Swagger UI interface for testing API endpoints directly in your browser. Perfect for development and API exploration.</p>
</a>
<a href="/redoc" class="card">
<h3>📖 API Reference</h3>
<p>Clean, readable API documentation with ReDoc. Great for understanding API structure and parameters.</p>
</a>
<a href="#" class="card">
<h3>📚 Complete Documentation</h3>
<p>Comprehensive project documentation with guides, tutorials, architecture, and development info.</p>
</a>
<a href="#" class="card">
<h3>🚀 Getting Started</h3>
<p>Step-by-step installation and setup guide to get you up and running quickly.</p>
</a>
<a href="#" class="card">
<h3>🧪 Testing Guide</h3>
<p>Testing conventions, how to run tests, and contribute to the test suite.</p>
</a>
<a href="/health" class="card">
<h3>💚 System Health</h3>
<p>Check the current status and health of the API and its dependencies.</p>
</a>
</div>
<div style="text-align: center; margin-top: 40px; color: #666;">
<p>Need help? Check our <a href="https://github.com/yourusername/letzshop-import/issues">GitHub Issues</a></p>
</div>
</body>
</html>
"""
async def documentation():
"""Redirect to MkDocs documentation"""
# Development
if settings.debug:
return RedirectResponse(url="http://localhost:8001")
# Production
return RedirectResponse(url=settings.documentation_url)
if __name__ == "__main__":

View File

@@ -10,7 +10,7 @@ from .database.shop import Shop, ShopProduct
from .database.marketplace import MarketplaceImportJob
# API models (Pydantic) - import the modules, not all classes
from . import api
from . import schemas
# Export database models for Alembic
__all__ = [

View File

@@ -4,7 +4,7 @@ from typing import List, Optional
from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
from models.api.stock import StockSummaryResponse
from models.schemas.stock import StockSummaryResponse
class ProductBase(BaseModel):

View File

@@ -4,7 +4,7 @@ from typing import List, Optional
from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
from models.api.product import ProductResponse
from models.schemas.product import ProductResponse
class ShopCreate(BaseModel):

View File

@@ -144,7 +144,7 @@ def verify_model_structure():
# Test API models
try:
import models.api
import models.schemas
print("[OK] API models package imported")
# Test specific API model imports

View File

@@ -3,7 +3,7 @@ import pytest
from fastapi import HTTPException
from app.services.auth_service import AuthService
from models.api.auth import UserLogin, UserRegister
from models.schemas.auth import UserLogin, UserRegister
from models.database.user import User

View File

@@ -5,7 +5,7 @@ from datetime import datetime
import pytest
from app.services.marketplace_service import MarketplaceService
from models.api.marketplace import MarketplaceImportRequest
from models.schemas.marketplace import MarketplaceImportRequest
from models.database.marketplace import MarketplaceImportJob
from models.database.shop import Shop
from models.database.user import User

View File

@@ -2,7 +2,7 @@
import pytest
from app.services.product_service import ProductService
from models.api.product import ProductCreate
from models.schemas.product import ProductCreate
from models.database.product import Product

View File

@@ -3,7 +3,7 @@ import pytest
from fastapi import HTTPException
from app.services.shop_service import ShopService
from models.api.shop import ShopCreate, ShopProductCreate
from models.schemas.shop import ShopCreate, ShopProductCreate
@pytest.mark.unit

View File

@@ -4,7 +4,7 @@ import uuid
import pytest
from app.services.stock_service import StockService
from models.api.stock import StockAdd, StockCreate, StockUpdate
from models.schemas.stock import StockAdd, StockCreate, StockUpdate
from models.database.product import Product
from models.database.stock import Stock