- Add CustomerAddressService with CRUD operations - Add shop API endpoints for address management (GET, POST, PUT, DELETE) - Add set default endpoint for address type - Implement addresses.html with full UI (cards, modals, Alpine.js) - Integrate saved addresses in checkout flow - Address selector dropdowns for shipping/billing - Auto-select default addresses - Save new address checkbox option - Add country_iso field alongside country_name - Add address exceptions (NotFound, LimitExceeded, InvalidType) - Max 10 addresses per customer limit - One default address per type (shipping/billing) - Add unit tests for CustomerAddressService - Add integration tests for shop addresses API 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
163 lines
4.7 KiB
Python
163 lines
4.7 KiB
Python
# tests/fixtures/customer_fixtures.py
|
|
"""
|
|
Customer-related test fixtures.
|
|
|
|
Note: Fixtures should NOT use db.expunge() as it breaks lazy loading.
|
|
See tests/conftest.py for details on fixture best practices.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from models.database.customer import Customer, CustomerAddress
|
|
from models.database.order import Order
|
|
|
|
|
|
@pytest.fixture
|
|
def test_customer(db, test_vendor):
|
|
"""Create a test customer."""
|
|
customer = Customer(
|
|
vendor_id=test_vendor.id,
|
|
email="testcustomer@example.com",
|
|
hashed_password="hashed_password",
|
|
first_name="John",
|
|
last_name="Doe",
|
|
customer_number="TEST001",
|
|
is_active=True,
|
|
)
|
|
db.add(customer)
|
|
db.commit()
|
|
db.refresh(customer)
|
|
return customer
|
|
|
|
|
|
@pytest.fixture
|
|
def test_customer_address(db, test_vendor, test_customer):
|
|
"""Create a test customer shipping address."""
|
|
address = CustomerAddress(
|
|
vendor_id=test_vendor.id,
|
|
customer_id=test_customer.id,
|
|
address_type="shipping",
|
|
first_name="John",
|
|
last_name="Doe",
|
|
address_line_1="123 Main St",
|
|
city="Luxembourg",
|
|
postal_code="L-1234",
|
|
country_name="Luxembourg",
|
|
country_iso="LU",
|
|
is_default=True,
|
|
)
|
|
db.add(address)
|
|
db.commit()
|
|
db.refresh(address)
|
|
return address
|
|
|
|
|
|
@pytest.fixture
|
|
def test_customer_billing_address(db, test_vendor, test_customer):
|
|
"""Create a test customer billing address."""
|
|
address = CustomerAddress(
|
|
vendor_id=test_vendor.id,
|
|
customer_id=test_customer.id,
|
|
address_type="billing",
|
|
first_name="John",
|
|
last_name="Doe",
|
|
company="Test Company S.A.",
|
|
address_line_1="456 Business Ave",
|
|
city="Luxembourg",
|
|
postal_code="L-5678",
|
|
country_name="Luxembourg",
|
|
country_iso="LU",
|
|
is_default=True,
|
|
)
|
|
db.add(address)
|
|
db.commit()
|
|
db.refresh(address)
|
|
return address
|
|
|
|
|
|
@pytest.fixture
|
|
def test_customer_multiple_addresses(db, test_vendor, test_customer):
|
|
"""Create multiple addresses for testing limits and listing."""
|
|
addresses = []
|
|
for i in range(3):
|
|
address = CustomerAddress(
|
|
vendor_id=test_vendor.id,
|
|
customer_id=test_customer.id,
|
|
address_type="shipping" if i % 2 == 0 else "billing",
|
|
first_name=f"Name{i}",
|
|
last_name="Test",
|
|
address_line_1=f"{i}00 Test Street",
|
|
city="Luxembourg",
|
|
postal_code=f"L-{1000+i}",
|
|
country_name="Luxembourg",
|
|
country_iso="LU",
|
|
is_default=(i == 0),
|
|
)
|
|
db.add(address)
|
|
addresses.append(address)
|
|
db.commit()
|
|
for addr in addresses:
|
|
db.refresh(addr)
|
|
return addresses
|
|
|
|
|
|
@pytest.fixture
|
|
def test_order(db, test_vendor, test_customer, test_customer_address):
|
|
"""Create a test order with customer/address snapshots."""
|
|
from datetime import datetime, timezone
|
|
|
|
order = Order(
|
|
vendor_id=test_vendor.id,
|
|
customer_id=test_customer.id,
|
|
order_number="TEST-ORD-001",
|
|
status="pending",
|
|
channel="direct",
|
|
subtotal=99.99,
|
|
total_amount=99.99,
|
|
currency="EUR",
|
|
order_date=datetime.now(timezone.utc),
|
|
# Customer snapshot
|
|
customer_first_name=test_customer.first_name,
|
|
customer_last_name=test_customer.last_name,
|
|
customer_email=test_customer.email,
|
|
customer_phone=None,
|
|
# Shipping address snapshot
|
|
ship_first_name=test_customer_address.first_name,
|
|
ship_last_name=test_customer_address.last_name,
|
|
ship_address_line_1=test_customer_address.address_line_1,
|
|
ship_city=test_customer_address.city,
|
|
ship_postal_code=test_customer_address.postal_code,
|
|
ship_country_iso="LU",
|
|
# Billing address snapshot
|
|
bill_first_name=test_customer_address.first_name,
|
|
bill_last_name=test_customer_address.last_name,
|
|
bill_address_line_1=test_customer_address.address_line_1,
|
|
bill_city=test_customer_address.city,
|
|
bill_postal_code=test_customer_address.postal_code,
|
|
bill_country_iso="LU",
|
|
)
|
|
db.add(order)
|
|
db.commit()
|
|
db.refresh(order)
|
|
return order
|
|
|
|
|
|
@pytest.fixture
|
|
def test_order_item(db, test_order, test_product):
|
|
"""Create a test order item."""
|
|
from models.database.order import OrderItem
|
|
|
|
order_item = OrderItem(
|
|
order_id=test_order.id,
|
|
product_id=test_product.id,
|
|
product_name="Test Product",
|
|
product_sku="TEST-SKU-001",
|
|
quantity=1,
|
|
unit_price=49.99,
|
|
total_price=49.99,
|
|
)
|
|
db.add(order_item)
|
|
db.commit()
|
|
db.refresh(order_item)
|
|
return order_item
|