This commit completes the migration to a fully module-driven architecture: ## Models Migration - Moved all domain models from models/database/ to their respective modules: - tenancy: User, Admin, Vendor, Company, Platform, VendorDomain, etc. - cms: MediaFile, VendorTheme - messaging: Email, VendorEmailSettings, VendorEmailTemplate - core: AdminMenuConfig - models/database/ now only contains Base and TimestampMixin (infrastructure) ## Schemas Migration - Moved all domain schemas from models/schema/ to their respective modules: - tenancy: company, vendor, admin, team, vendor_domain - cms: media, image, vendor_theme - messaging: email - models/schema/ now only contains base.py and auth.py (infrastructure) ## Routes Migration - Moved admin routes from app/api/v1/admin/ to modules: - menu_config.py -> core module - modules.py -> tenancy module - module_config.py -> tenancy module - app/api/v1/admin/ now only aggregates auto-discovered module routes ## Menu System - Implemented module-driven menu system with MenuDiscoveryService - Extended FrontendType enum: PLATFORM, ADMIN, VENDOR, STOREFRONT - Added MenuItemDefinition and MenuSectionDefinition dataclasses - Each module now defines its own menu items in definition.py - MenuService integrates with MenuDiscoveryService for template rendering ## Documentation - Updated docs/architecture/models-structure.md - Updated docs/architecture/menu-management.md - Updated architecture validation rules for new exceptions ## Architecture Validation - Updated MOD-019 rule to allow base.py in models/schema/ - Created core module exceptions.py and schemas/ directory - All validation errors resolved (only warnings remain) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
139 lines
4.4 KiB
Python
139 lines
4.4 KiB
Python
# tests/unit/models/database/test_vendor.py
|
|
"""Unit tests for Vendor database model."""
|
|
|
|
import pytest
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
from app.modules.tenancy.models import Vendor
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.database
|
|
class TestVendorModel:
|
|
"""Test Vendor model."""
|
|
|
|
def test_vendor_creation(self, db, test_company):
|
|
"""Test Vendor model creation with company relationship."""
|
|
vendor = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="DBTEST",
|
|
subdomain="dbtest",
|
|
name="Database Test Vendor",
|
|
description="Testing vendor model",
|
|
contact_email="contact@dbtest.com",
|
|
contact_phone="+1234567890",
|
|
business_address="123 Test Street",
|
|
is_active=True,
|
|
is_verified=False,
|
|
)
|
|
|
|
db.add(vendor)
|
|
db.commit()
|
|
db.refresh(vendor)
|
|
|
|
assert vendor.id is not None
|
|
assert vendor.vendor_code == "DBTEST"
|
|
assert vendor.subdomain == "dbtest"
|
|
assert vendor.name == "Database Test Vendor"
|
|
assert vendor.company_id == test_company.id
|
|
assert vendor.contact_email == "contact@dbtest.com"
|
|
assert vendor.is_active is True
|
|
assert vendor.is_verified is False
|
|
assert vendor.created_at is not None
|
|
|
|
def test_vendor_with_letzshop_urls(self, db, test_company):
|
|
"""Test Vendor model with multi-language Letzshop URLs."""
|
|
vendor = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="MULTILANG",
|
|
subdomain="multilang",
|
|
name="Multi-Language Vendor",
|
|
letzshop_csv_url_fr="https://example.com/feed_fr.csv",
|
|
letzshop_csv_url_en="https://example.com/feed_en.csv",
|
|
letzshop_csv_url_de="https://example.com/feed_de.csv",
|
|
is_active=True,
|
|
)
|
|
|
|
db.add(vendor)
|
|
db.commit()
|
|
db.refresh(vendor)
|
|
|
|
assert vendor.letzshop_csv_url_fr == "https://example.com/feed_fr.csv"
|
|
assert vendor.letzshop_csv_url_en == "https://example.com/feed_en.csv"
|
|
assert vendor.letzshop_csv_url_de == "https://example.com/feed_de.csv"
|
|
|
|
def test_vendor_code_uniqueness(self, db, test_company):
|
|
"""Test vendor_code unique constraint."""
|
|
vendor1 = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="UNIQUE",
|
|
subdomain="unique1",
|
|
name="Unique Vendor 1",
|
|
)
|
|
db.add(vendor1)
|
|
db.commit()
|
|
|
|
# Duplicate vendor_code should raise error
|
|
with pytest.raises(IntegrityError):
|
|
vendor2 = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="UNIQUE",
|
|
subdomain="unique2",
|
|
name="Unique Vendor 2",
|
|
)
|
|
db.add(vendor2)
|
|
db.commit()
|
|
|
|
def test_subdomain_uniqueness(self, db, test_company):
|
|
"""Test subdomain unique constraint."""
|
|
vendor1 = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="VENDOR1",
|
|
subdomain="testsubdomain",
|
|
name="Vendor 1",
|
|
)
|
|
db.add(vendor1)
|
|
db.commit()
|
|
|
|
# Duplicate subdomain should raise error
|
|
with pytest.raises(IntegrityError):
|
|
vendor2 = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="VENDOR2",
|
|
subdomain="testsubdomain",
|
|
name="Vendor 2",
|
|
)
|
|
db.add(vendor2)
|
|
db.commit()
|
|
|
|
def test_vendor_default_values(self, db, test_company):
|
|
"""Test Vendor model default values."""
|
|
vendor = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="DEFAULTS",
|
|
subdomain="defaults",
|
|
name="Default Vendor",
|
|
)
|
|
db.add(vendor)
|
|
db.commit()
|
|
db.refresh(vendor)
|
|
|
|
assert vendor.is_active is True # Default
|
|
assert vendor.is_verified is False # Default
|
|
|
|
def test_vendor_company_relationship(self, db, test_company):
|
|
"""Test Vendor-Company relationship."""
|
|
vendor = Vendor(
|
|
company_id=test_company.id,
|
|
vendor_code="RELTEST",
|
|
subdomain="reltest",
|
|
name="Relationship Test Vendor",
|
|
)
|
|
db.add(vendor)
|
|
db.commit()
|
|
db.refresh(vendor)
|
|
|
|
assert vendor.company is not None
|
|
assert vendor.company.id == test_company.id
|
|
assert vendor.company.name == test_company.name
|