# tests/fixtures/loyalty_fixtures.py """ Loyalty module test fixtures. Provides fixtures for: - Loyalty programs (company-based) - Loyalty cards - Transactions - Staff PINs - Authentication tokens for loyalty tests """ import uuid from datetime import UTC, datetime, timedelta import pytest from app.modules.loyalty.models import ( LoyaltyCard, LoyaltyProgram, LoyaltyTransaction, StaffPin, ) from app.modules.loyalty.models.loyalty_program import LoyaltyType from app.modules.loyalty.models.loyalty_transaction import TransactionType from app.modules.tenancy.models import Company, Vendor, VendorUser, VendorUserType from app.modules.customers.models import Customer from middleware.auth import AuthManager @pytest.fixture def test_loyalty_program(db, test_company): """Create a test loyalty program for a company.""" program = LoyaltyProgram( company_id=test_company.id, loyalty_type=LoyaltyType.POINTS.value, points_per_euro=10, welcome_bonus_points=50, minimum_redemption_points=100, minimum_purchase_cents=0, points_expiration_days=365, cooldown_minutes=15, max_daily_stamps=5, require_staff_pin=True, card_name="Test Rewards", card_color="#4F46E5", is_active=True, points_rewards=[ {"id": "reward_1", "name": "€5 off", "points_required": 100, "description": "€5 discount"}, {"id": "reward_2", "name": "€10 off", "points_required": 200, "description": "€10 discount"}, {"id": "reward_3", "name": "€25 off", "points_required": 500, "description": "€25 discount"}, ], ) db.add(program) db.commit() db.refresh(program) return program @pytest.fixture def test_loyalty_program_no_expiration(db, test_company): """Create a test loyalty program without point expiration.""" # Use different company to avoid unique constraint from app.modules.tenancy.models import Company unique_id = str(uuid.uuid4())[:8] company = Company( name=f"No Expiry Company {unique_id}", contact_email=f"noexpiry{unique_id}@test.com", is_active=True, ) db.add(company) db.flush() program = LoyaltyProgram( company_id=company.id, loyalty_type=LoyaltyType.POINTS.value, points_per_euro=1, welcome_bonus_points=0, minimum_redemption_points=50, points_expiration_days=None, # No expiration cooldown_minutes=0, max_daily_stamps=10, require_staff_pin=False, card_name="No Expiry Rewards", is_active=True, ) db.add(program) db.commit() db.refresh(program) return program @pytest.fixture def test_loyalty_card(db, test_loyalty_program, test_customer, test_vendor): """Create a test loyalty card.""" unique_id = str(uuid.uuid4())[:8].upper() card = LoyaltyCard( company_id=test_loyalty_program.company_id, program_id=test_loyalty_program.id, customer_id=test_customer.id, enrolled_at_vendor_id=test_vendor.id, card_number=f"CARD-{unique_id}", customer_email=test_customer.email, customer_phone=test_customer.phone, customer_name=f"{test_customer.first_name} {test_customer.last_name}", points_balance=100, stamps_balance=0, total_points_earned=150, total_points_redeemed=50, is_active=True, last_activity_at=datetime.now(UTC), ) db.add(card) db.commit() db.refresh(card) return card @pytest.fixture def test_loyalty_card_inactive(db, test_loyalty_program, test_vendor): """Create a test loyalty card that hasn't been used in a long time (for expiration tests).""" unique_id = str(uuid.uuid4())[:8].upper() card = LoyaltyCard( company_id=test_loyalty_program.company_id, program_id=test_loyalty_program.id, customer_id=None, enrolled_at_vendor_id=test_vendor.id, card_number=f"INACTIVE-{unique_id}", customer_email=f"inactive{unique_id}@test.com", customer_name="Inactive Customer", points_balance=500, stamps_balance=0, total_points_earned=500, is_active=True, # Last activity was 400 days ago (beyond 365-day expiration) last_activity_at=datetime.now(UTC) - timedelta(days=400), ) db.add(card) db.commit() db.refresh(card) return card @pytest.fixture def test_loyalty_transaction(db, test_loyalty_card, test_vendor): """Create a test loyalty transaction.""" transaction = LoyaltyTransaction( company_id=test_loyalty_card.company_id, card_id=test_loyalty_card.id, vendor_id=test_vendor.id, transaction_type=TransactionType.POINTS_EARNED.value, points_delta=50, balance_after=150, stamps_delta=0, stamps_balance_after=0, notes="Test purchase", transaction_at=datetime.now(UTC), ) db.add(transaction) db.commit() db.refresh(transaction) return transaction @pytest.fixture def test_staff_pin(db, test_loyalty_program, test_vendor): """Create a test staff PIN.""" from app.modules.loyalty.services.pin_service import pin_service unique_id = str(uuid.uuid4())[:8] pin = StaffPin( program_id=test_loyalty_program.id, vendor_id=test_vendor.id, staff_name=f"Test Staff {unique_id}", pin_hash=pin_service._hash_pin("1234"), is_active=True, ) db.add(pin) db.commit() db.refresh(pin) return pin