Refactoring code for modular approach

This commit is contained in:
2025-09-10 20:48:55 +02:00
parent 1fc8810242
commit fca389cff4
5 changed files with 40 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.orm import sessionmaker, Session
from .config import settings from .config import settings

View File

@@ -1,5 +1,5 @@
# models/api_models.py - Updated with Marketplace Support # models/api_models.py - Updated with Marketplace Support and Pydantic v2
from pydantic import BaseModel, Field, field_validator, EmailStr from pydantic import BaseModel, Field, field_validator, EmailStr, ConfigDict
from typing import Optional, List from typing import Optional, List
from datetime import datetime from datetime import datetime
@@ -36,6 +36,8 @@ class UserLogin(BaseModel):
class UserResponse(BaseModel): class UserResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int id: int
email: str email: str
username: str username: str
@@ -45,8 +47,6 @@ class UserResponse(BaseModel):
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
model_config = {"from_attributes": True}
class LoginResponse(BaseModel): class LoginResponse(BaseModel):
access_token: str access_token: str
@@ -98,6 +98,8 @@ class ShopUpdate(BaseModel):
class ShopResponse(BaseModel): class ShopResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int id: int
shop_code: str shop_code: str
shop_name: str shop_name: str
@@ -113,9 +115,6 @@ class ShopResponse(BaseModel):
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
class Config:
from_attributes = True
class ShopListResponse(BaseModel): class ShopListResponse(BaseModel):
shops: List[ShopResponse] shops: List[ShopResponse]
@@ -185,12 +184,12 @@ class ProductUpdate(ProductBase):
class ProductResponse(ProductBase): class ProductResponse(ProductBase):
model_config = ConfigDict(from_attributes=True)
id: int id: int
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
model_config = {"from_attributes": True}
# NEW: Shop Product models # NEW: Shop Product models
class ShopProductCreate(BaseModel): class ShopProductCreate(BaseModel):
@@ -207,6 +206,8 @@ class ShopProductCreate(BaseModel):
class ShopProductResponse(BaseModel): class ShopProductResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int id: int
shop_id: int shop_id: int
product: ProductResponse product: ProductResponse
@@ -223,9 +224,6 @@ class ShopProductResponse(BaseModel):
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
class Config:
from_attributes = True
# Stock Models # Stock Models
class StockBase(BaseModel): class StockBase(BaseModel):
@@ -246,6 +244,8 @@ class StockUpdate(BaseModel):
class StockResponse(BaseModel): class StockResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int id: int
gtin: str gtin: str
location: str location: str
@@ -253,8 +253,6 @@ class StockResponse(BaseModel):
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
model_config = {"from_attributes": True}
class StockLocationResponse(BaseModel): class StockLocationResponse(BaseModel):
location: str location: str

View File

@@ -1,10 +1,10 @@
# models/database_models.py - Updated with Marketplace Support # models/database_models.py - Updated with Marketplace Support
from sqlalchemy import Column, Integer, String, Float, DateTime, Boolean, Text, ForeignKey, UniqueConstraint, Index from sqlalchemy import Column, Integer, String, Float, DateTime, Boolean, Text, ForeignKey, UniqueConstraint, Index
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from datetime import datetime from datetime import datetime
Base = declarative_base() # Import Base from the central database module instead of creating a new one
from app.core.database import Base
class User(Base): class User(Base):

View File

@@ -9,7 +9,8 @@ from sqlalchemy.pool import StaticPool
from main import app from main import app
from app.core.database import get_db, Base from app.core.database import get_db, Base
from models.database_models import User, Product, Stock, Shop # Import all models to ensure they're registered with Base metadata
from models.database_models import User, Product, Stock, Shop, MarketplaceImportJob, ShopProduct
from middleware.auth import AuthManager from middleware.auth import AuthManager
# Use in-memory SQLite database for tests # Use in-memory SQLite database for tests
@@ -35,38 +36,41 @@ def testing_session_local(engine):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def db(engine, testing_session_local): def db(engine, testing_session_local):
"""Create a fresh database for each test""" """Create a database session for direct database operations"""
# Create all tables # Create all tables
Base.metadata.create_all(bind=engine) Base.metadata.create_all(bind=engine)
# Create session # Create session
db = testing_session_local() db_session = testing_session_local()
# Override the dependency try:
yield db_session
finally:
db_session.rollback()
db_session.close()
# Tables will be dropped by the client fixture
@pytest.fixture(scope="function")
def client(db): # Now client depends on db
"""Create a test client with database dependency override"""
# Override the dependency to use our test database
def override_get_db(): def override_get_db():
try: try:
yield db yield db
finally: finally:
pass # Don't close here, we'll close in cleanup pass # Don't close here, the db fixture handles it
app.dependency_overrides[get_db] = override_get_db app.dependency_overrides[get_db] = override_get_db
try: try:
yield db client = TestClient(app)
yield client
finally: finally:
db.rollback() # Rollback any uncommitted changes
db.close()
# Clean up the dependency override # Clean up the dependency override
if get_db in app.dependency_overrides: if get_db in app.dependency_overrides:
del app.dependency_overrides[get_db] del app.dependency_overrides[get_db]
# Drop all tables for next test
Base.metadata.drop_all(bind=engine)
@pytest.fixture(scope="function")
def client(db):
"""Create a test client with database dependency override"""
return TestClient(app)
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
@@ -174,10 +178,11 @@ def test_shop(db, test_user):
def test_stock(db, test_product, test_shop): def test_stock(db, test_product, test_shop):
"""Create test stock entry""" """Create test stock entry"""
stock = Stock( stock = Stock(
product_id=test_product.product_id, gtin=test_product.gtin, # Fixed: use gtin instead of product_id
shop_code=test_shop.shop_code, location=test_shop.shop_code, # Fixed: use location instead of shop_code
quantity=10, quantity=10,
reserved_quantity=0 reserved_quantity=0,
shop_id=test_shop.id # Add shop_id reference
) )
db.add(stock) db.add(stock)
db.commit() db.commit()

View File

@@ -66,7 +66,7 @@ class TestAuthenticationAPI:
assert response.status_code == 401 assert response.status_code == 401
assert "Incorrect username or password" in response.json()["detail"] assert "Incorrect username or password" in response.json()["detail"]
def test_login_nonexistent_user(self, client): def test_login_nonexistent_user(self, client, db): # Added db fixture
"""Test login with nonexistent user""" """Test login with nonexistent user"""
response = client.post("/api/v1/auth/login", json={ response = client.post("/api/v1/auth/login", json={
"username": "nonexistent", "username": "nonexistent",
@@ -116,4 +116,3 @@ class TestAuthManager:
assert token_data["token_type"] == "bearer" assert token_data["token_type"] == "bearer"
assert "expires_in" in token_data assert "expires_in" in token_data
assert isinstance(token_data["expires_in"], int) assert isinstance(token_data["expires_in"], int)