# Pricing Model Tests Documentation

This directory contains comprehensive tests for the Django pricing models in the Servala project. The tests ensure that price calculations work correctly and prevent regressions when making changes to the pricing logic.

## Test Structure

### `test_pricing.py`
Core tests for all pricing models including:
- **ComputePlanTestCase**: Tests for compute plan pricing and retrieval
- **StoragePlanTestCase**: Tests for storage plan pricing
- **ProgressiveDiscountModelTestCase**: Tests for discount calculations with multiple tiers
- **VSHNAppCatPriceTestCase**: Tests for AppCat service pricing with discounts
- **VSHNAppCatAddonTestCase**: Tests for addon pricing (base fees and unit rates)

### `test_pricing_edge_cases.py`
Edge case and error condition tests including:
- Discount calculations with zero units or very large numbers
- Price calculations with inactive discount models
- Missing price data handling
- Decimal precision edge cases
- Unique constraint enforcement
- Addon ordering and filtering

### `test_pricing_integration.py`
Integration tests that verify models work together:
- Complete pricing setup across all models
- Multi-currency pricing scenarios
- Complex AppCat services with all features
- External price comparisons
- Real-world comprehensive pricing scenarios

### `test_utils.py`
Helper utilities and mixins for test setup:
- `PricingTestMixin`: Common setup methods for pricing tests
- Helper functions for expected price calculations

## Running the Tests

### Individual Test Classes
```bash
# Run specific test class
uv run --extra dev manage.py test hub.services.tests.test_pricing.ComputePlanTestCase --verbosity=2

# Run specific test method
uv run --extra dev manage.py test hub.services.tests.test_pricing.VSHNAppCatPriceTestCase.test_calculate_final_price_simple --verbosity=2
```

### All Pricing Tests
```bash
# Run all pricing tests
uv run --extra dev manage.py test hub.services.tests --verbosity=2

# Run with database reuse for faster execution
uv run --extra dev manage.py test hub.services.tests --verbosity=2 --keepdb
```

### Test Script
Use the provided test runner script:
```bash
./run_pricing_tests.sh
```

## Test Coverage

The test suite covers:

### Basic Model Functionality
- Model creation and string representations
- Field validation and constraints
- Relationship handling

### Price Calculations
- Simple price retrieval (`get_price` methods)
- Progressive discount calculations
- Final price calculations with base fees, unit rates, and addons
- Multi-currency support

### Edge Cases
- Zero or negative values
- Very large numbers
- Missing price data
- Inactive discount models
- Decimal precision issues

### Business Logic
- Mandatory vs. optional addons
- Discount tier spanning
- Service level pricing differences
- External price comparisons

### Integration Scenarios
- Complete service setups
- Real-world pricing scenarios
- Cross-model relationships

## Key Test Scenarios

### Progressive Discount Testing
The tests verify that progressive discounts work correctly:
```python
# Example: 0-9 units (0%), 10-49 units (10%), 50+ units (20%)
# For 60 units:
# - First 10 units: full price
# - Next 40 units: 90% of price (10% discount)
# - Next 10 units: 80% of price (20% discount)
```

### Addon Pricing Testing
Tests cover both addon types:
- **Base Fee Addons**: Fixed cost regardless of units
- **Unit Rate Addons**: Cost multiplied by number of units

### Multi-Currency Testing
Ensures pricing works across CHF, EUR, and USD currencies.

## Best Practices for Adding New Tests

1. **Use Descriptive Test Names**: Test method names should clearly describe what is being tested
2. **Test Both Success and Failure Cases**: Include tests for valid inputs and error conditions
3. **Use Decimal for Monetary Values**: Always use `Decimal` for precise monetary calculations
4. **Test Edge Cases**: Include tests for boundary conditions and unusual inputs
5. **Verify Relationships**: Test that model relationships work correctly
6. **Test Business Logic**: Focus on the actual business rules, not just CRUD operations

## Common Test Patterns

### Setting Up Test Data
```python
def setUp(self):
    self.cloud_provider = CloudProvider.objects.create(
        name="Test Provider",
        slug="test-provider",
        description="Test description",
        website="https://test.com"
    )
```

### Testing Price Calculations
```python
def test_price_calculation(self):
    # Set up pricing data
    # Call calculation method
    result = price_config.calculate_final_price(currency, service_level, units)
    # Verify expected result
    self.assertEqual(result['total_price'], expected_amount)
```

### Testing Error Conditions
```python
def test_negative_units_error(self):
    with self.assertRaises(ValueError):
        price_config.calculate_final_price(currency, service_level, -1)
```

## Maintenance

- Run tests after any changes to pricing models or calculations
- Update tests when adding new pricing features
- Add regression tests when fixing bugs
- Keep test data realistic but minimal
- Document complex test scenarios in comments

## Dependencies

The tests require:
- Django test framework
- Test database (SQLite in-memory for speed)
- All pricing models and their dependencies
- Decimal library for precise calculations
