refactor: migrate models to canonical module locations

- Move Product/ProductTranslation to app/modules/catalog/models/
- Move VendorOnboarding to app/modules/marketplace/models/
- Delete legacy re-export files for marketplace models:
  - letzshop.py, marketplace.py, marketplace_product.py
  - marketplace_product_translation.py, marketplace_import_job.py
- Delete legacy product.py, product_translation.py, onboarding.py
- Update all imports across services, tasks, tests to use module locations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 14:45:32 +01:00
parent a123341aa8
commit 0c63f387aa
72 changed files with 176 additions and 276 deletions

View File

@@ -108,14 +108,14 @@ except ImportError as e:
# PRODUCT MODELS
# ----------------------------------------------------------------------------
try:
from models.database.product import Product
from app.modules.catalog.models import Product
print(" ✓ Product model imported")
except ImportError as e:
print(f" ✗ Product model failed: {e}")
try:
from models.database.marketplace_product import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProduct
print(" ✓ MarketplaceProduct model imported")
except ImportError as e:
@@ -135,7 +135,7 @@ except ImportError as e:
# MARKETPLACE IMPORT
# ----------------------------------------------------------------------------
try:
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
print(" ✓ MarketplaceImportJob model imported")
except ImportError as e:

View File

@@ -21,7 +21,7 @@ from sqlalchemy.orm import Session
from app.core.database import get_db
from app.services.letzshop.vendor_sync_service import LetzshopVendorSyncService
from app.services.platform_signup_service import platform_signup_service
from models.database.letzshop import LetzshopVendorCache
from app.modules.marketplace.models import LetzshopVendorCache
router = APIRouter()
logger = logging.getLogger(__name__)

View File

@@ -21,10 +21,9 @@ from sqlalchemy.orm import Session
from app.exceptions import AdminOperationException, VendorNotFoundException
from app.modules.customers.models.customer import Customer
from app.modules.inventory.models import Inventory
from models.database.marketplace_import_job import MarketplaceImportJob
from models.database.marketplace_product import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceImportJob, MarketplaceProduct
from app.modules.orders.models import Order
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.user import User
from models.database.vendor import Vendor

View File

@@ -16,7 +16,7 @@ from dataclasses import dataclass
from sqlalchemy import func
from sqlalchemy.orm import Session
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.subscription import SubscriptionTier, VendorSubscription
from models.database.vendor import VendorUser

View File

@@ -27,7 +27,7 @@ from app.modules.billing.models import (
SubscriptionTier,
VendorSubscription,
)
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor, VendorUser
logger = logging.getLogger(__name__)

View File

@@ -45,7 +45,7 @@ from app.modules.billing.schemas import (
TierLimits,
UsageSummary,
)
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor, VendorUser
logger = logging.getLogger(__name__)

View File

@@ -24,7 +24,7 @@ from app.exceptions import (
)
from app.utils.money import cents_to_euros
from app.modules.cart.models.cart import CartItem
from models.database.product import Product
from app.modules.catalog.models import Product
logger = logging.getLogger(__name__)

View File

@@ -2,6 +2,16 @@
"""
Catalog module models.
Note: The catalog module uses the Product model from the products module.
This file exists for consistency with the module structure.
This is the canonical location for product models.
Usage:
from app.modules.catalog.models import Product, ProductTranslation
"""
from app.modules.catalog.models.product import Product
from app.modules.catalog.models.product_translation import ProductTranslation
__all__ = [
"Product",
"ProductTranslation",
]

View File

@@ -1,3 +1,4 @@
# app/modules/catalog/models/product.py
"""Vendor Product model - independent copy pattern.
This model represents a vendor's product. Products can be:
@@ -7,7 +8,7 @@ This model represents a vendor's product. Products can be:
When created from marketplace, the marketplace_product_id FK provides
"view original source" comparison feature.
Money values are stored as integer cents (e.g., 105.91 = 10591).
Money values are stored as integer cents (e.g., 105.91 = 10591).
See docs/architecture/money-handling.md for details.
"""
@@ -34,7 +35,7 @@ class Product(Base, TimestampMixin):
Products can be created from marketplace imports or directly by vendors.
When from marketplace, marketplace_product_id provides source comparison.
Price fields use integer cents for precision (19.99 = 1999 cents).
Price fields use integer cents for precision (19.99 = 1999 cents).
"""
__tablename__ = "products"
@@ -55,7 +56,7 @@ class Product(Base, TimestampMixin):
gtin_type = Column(String(20)) # Format: gtin13, gtin14, gtin12, gtin8, isbn13, isbn10
# === PRODUCT FIELDS (copied from marketplace at creation) ===
# Pricing - stored as integer cents (19.99 = 1999)
# Pricing - stored as integer cents (19.99 = 1999)
price_cents = Column(Integer) # Price in cents
sale_price_cents = Column(Integer) # Sale price in cents
currency = Column(String(3), default="EUR")
@@ -188,7 +189,7 @@ class Product(Base, TimestampMixin):
"""Calculate net price (excluding VAT) from gross price.
Formula: Net = Gross / (1 + rate/100)
Example: 119 gross at 17% VAT = 119 / 1.17 = 101.71 net
Example: 119 gross at 17% VAT = 119 / 1.17 = 101.71 net
"""
if self.price_cents is None:
return None
@@ -244,7 +245,7 @@ class Product(Base, TimestampMixin):
"""Calculate profit margin as percentage of net revenue.
Formula: Margin% = (Profit / Net) * 100
Example: 41.71 profit on 101.71 net = 41.0% margin
Example: 41.71 profit on 101.71 net = 41.0% margin
"""
net = self.net_price_cents
profit = self.profit_cents

View File

@@ -1,3 +1,4 @@
# app/modules/catalog/models/product_translation.py
"""Product Translation model for vendor-specific localized content.
This model stores vendor-specific translations. Translations are independent

View File

@@ -18,8 +18,7 @@ from sqlalchemy import or_
from sqlalchemy.orm import Session, joinedload
from app.exceptions import ProductNotFoundException, ValidationException
from models.database.product import Product
from models.database.product_translation import ProductTranslation
from app.modules.catalog.models import Product, ProductTranslation
logger = logging.getLogger(__name__)

View File

@@ -24,7 +24,7 @@ from dataclasses import dataclass, field
from sqlalchemy.orm import Session
from app.modules.inventory.models.inventory import Inventory
from models.database.product import Product
from app.modules.catalog.models import Product
logger = logging.getLogger(__name__)

View File

@@ -30,7 +30,7 @@ from app.modules.inventory.schemas.inventory import (
InventoryUpdate,
ProductInventorySummary,
)
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor
logger = logging.getLogger(__name__)
@@ -603,8 +603,8 @@ class InventoryService:
query = query.filter(Inventory.quantity <= low_stock)
if search:
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)

View File

@@ -15,7 +15,7 @@ from app.exceptions import OrderNotFoundException, ProductNotFoundException
from app.modules.inventory.models.inventory import Inventory
from app.modules.inventory.models.inventory_transaction import InventoryTransaction
from app.modules.orders.models import Order
from models.database.product import Product
from app.modules.catalog.models import Product
logger = logging.getLogger(__name__)

View File

@@ -35,6 +35,12 @@ from app.modules.marketplace.models.letzshop import (
# Import jobs
LetzshopHistoricalImportJob,
)
from app.modules.marketplace.models.onboarding import (
OnboardingStatus,
OnboardingStep,
STEP_ORDER,
VendorOnboarding,
)
__all__ = [
# Marketplace products
@@ -51,4 +57,9 @@ __all__ = [
"LetzshopFulfillmentQueue",
"LetzshopVendorCache",
"LetzshopSyncLog",
# Onboarding
"OnboardingStatus",
"OnboardingStep",
"STEP_ORDER",
"VendorOnboarding",
]

View File

@@ -1,9 +1,15 @@
# models/database/onboarding.py
# app/modules/marketplace/models/onboarding.py
"""
Vendor onboarding progress tracking.
Tracks completion status of mandatory onboarding steps for new vendors.
Onboarding must be completed before accessing the vendor dashboard.
The onboarding flow guides vendors through Letzshop marketplace integration:
1. Company Profile setup
2. Letzshop API configuration
3. Product import from CSV feed
4. Historical order sync
"""
import enum
@@ -23,8 +29,7 @@ from sqlalchemy.dialects.sqlite import JSON
from sqlalchemy.orm import relationship
from app.core.database import Base
from .base import TimestampMixin
from models.database.base import TimestampMixin
class OnboardingStep(str, enum.Enum):

View File

@@ -11,7 +11,7 @@ from datetime import UTC, datetime
from sqlalchemy.orm import Session
from app.utils.encryption import decrypt_value, encrypt_value, mask_api_key
from models.database.letzshop import VendorLetzshopCredentials
from app.modules.marketplace.models import VendorLetzshopCredentials
from .client_service import LetzshopClient

View File

@@ -16,15 +16,15 @@ from sqlalchemy.orm import Session
from app.services.order_service import order_service as unified_order_service
from app.services.subscription_service import subscription_service
from models.database.letzshop import (
from app.modules.marketplace.models import (
LetzshopFulfillmentQueue,
LetzshopHistoricalImportJob,
LetzshopSyncLog,
MarketplaceImportJob,
VendorLetzshopCredentials,
)
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.orders.models import Order, OrderItem
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor
logger = logging.getLogger(__name__)

View File

@@ -15,7 +15,7 @@ from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.orm import Session
from app.services.letzshop.client_service import LetzshopClient
from models.database.letzshop import LetzshopVendorCache
from app.modules.marketplace.models import LetzshopVendorCache
logger = logging.getLogger(__name__)

View File

@@ -12,9 +12,8 @@ from datetime import UTC, datetime
from sqlalchemy.orm import Session, joinedload
from models.database.letzshop import LetzshopSyncLog
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from app.modules.marketplace.models import LetzshopSyncLog, MarketplaceProduct
from app.modules.catalog.models import Product
logger = logging.getLogger(__name__)

View File

@@ -8,7 +8,7 @@ from app.exceptions import (
ImportJobNotOwnedException,
ValidationException,
)
from models.database.marketplace_import_job import (
from app.modules.marketplace.models import (
MarketplaceImportError,
MarketplaceImportJob,
)

View File

@@ -31,8 +31,8 @@ from app.exceptions import (
)
from app.utils.data_processing import GTINProcessor, PriceProcessor
from app.modules.inventory.models import Inventory
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)
from app.modules.inventory.schemas import InventoryLocationResponse, InventorySummaryResponse
@@ -859,8 +859,8 @@ class MarketplaceProductService:
Returns:
Dict with copied, skipped, failed counts and details
"""
from models.database.product import Product
from models.database.product_translation import ProductTranslation
from app.modules.catalog.models import Product
from app.modules.catalog.models import ProductTranslation
from models.database.vendor import Vendor
vendor = db.query(Vendor).filter(Vendor.id == vendor_id).first()

View File

@@ -13,8 +13,7 @@ from datetime import UTC, datetime
from typing import Callable
from app.core.celery_config import celery_app
from models.database.marketplace_import_job import MarketplaceImportJob
from models.database.letzshop import LetzshopHistoricalImportJob
from app.modules.marketplace.models import MarketplaceImportJob, LetzshopHistoricalImportJob
from app.services.admin_notification_service import admin_notification_service
from app.services.letzshop import LetzshopClientError
from app.services.letzshop.credentials_service import LetzshopCredentialsService

View File

@@ -10,7 +10,7 @@ from sqlalchemy import case, desc, func
from sqlalchemy.orm import Session
from models.database.architecture_scan import ArchitectureScan
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
from models.database.test_run import TestRun

View File

@@ -23,7 +23,7 @@ from app.exceptions import (
)
from app.modules.orders.models.order import Order, OrderItem
from app.modules.orders.models.order_item_exception import OrderItemException
from models.database.product import Product
from app.modules.catalog.models import Product
logger = logging.getLogger(__name__)

View File

@@ -49,9 +49,8 @@ from app.utils.vat import (
calculate_vat_amount,
determine_vat_regime,
)
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import MarketplaceProductTranslation
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct, MarketplaceProductTranslation
from app.modules.catalog.models import Product
from models.database.vendor import Vendor
# Placeholder product constants

View File

@@ -33,7 +33,7 @@ from app.exceptions import (
from app.exceptions.auth import UserAlreadyExistsException
from middleware.auth import AuthManager
from models.database.company import Company
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
from models.database.platform import Platform
from models.database.user import User
from models.database.vendor import Role, Vendor

View File

@@ -16,7 +16,7 @@ from decimal import Decimal
from sqlalchemy import func
from sqlalchemy.orm import Session
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.subscription import (
CapacitySnapshot,
SubscriptionStatus,

View File

@@ -11,7 +11,7 @@ from datetime import UTC, datetime
from sqlalchemy.orm import Session
from app.utils.encryption import decrypt_value, encrypt_value, mask_api_key
from models.database.letzshop import VendorLetzshopCredentials
from app.modules.marketplace.models import VendorLetzshopCredentials
from .client_service import LetzshopClient

View File

@@ -16,15 +16,15 @@ from sqlalchemy.orm import Session
from app.services.order_service import order_service as unified_order_service
from app.services.subscription_service import subscription_service
from models.database.letzshop import (
from app.modules.marketplace.models import (
LetzshopFulfillmentQueue,
LetzshopHistoricalImportJob,
LetzshopSyncLog,
MarketplaceImportJob,
VendorLetzshopCredentials,
)
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.orders.models import Order, OrderItem
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor
logger = logging.getLogger(__name__)

View File

@@ -15,7 +15,7 @@ from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.orm import Session
from app.services.letzshop.client_service import LetzshopClient
from models.database.letzshop import LetzshopVendorCache
from app.modules.marketplace.models import LetzshopVendorCache
logger = logging.getLogger(__name__)

View File

@@ -24,7 +24,7 @@ from app.exceptions import (
)
from app.services.letzshop.credentials_service import LetzshopCredentialsService
from app.services.letzshop.order_service import LetzshopOrderService
from models.database.onboarding import (
from app.modules.marketplace.models import (
OnboardingStatus,
OnboardingStep,
VendorOnboarding,

View File

@@ -19,7 +19,7 @@ from sqlalchemy.orm import Session
from app.services.image_service import image_service
from app.modules.inventory.models import Inventory
from app.modules.orders.models import Order
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor
logger = logging.getLogger(__name__)

View File

@@ -18,8 +18,8 @@ from app.exceptions import (
ProductNotFoundException,
ValidationException,
)
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.catalog.models import Product
from models.schema.product import ProductCreate, ProductUpdate
logger = logging.getLogger(__name__)
@@ -272,7 +272,7 @@ class ProductService:
from sqlalchemy import or_
from sqlalchemy.orm import joinedload
from models.database.product_translation import ProductTranslation
from app.modules.catalog.models import ProductTranslation
try:
# Prepare search pattern for LIKE queries

View File

@@ -15,7 +15,7 @@ from sqlalchemy import func
from sqlalchemy.orm import Session, joinedload
from app.exceptions import ProductNotFoundException
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor
logger = logging.getLogger(__name__)
@@ -270,7 +270,7 @@ class VendorProductService:
Returns:
Created Product instance
"""
from models.database.product_translation import ProductTranslation
from app.modules.catalog.models import ProductTranslation
# Determine product_type from is_digital flag
is_digital = data.get("is_digital", False)
@@ -344,7 +344,7 @@ class VendorProductService:
Returns:
Updated Product instance
"""
from models.database.product_translation import ProductTranslation
from app.modules.catalog.models import ProductTranslation
product = (
db.query(Product)

View File

@@ -23,8 +23,8 @@ from app.exceptions import (
VendorAlreadyExistsException,
VendorNotFoundException,
)
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.catalog.models import Product
from models.database.user import User
from models.database.vendor import Vendor
from models.schema.product import ProductCreate

View File

@@ -7,7 +7,7 @@ from datetime import UTC, datetime
from app.core.database import SessionLocal
from app.services.admin_notification_service import admin_notification_service
from app.utils.csv_processor import CSVProcessor
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
from models.database.vendor import Vendor
logger = logging.getLogger(__name__)

View File

@@ -11,7 +11,7 @@ from app.services.letzshop import LetzshopClientError
from app.services.letzshop.credentials_service import LetzshopCredentialsService
from app.services.letzshop.order_service import LetzshopOrderService
from app.services.letzshop.vendor_sync_service import LetzshopVendorSyncService
from models.database.letzshop import LetzshopHistoricalImportJob
from app.modules.marketplace.models import LetzshopHistoricalImportJob
logger = logging.getLogger(__name__)

View File

@@ -19,9 +19,9 @@ from sqlalchemy import literal
from sqlalchemy.orm import Session
from app.utils.money import euros_to_cents
from models.database.marketplace_import_job import MarketplaceImportError
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceImportError,
MarketplaceProduct,
MarketplaceProductTranslation,
)

View File

@@ -6,14 +6,13 @@ from . import schema
# Database models (SQLAlchemy)
from .database.base import Base
from .database.marketplace_import_job import MarketplaceImportJob
from .database.marketplace_product import MarketplaceProduct
from .database.product import Product
from .database.user import User
from .database.vendor import Vendor
# Module-based models
from app.modules.inventory.models import Inventory
from app.modules.marketplace.models import MarketplaceImportJob, MarketplaceProduct
from app.modules.catalog.models import Product
# Export database models for Alembic
__all__ = [

View File

@@ -57,13 +57,18 @@ from app.modules.orders.models import (
VATRegime,
VendorInvoiceSettings,
)
from .letzshop import (
from app.modules.marketplace.models import (
LetzshopFulfillmentQueue,
LetzshopHistoricalImportJob,
LetzshopSyncLog,
VendorLetzshopCredentials,
MarketplaceImportError,
MarketplaceImportJob,
DigitalDeliveryMethod,
MarketplaceProduct,
ProductType,
MarketplaceProductTranslation,
)
from .marketplace_import_job import MarketplaceImportError, MarketplaceImportJob
from app.modules.messaging.models import (
Conversation,
ConversationParticipant,
@@ -72,18 +77,11 @@ from app.modules.messaging.models import (
MessageAttachment,
ParticipantType,
)
from .marketplace_product import (
DigitalDeliveryMethod,
MarketplaceProduct,
ProductType,
)
from .media import MediaFile, ProductMedia
from .marketplace_product_translation import MarketplaceProductTranslation
from .onboarding import OnboardingStatus, OnboardingStep, VendorOnboarding
from app.modules.marketplace.models import OnboardingStatus, OnboardingStep, VendorOnboarding
from app.modules.orders.models import Order, OrderItem
from app.modules.orders.models import OrderItemException
from .product import Product
from .product_translation import ProductTranslation
from app.modules.catalog.models import Product, ProductTranslation
from .subscription import (
AddOnCategory,
AddOnProduct,

View File

@@ -1,34 +0,0 @@
# models/database/letzshop.py
"""
Legacy location for Letzshop models.
MIGRATED: Models have been moved to app.modules.marketplace.models.letzshop.
New location:
from app.modules.marketplace.models import (
VendorLetzshopCredentials,
LetzshopFulfillmentQueue,
LetzshopVendorCache,
LetzshopSyncLog,
LetzshopHistoricalImportJob,
)
This file re-exports from the new location for backward compatibility.
"""
# Re-export from the new canonical location
from app.modules.marketplace.models.letzshop import (
VendorLetzshopCredentials,
LetzshopFulfillmentQueue,
LetzshopVendorCache,
LetzshopSyncLog,
LetzshopHistoricalImportJob,
)
__all__ = [
"VendorLetzshopCredentials",
"LetzshopFulfillmentQueue",
"LetzshopVendorCache",
"LetzshopSyncLog",
"LetzshopHistoricalImportJob",
]

View File

@@ -1 +0,0 @@
# MarketplaceImportJob model

View File

@@ -1,22 +0,0 @@
# models/database/marketplace_import_job.py
"""
Legacy location for marketplace import job models.
MIGRATED: Models have been moved to app.modules.marketplace.models.marketplace_import_job.
New location:
from app.modules.marketplace.models import (
MarketplaceImportJob,
MarketplaceImportError,
)
This file re-exports from the new location for backward compatibility.
"""
# Re-export from the new canonical location
from app.modules.marketplace.models.marketplace_import_job import (
MarketplaceImportJob,
MarketplaceImportError,
)
__all__ = ["MarketplaceImportJob", "MarketplaceImportError"]

View File

@@ -1,28 +0,0 @@
# models/database/marketplace_product.py
"""
Legacy location for marketplace product model.
MIGRATED: All models have been moved to app.modules.marketplace.models.marketplace_product.
New location:
from app.modules.marketplace.models import (
MarketplaceProduct,
ProductType,
DigitalDeliveryMethod,
)
This file re-exports from the new location for backward compatibility.
"""
# Re-export everything from the new canonical location
from app.modules.marketplace.models.marketplace_product import (
MarketplaceProduct,
ProductType,
DigitalDeliveryMethod,
)
__all__ = [
"MarketplaceProduct",
"ProductType",
"DigitalDeliveryMethod",
]

View File

@@ -1,18 +0,0 @@
# models/database/marketplace_product_translation.py
"""
Legacy location for marketplace product translation model.
MIGRATED: Model has been moved to app.modules.marketplace.models.marketplace_product_translation.
New location:
from app.modules.marketplace.models import MarketplaceProductTranslation
This file re-exports from the new location for backward compatibility.
"""
# Re-export from the new canonical location
from app.modules.marketplace.models.marketplace_product_translation import (
MarketplaceProductTranslation,
)
__all__ = ["MarketplaceProductTranslation"]

View File

@@ -6,7 +6,7 @@ sys.path.insert(0, ".")
from app.core.database import SessionLocal
from app.services.letzshop.credentials_service import LetzshopCredentialsService
from models.database.letzshop import LetzshopHistoricalImportJob
from app.modules.marketplace.models import LetzshopHistoricalImportJob
def get_valid_shipment_states(vendor_id: int = 1):

View File

@@ -55,13 +55,13 @@ from app.modules.cms.models import ContentPage
from models.database.admin import PlatformAlert
from models.database.company import Company
from app.modules.customers.models.customer import Customer, CustomerAddress
from models.database.marketplace_import_job import MarketplaceImportJob
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceImportJob,
MarketplaceProduct,
MarketplaceProductTranslation,
)
from app.modules.orders.models import Order, OrderItem
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.user import User
from models.database.vendor import Role, Vendor, VendorUser
from models.database.vendor_domain import VendorDomain

View File

@@ -144,9 +144,8 @@ def verify_model_structure():
# Import specific models
from app.modules.inventory.models import Inventory
from models.database.marketplace_import_job import MarketplaceImportJob
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceImportJob, MarketplaceProduct
from app.modules.catalog.models import Product
from models.database.user import User
from models.database.vendor import Vendor

View File

@@ -8,7 +8,7 @@ See tests/conftest.py for details on fixture best practices.
import pytest
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
@pytest.fixture

View File

@@ -13,8 +13,8 @@ import uuid
import pytest
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)

View File

@@ -12,7 +12,7 @@ import pytest
from models.database.company import Company
from app.modules.inventory.models import Inventory
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.vendor import Vendor

View File

@@ -41,7 +41,7 @@ class TestAdminLetzshopVendorsAPI:
def test_list_vendors_configured_only(self, client, db, admin_headers, test_vendor):
"""Test listing only configured vendors."""
from app.utils.encryption import encrypt_value
from models.database.letzshop import VendorLetzshopCredentials
from app.modules.marketplace.models import VendorLetzshopCredentials
# Configure credentials for test vendor
credentials = VendorLetzshopCredentials(
@@ -384,11 +384,9 @@ class TestAdminLetzshopExportAPI:
self, client, db, admin_headers, test_vendor
):
"""Test exporting products with actual data."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
# Create marketplace product
mp = MarketplaceProduct(
@@ -438,11 +436,9 @@ class TestAdminLetzshopExportAPI:
self, client, db, admin_headers, test_vendor
):
"""Test exporting products in French."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
mp = MarketplaceProduct(
marketplace_product_id="EXPORT-FR-001",
@@ -484,11 +480,9 @@ class TestAdminLetzshopExportAPI:
self, client, db, admin_headers, test_vendor
):
"""Test exporting including inactive products."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
# Create inactive product
mp = MarketplaceProduct(

View File

@@ -67,8 +67,8 @@ class TestVendorDashboardAPI:
"""Test that dashboard stats only show data for the authenticated vendor"""
import uuid
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.catalog.models import Product
# Create products for the test vendor
for i in range(3):
@@ -195,8 +195,8 @@ class TestVendorDashboardAPI:
"""Test dashboard stats accuracy with actual products"""
import uuid
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.catalog.models import Product
# Create 5 different marketplace products
marketplace_products = []

View File

@@ -24,7 +24,7 @@ class TestVendorInventoryAPI:
):
"""Test setting inventory for a product."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -56,7 +56,7 @@ class TestVendorInventoryAPI:
db,
):
"""Test adjusting inventory quantity."""
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -123,7 +123,7 @@ class TestVendorInventoryAPI:
db,
):
"""Test getting inventory for a specific product."""
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -155,7 +155,7 @@ class TestVendorInventoryAPI:
db,
):
"""Test reserving inventory for an order."""
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -198,7 +198,7 @@ class TestVendorInventoryAPI:
db,
):
"""Test updating inventory record."""
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -240,7 +240,7 @@ class TestVendorInventoryAPI:
db,
):
"""Test deleting inventory record."""
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id

View File

@@ -642,11 +642,9 @@ class TestVendorLetzshopExportAPI:
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test exporting products with actual data."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
# Create marketplace product
mp = MarketplaceProduct(
@@ -695,11 +693,9 @@ class TestVendorLetzshopExportAPI:
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test exporting products in French."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
mp = MarketplaceProduct(
marketplace_product_id="VENDOR-FR-001",
@@ -741,11 +737,9 @@ class TestVendorLetzshopExportAPI:
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test exporting products in German."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
mp = MarketplaceProduct(
marketplace_product_id="VENDOR-DE-001",
@@ -785,11 +779,9 @@ class TestVendorLetzshopExportAPI:
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test exporting including inactive products."""
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
mp = MarketplaceProduct(
marketplace_product_id="VENDOR-INACTIVE-001",

View File

@@ -14,7 +14,7 @@ Tests cover:
import pytest
from models.database.onboarding import OnboardingStatus, OnboardingStep, VendorOnboarding
from app.modules.marketplace.models import OnboardingStatus, OnboardingStep, VendorOnboarding
@pytest.mark.integration

View File

@@ -50,7 +50,7 @@ class TestVendorProductsAPI:
):
"""Test adding product that already exists returns error."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -140,7 +140,7 @@ class TestVendorProductsAPI:
):
"""Test getting product details."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -174,7 +174,7 @@ class TestVendorProductsAPI:
):
"""Test updating product details."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -206,7 +206,7 @@ class TestVendorProductsAPI:
):
"""Test toggling product active status."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -232,7 +232,7 @@ class TestVendorProductsAPI:
):
"""Test toggling product featured status."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id
@@ -258,7 +258,7 @@ class TestVendorProductsAPI:
):
"""Test removing product from catalog."""
# Ensure test_product belongs to the vendor
from models.database.product import Product
from app.modules.catalog.models import Product
product = db.query(Product).filter(Product.id == test_product.id).first()
product.vendor_id = test_vendor_with_vendor_user.id

View File

@@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from app.tasks.background_tasks import process_marketplace_import
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
@pytest.mark.integration

View File

@@ -8,7 +8,7 @@ import pytest
from app.services.letzshop import LetzshopClientError
from app.tasks.letzshop_tasks import process_historical_import
from models.database.letzshop import LetzshopHistoricalImportJob
from app.modules.marketplace.models import LetzshopHistoricalImportJob
@pytest.fixture

View File

@@ -9,8 +9,8 @@ import time
import pytest
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)

View File

@@ -3,7 +3,7 @@
import pytest
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
@pytest.mark.unit

View File

@@ -4,8 +4,8 @@
import pytest
from sqlalchemy.exc import IntegrityError
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)

View File

@@ -4,7 +4,7 @@
import pytest
from sqlalchemy.exc import IntegrityError
from models.database.product import Product
from app.modules.catalog.models import Product
@pytest.mark.unit

View File

@@ -363,11 +363,9 @@ class TestInventoryService:
def test_get_product_inventory_no_inventory(self, db, test_product, test_vendor):
"""Test getting inventory for product with no inventory entries."""
# Create a new product without inventory
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
MarketplaceProductTranslation,
)
from models.database.product import Product
from app.modules.marketplace.models import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProductTranslation
from app.modules.catalog.models import Product
unique_id = str(uuid.uuid4())[:8]
mp = MarketplaceProduct(

View File

@@ -26,8 +26,8 @@ from app.services.marketplace_product_service import (
MarketplaceProductService,
marketplace_product_service,
)
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)
from models.schema.marketplace_product import (

View File

@@ -12,7 +12,7 @@ from app.exceptions.marketplace_import_job import (
)
from app.exceptions.vendor import UnauthorizedVendorAccessException
from app.services.marketplace_import_job_service import MarketplaceImportJobService
from models.database.marketplace_import_job import MarketplaceImportJob
from app.modules.marketplace.models import MarketplaceImportJob
from models.schema.marketplace_import_job import MarketplaceImportJobRequest
@@ -283,7 +283,7 @@ class TestMarketplaceImportJobService:
self, db, test_marketplace_import_job, test_vendor
):
"""Test converting database model to response model."""
from models.database.marketplace_import_job import MarketplaceImportJob as MIJ
from app.modules.marketplace.models import MarketplaceImportJob as MIJ
# Re-query to get fresh instance with relationships
job = db.query(MIJ).filter(MIJ.id == test_marketplace_import_job.id).first()

View File

@@ -16,7 +16,7 @@ from unittest.mock import MagicMock, patch
import pytest
from app.services.onboarding_service import OnboardingService
from models.database.onboarding import OnboardingStatus, OnboardingStep, VendorOnboarding
from app.modules.marketplace.models import OnboardingStatus, OnboardingStep, VendorOnboarding
@pytest.mark.unit

View File

@@ -10,8 +10,8 @@ from sqlalchemy.exc import SQLAlchemyError
from app.exceptions import AdminOperationException, VendorNotFoundException
from app.services.stats_service import StatsService
from app.modules.inventory.models import Inventory
from models.database.marketplace_product import MarketplaceProduct
from models.database.marketplace_product_translation import (
from app.modules.marketplace.models import (
MarketplaceProduct,
MarketplaceProductTranslation,
)

View File

@@ -4,7 +4,7 @@
import pytest
from app.services.usage_service import UsageService, usage_service
from models.database.product import Product
from app.modules.catalog.models import Product
from models.database.subscription import SubscriptionTier, VendorSubscription
from models.database.vendor import VendorUser

View File

@@ -358,7 +358,7 @@ class TestVendorService:
def test_add_product_to_vendor_success(self, db, test_vendor, unique_product):
"""Test successfully adding product to vendor."""
from models.database.marketplace_product import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProduct
# Re-query objects to avoid session issues
vendor = db.query(Vendor).filter(Vendor.id == test_vendor.id).first()
@@ -398,7 +398,7 @@ class TestVendorService:
def test_add_product_to_vendor_already_exists(self, db, test_vendor, test_product):
"""Test adding product that's already in vendor fails."""
# Re-query to get fresh instances
from models.database.product import Product
from app.modules.catalog.models import Product
vendor = db.query(Vendor).filter(Vendor.id == test_vendor.id).first()
product = db.query(Product).filter(Product.id == test_product.id).first()

View File

@@ -9,7 +9,7 @@ import requests
import requests.exceptions
from app.utils.csv_processor import CSVProcessor
from models.database.marketplace_product import MarketplaceProduct
from app.modules.marketplace.models import MarketplaceProduct
@pytest.mark.unit