# Wallet Utils Test Suite

This sandbox contains a Django test app for comprehensive testing of the `wallet_utils` package.

## Test Organization

**Tests are kept separate from the package** to ensure they are NOT included when installing the package via pip:

- ✅ **Tests location**: `sandbox/` (at project root, same level as `packages/`)
- ✅ **Package location**: `packages/wallet_utils/`
- ✅ **Distribution**: Only package source code is included in pip installs
- ✅ **Development**: Tests remain accessible for development and CI/CD

This follows Python packaging best practices where tests are kept with the project but excluded from distribution.

## Setup

1. **Install dependencies**:
   ```bash
   # From sandbox directory
   cd sandbox
   
   # Install Django and other dependencies
   pip install -r requirements.txt
   
   # Install wallet_utils package (from project root)
   pip install -e ../packages/wallet_utils
   ```

2. **Run migrations**:
   ```bash
   python manage.py migrate
   ```

## Development Workflow

Since the package is installed in **editable mode** (`pip install -e`), here's what you need to know:

### When Changes Are Automatically Picked Up (No Reinstall Needed)

✅ **Python code changes** (service, repository, exceptions, transaction types):
- Changes to `.py` files in `packages/wallet_utils/src/wallet_utils/`
- Automatically available after saving the file
- Just restart your Django test server or rerun tests

✅ **Documentation changes**:
- Changes to `.md` files
- No reinstall needed

### When You Need to Reinstall

⚠️ **Package metadata changes** (`pyproject.toml`):
- If you change package name, version, dependencies, etc.
- Run: `pip install -e ../packages/wallet_utils` (from sandbox directory)

### When You Need to Rerun Migrations

⚠️ **Model changes** (fields, indexes, etc.):
- If you modify `AbstractWalletTransaction` or `WalletTransaction` models
- Create new migration: `python manage.py makemigrations wallet_utils` (from sandbox)
- Run migration: `python manage.py migrate`

⚠️ **Migration changes**:
- If you modify existing migrations, you may need to:
  - Reset database: Delete `db.sqlite3` (if using SQLite)
  - Or handle migration conflicts manually

### Quick Reference

```bash
# After changing Python code (service, repository, etc.)
# No action needed - just rerun tests

# After changing pyproject.toml
pip install -e ../packages/wallet_utils

# After changing models
python manage.py makemigrations wallet_utils
python manage.py migrate

# After changing migrations (if needed)
rm db.sqlite3  # Reset SQLite database
python manage.py migrate
```

## Running Tests

Run all tests:
```bash
python manage.py test test_app.tests
```

Run specific test file:
```bash
python manage.py test test_app.tests.test_wallet_service
python manage.py test test_app.tests.test_wallet_repository
python manage.py test test_app.tests.test_wallet_models
python manage.py test test_app.tests.test_transaction_types
python manage.py test test_app.tests.test_exceptions
```

Run specific test class:
```bash
python manage.py test test_app.tests.test_wallet_service.WalletServiceAddPointTests
```

Run specific test method:
```bash
python manage.py test test_app.tests.test_wallet_service.WalletServiceAddPointTests.test_add_point_standard
```

## Test Coverage

The test suite covers:

### 1. WalletService Tests (`test_wallet_service.py`)
- **Add Point Operations**: Standard, edge cases, error cases
- **Deduct Point Operations**: Standard, edge cases, error cases, race conditions
- **Transaction History**: All filters, pagination, ordering
- **Separate Wallet Model**: Using separate model for balances
- **Custom Field Names**: Field name mapping
- **Custom User ID Field**: Custom user_id field name
- **Transaction Types**: Constants and helpers
- **Edge Cases**: System user IDs, very long remarks, empty values, concurrent operations
- **Race Conditions**: Atomic deduction prevention

### 2. WalletRepository Tests (`test_wallet_repository.py`)
- **Initialization**: User model, separate wallet model, custom fields
- **Balance Operations**: Update, deduct, get balance
- **Separate Model**: Operations with separate wallet model
- **Transaction Records**: Creating transaction records

### 3. Model Tests (`test_wallet_models.py`)
- **WalletTransaction Model**: Field validation, defaults, ordering
- **AbstractWalletTransaction**: Abstract model behavior, custom extensions
- **Indexes**: Query performance with indexes
- **Decimal Precision**: Default 2 decimal places

### 4. Transaction Types Tests (`test_transaction_types.py`)
- **Constants**: All transaction type constants
- **Helper Functions**: `get_transaction_type()`, `get_transaction_type_name()`
- **Dictionaries**: `TRANSACTION_TYPES`, `TRANSACTION_TYPE_NAMES`
- **Consistency**: Dictionary consistency checks

### 5. Exception Tests (`test_exceptions.py`)
- **WalletOperationError**: Base exception
- **InsufficientBalanceError**: Balance error with available/requested
- **InvalidPointTypeError**: Invalid point type error
- **InvalidParamsError**: Invalid parameters error

## Test Categories

### Standard Cases
- Normal operations with valid inputs
- Expected behavior verification
- Return value validation

### Edge Cases
- Zero amounts
- Very small amounts
- Very large amounts
- Exact balance deductions
- Empty strings/None values
- System user IDs (-100)

### Error Cases
- Invalid point types
- Invalid parameters
- Insufficient balance
- Reserved fields in extra_data
- Invalid transaction types

### Outlier Cases
- Very long remarks
- Multiple concurrent operations
- Balance accuracy after many operations
- Race condition prevention
- Custom field mappings
- Separate wallet models

## Test Models

The test app includes several test models:

- **TestUser**: User model with wallet balance fields
- **TestWallet**: Separate wallet model for testing
- **TestWalletCustomField**: Wallet model with custom user_id field name

These models simulate real-world usage scenarios and allow testing of various configurations.

## Notes

- Tests use SQLite database (in-memory for most tests)
- `TransactionTestCase` is used for race condition tests
- All tests are isolated and can run independently
- Tests follow Django testing best practices
