# app/modules/customers/tests/unit/test_customer_metrics.py """Unit tests for CustomerMetricsProvider.get_merchant_metrics.""" import uuid import pytest from app.modules.customers.models.customer import Customer from app.modules.customers.services.customer_metrics import CustomerMetricsProvider from app.modules.tenancy.models import Merchant, Store, User @pytest.fixture def cust_merchant(db): """Create a merchant for customer metrics tests.""" from middleware.auth import AuthManager auth = AuthManager() user = User( email=f"custowner_{uuid.uuid4().hex[:8]}@test.com", username=f"custowner_{uuid.uuid4().hex[:8]}", hashed_password=auth.hash_password("pass123"), role="merchant_owner", is_active=True, ) db.add(user) db.flush() merchant = Merchant( name="Customer Metrics Merchant", owner_user_id=user.id, contact_email=user.email, is_active=True, is_verified=True, ) db.add(merchant) db.commit() db.refresh(merchant) return merchant @pytest.fixture def cust_stores(db, cust_merchant): """Create 2 stores for the merchant.""" stores = [] for i in range(2): uid = uuid.uuid4().hex[:8].upper() stores.append(Store( merchant_id=cust_merchant.id, store_code=f"CSTORE_{uid}", subdomain=f"cstore{uid.lower()}", name=f"Cust Store {i}", is_active=True, is_verified=True, )) db.add_all(stores) db.commit() for s in stores: db.refresh(s) return stores @pytest.fixture def cust_customers(db, cust_stores): """Create customers across the merchant's stores.""" customers = [] # 3 customers in store 0 for i in range(3): uid = uuid.uuid4().hex[:8] customers.append(Customer( store_id=cust_stores[0].id, email=f"cust_{uid}@test.com", hashed_password="hashed", # noqa: SEC001 first_name=f"First{i}", last_name=f"Last{i}", customer_number=f"C{uid}", is_active=True, )) # 2 customers in store 1 for i in range(2): uid = uuid.uuid4().hex[:8] customers.append(Customer( store_id=cust_stores[1].id, email=f"cust_{uid}@test.com", hashed_password="hashed", # noqa: SEC001 first_name=f"First{i}", last_name=f"Last{i}", customer_number=f"C{uid}", is_active=True, )) db.add_all(customers) db.commit() return customers @pytest.mark.unit @pytest.mark.customers class TestCustomerMetricsProviderMerchant: """Tests for CustomerMetricsProvider.get_merchant_metrics.""" def setup_method(self): self.provider = CustomerMetricsProvider() def test_total_customers_across_stores(self, db, cust_merchant, cust_stores, cust_customers): """Aggregates customers across all merchant stores.""" metrics = self.provider.get_merchant_metrics(db, cust_merchant.id) by_key = {m.key: m.value for m in metrics} assert by_key["customers.total"] == 5 def test_no_customers(self, db, cust_merchant, cust_stores): """Returns zero when stores have no customers.""" metrics = self.provider.get_merchant_metrics(db, cust_merchant.id) by_key = {m.key: m.value for m in metrics} assert by_key["customers.total"] == 0 def test_no_stores(self, db, cust_merchant): """Returns zero when merchant has no stores.""" metrics = self.provider.get_merchant_metrics(db, cust_merchant.id) by_key = {m.key: m.value for m in metrics} assert by_key["customers.total"] == 0 def test_nonexistent_merchant(self, db): """Returns zero for a non-existent merchant ID.""" metrics = self.provider.get_merchant_metrics(db, 999999) by_key = {m.key: m.value for m in metrics} assert by_key["customers.total"] == 0