# Migration Guide: UUID to TEXT User IDs

## Overview

This guide helps you migrate from UUID-based user IDs to custom TEXT username format (e.g., `rta_vytran`, `rta_traphan`).

## What Changed

### Before (v1)
- User IDs were UUIDs: `550e8400-e29b-41d4-a716-446655440000`
- Auto-generated by database
- Not human-readable

### After (v2)
- User IDs are custom TEXT usernames: `rta_vytran`, `rta_traphan`, `rta_minhnguyen`
- User-defined at account creation
- Human-readable and memorable
- Better for referencing users in support/admin tasks

## Database Changes

### Schema Changes
- `users.id`: Changed from `UUID PRIMARY KEY DEFAULT uuid_generate_v4()` to `TEXT PRIMARY KEY`
- `users.parent_id`: Changed from `UUID` to `TEXT`
- `transactions.user_id`: Changed from `UUID` to `TEXT`
- `transactions.shared_with_id`: Changed from `UUID` to `TEXT`
- `monthly_stats.user_id`: Changed from `TEXT` (was storing UUID as text) to `TEXT` (now stores username)
- `monthly_stats.id`: Still TEXT, but format changed from `{uuid}_{YYYY-MM}` to `{username}_{YYYY-MM}`

### Trigger Changes
- All function signatures changed from `p_user_id UUID` to `p_user_id TEXT`
- Removed all `::uuid` type casting
- Logic remains identical

## Migration Steps

### Step 1: Backup Existing Data

If you have production data in Supabase, export it first:

```sql
-- Export users
COPY (SELECT * FROM users) TO '/tmp/users_backup.csv' WITH CSV HEADER;

-- Export transactions
COPY (SELECT * FROM transactions) TO '/tmp/transactions_backup.csv' WITH CSV HEADER;

-- Export monthly_stats
COPY (SELECT * FROM monthly_stats) TO '/tmp/monthly_stats_backup.csv' WITH CSV HEADER;
```

Or use Supabase Dashboard: Database > Backups

### Step 2: Drop Old Tables and Functions

Run this in Supabase SQL Editor:

```sql
-- Drop triggers first
DROP TRIGGER IF EXISTS on_transaction_insert ON transactions;
DROP TRIGGER IF EXISTS on_transaction_update ON transactions;

-- Drop functions
DROP FUNCTION IF EXISTS handle_new_transaction();
DROP FUNCTION IF EXISTS handle_transaction_update();
DROP FUNCTION IF EXISTS recalculate_monthly_stats(UUID, TEXT);
DROP FUNCTION IF EXISTS recalculate_monthly_stats(TEXT, TEXT);
DROP FUNCTION IF EXISTS get_leg_commission_volume(UUID, TEXT);
DROP FUNCTION IF EXISTS get_leg_commission_volume(TEXT, TEXT);
DROP FUNCTION IF EXISTS get_commission_rate(NUMERIC);

-- Drop tables (cascades to references)
DROP TABLE IF EXISTS monthly_stats CASCADE;
DROP TABLE IF EXISTS transactions CASCADE;
DROP TABLE IF EXISTS users CASCADE;
```

### Step 3: Apply New Schema

Copy the entire contents of `scripts/supabase_schema_v2.sql` and run it in Supabase SQL Editor.

This will create:
- `users` table with TEXT id
- `transactions` table with TEXT user_id references
- `monthly_stats` table with TEXT user_id references
- Proper indexes

### Step 4: Apply New Triggers

Copy the entire contents of `scripts/supabase_triggers_v2.sql` and run it in Supabase SQL Editor.

This will create:
- `get_commission_rate()` function
- `get_leg_commission_volume()` function (recursive)
- `recalculate_monthly_stats()` function
- `handle_new_transaction()` trigger function
- `handle_transaction_update()` trigger function
- Triggers: `on_transaction_insert`, `on_transaction_update`

### Step 5: Verify Setup

Run this verification query:

```sql
-- Check triggers exist
SELECT trigger_name, event_manipulation, event_object_table
FROM information_schema.triggers
WHERE trigger_schema = 'public'
AND event_object_table = 'transactions'
ORDER BY trigger_name;
```

Expected output:
```
trigger_name              | event_manipulation | event_object_table
--------------------------+--------------------+-------------------
on_transaction_insert     | INSERT             | transactions
on_transaction_update     | UPDATE             | transactions
```

### Step 6: Seed Test Data (Optional)

If starting fresh, you can seed test data using the Python application:

```bash
# Make sure DATABASE_TYPE=supabase in .env
python -c "from rt_commission_dashboard.core.supabase_handler import SupabaseHandler; SupabaseHandler()._seed_mock_data()"
```

This creates:
- `rta_admin` (admin, no parent)
- `rta_vytran` (affiliate, child of admin)
- `rta_traphan` (affiliate, child of vytran)
- `rta_minhnguyen` (ctv, child of traphan)
- `rta_hangle` (ctv, child of vytran)
- `rta_orphan` (affiliate, no parent)
- Sample transactions for last 3 months

### Step 7: Verify Data and Calculations

Check that data was seeded correctly:

```sql
-- Check users
SELECT id, email, full_name, role, parent_id FROM users ORDER BY id;

-- Check transactions
SELECT user_id, amount, type, status, created_at
FROM transactions
ORDER BY created_at DESC
LIMIT 10;

-- Check monthly stats (should be auto-calculated by triggers)
SELECT
    ms.user_id,
    u.full_name,
    ms.month,
    ms.personal_sales_volume,
    ms.f1_sales_volume,
    ms.tier_rate,
    ms.total_commission
FROM monthly_stats ms
JOIN users u ON ms.user_id = u.id
ORDER BY ms.month DESC, u.full_name;
```

## Migrating Production Data

If you have existing production data with UUIDs, you need to:

1. Create a mapping table: `uuid -> new_username`
2. Update all foreign keys using the mapping
3. This is a complex migration - contact support for assistance

Example mapping approach:

```sql
-- Create temporary mapping
CREATE TEMP TABLE user_mapping (
    old_uuid UUID,
    new_username TEXT
);

-- Manual mapping (you define usernames for each UUID)
INSERT INTO user_mapping VALUES
('550e8400-e29b-41d4-a716-446655440000', 'rta_vytran'),
('7c9e6679-7425-40de-944b-e07fc1f90ae7', 'rta_traphan');
-- ... add all users

-- Update tables (after new schema is in place)
-- This requires carefully updating parent_id, user_id, shared_with_id references
-- Contact support for detailed migration script
```

## Python Code Changes

The Python code in `rt_commission_dashboard/core/supabase_handler.py` has been updated to:

1. Use TEXT usernames when inserting users
2. Pass TEXT usernames to `create_retail_sale()` and `create_shared_opportunity()`
3. No other changes needed - the API remains the same

## Username Format Guidelines

When creating new users, follow these conventions:

- **Format**: `rta_{firstname}` or `rta_{firstname}{lastname}`
- **Lowercase**: Always use lowercase
- **No spaces**: Use underscores if needed
- **ASCII only**: Avoid special characters, accents, or Unicode
- **Unique**: Each username must be unique
- **Examples**:
  - `rta_vytran` (Vy Tran)
  - `rta_traphan` (Tra Phan)
  - `rta_minhnguyen` (Minh Nguyen)
  - `rta_admin` (system admin)

## Rollback (Emergency)

If you need to rollback to UUID-based IDs:

1. Use your backup from Step 1
2. Run `scripts/supabase_schema.sql` (old v1 schema)
3. Run `scripts/supabase_triggers.sql` (old v1 triggers)
4. Restore data from backups

## Support

If you encounter issues during migration:

1. Check Supabase logs: Dashboard > Database > Logs
2. Verify trigger creation: Run verification query from Step 5
3. Check function exists: `\df` in psql or Dashboard > Database > Functions
4. Review error messages carefully - common issues:
   - Foreign key violations (parent_id references)
   - Duplicate username errors
   - Permission issues (use service_role key)

## Testing After Migration

Test the following workflows:

1. **Create user**: Should accept TEXT username
2. **Create retail sale**: Should trigger commission calculation
3. **Create shared opportunity**: Should calculate for both users
4. **Check monthly stats**: Should auto-populate after transaction insert
5. **Verify tier upgrades**: Large sale should upgrade tier and recalculate entire month
6. **Test override commission**: Parent with higher tier should earn differential on child's volume

Example test:

```python
from rt_commission_dashboard.core.supabase_handler import SupabaseHandler

db = SupabaseHandler()

# Create a large sale for rta_traphan
db.create_retail_sale('rta_traphan', 250000000.00, {'test': 'tier upgrade'})

# Check their stats - should be 22% tier now
# Check parent rta_vytran - should have override commission
```

## FAQ

**Q: Can I mix UUID and TEXT user IDs?**
A: No, all user IDs must be the same type (TEXT).

**Q: What if I want to change a username later?**
A: Username changes require updating all foreign key references. Not recommended after production use.

**Q: Can usernames contain uppercase letters?**
A: Technically yes, but convention is lowercase for consistency.

**Q: What's the maximum username length?**
A: PostgreSQL TEXT has no practical limit, but keep it under 50 characters for usability.

**Q: Do I need to update my .env file?**
A: No, .env configuration remains the same (SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_KEY).

## Next Steps

After migration is complete:

1. Update application code to collect username during user registration
2. Add username validation (format, uniqueness, reserved words)
3. Consider adding username change workflow (if needed)
4. Update documentation/training for support staff using new username format
5. Test thoroughly in staging before production rollout

---

**Migration Version**: v2 (TEXT usernames)
**Last Updated**: 2026-01-06
**Compatibility**: Requires Supabase PostgreSQL 13+
