# Organization Migration Guide

This guide explains how to migrate existing users to the new multi-staff organization structure.

## Overview

The multi-staff dashboard feature requires migrating existing users with active subscriptions (tiers 3-5) to the new organization model. This migration:

1. Creates an organization for each eligible user
2. Sets them as the OWNER of their organization
3. Configures seat limits based on their subscription tier
4. Syncs data to both Prisma and Supabase databases

## Prerequisites

Before running the migration:

1. **Database Schema Applied**: Ensure organization tables exist
   ```bash
   # Check if tables exist
   npm run check:schema

   # If not, apply migrations
   npm run migrate:apply-all
   ```

2. **Backup Your Database**: Always backup before running migrations
   ```bash
   # Backup Prisma PostgreSQL
   pg_dump -h localhost -p 5432 -U postgres mawidi > backup-$(date +%Y%m%d).sql

   # Backup Supabase
   PGPASSWORD=postgres pg_dump -h localhost -p 54322 -U postgres postgres > backup-supabase-$(date +%Y%m%d).sql
   ```

3. **Environment Ready**: Make sure .env.local is configured
   - Database connection strings
   - Supabase credentials

## Eligibility Criteria

Users are eligible for migration if they meet ALL of the following:

- **Role**: CUSTOMER
- **Subscription Status**: active OR trialing
- **Tier**: tier3, tier4, or tier5 (multi-staff enabled)

### Seat Allocation by Tier

| Tier | Included Seats | Feature Level |
|------|----------------|---------------|
| tier1 | 0 | No multi-staff |
| tier2 | 0 | No multi-staff |
| tier3 | 1 | Business - 1 additional seat |
| tier4 | 2 | Enterprise - 2 additional seats |
| tier5 | 5 | Ultimate - 5 additional seats |

## Migration Process

### Step 1: Dry Run (REQUIRED)

Always run a dry run first to preview what will happen:

```bash
# Using npm script
npm run migrate:organizations:dry

# Or directly with ts-node
npx tsx scripts/migrate-to-organizations.ts --dry-run
```

The dry run will:
- Show how many users are eligible
- Preview organization names and seat limits
- NOT make any database changes

**Example Output:**
```
======================================================================
🚀 Organization Migration (DRY RUN)
======================================================================

📊 Found 5 eligible user(s) for migration

⚠️  DRY RUN MODE - No changes will be made

[1/5] Processing: john@clinic.com (tier3)...
  [DRY RUN] Would create organization for john@clinic.com:
    - Organization: John's Medical Clinic
    - Tier: tier3
    - Included Seats: 1
  ✅ Would create organization

[2/5] Processing: sara@hospital.com (tier5)...
  [DRY RUN] Would create organization for sara@hospital.com:
    - Organization: Sara's Workspace
    - Tier: tier5
    - Included Seats: 5
  ✅ Would create organization
...
```

### Step 2: Review Dry Run Results

Examine the output carefully:

1. **Check eligible user count**: Does it match expectations?
2. **Review organization names**: Are they appropriate?
3. **Verify seat limits**: Correct for each tier?
4. **Look for errors**: Any pre-existing conditions?

### Step 3: Run Actual Migration

If the dry run looks good, run the actual migration:

```bash
# Using npm script
npm run migrate:organizations

# Or directly with ts-node
npx tsx scripts/migrate-to-organizations.ts
```

**⚠️ WARNING**: This makes actual database changes!

### Step 4: Verify Results

After migration completes, verify the results:

```bash
# Check Prisma database
npx prisma studio

# Check Supabase
npm run supabase:studio

# Query organization count
psql -h localhost -p 5432 -U postgres -d mawidi -c "SELECT COUNT(*) FROM organizations;"

# Check organization members
psql -h localhost -p 5432 -U postgres -d mawidi -c "SELECT o.name, u.email, om.role FROM organizations o JOIN organization_members om ON o.id = om.organization_id JOIN users u ON om.user_id = u.id;"
```

## Migration Output

The migration script provides detailed progress and summary information:

### Progress Indicators

- `✅` Success - Organization created
- `⏭️` Skipped - Organization already exists (idempotent)
- `❌` Failed - Error occurred

### Summary Report

```
======================================================================
📊 MIGRATION SUMMARY
======================================================================

Total users processed: 5
✅ Organizations created: 4
⏭️  Skipped (already exist): 1
❌ Failed: 0

✨ Migration completed successfully!
📝 Next steps:
   1. Verify organizations in database
   2. Test multi-staff login
   3. Test team invitations
```

## Idempotency

The migration is **idempotent** - it's safe to run multiple times:

- If an organization already exists for a user, it will be **skipped**
- No duplicate organizations will be created
- Existing data won't be modified

## Troubleshooting

### No Eligible Users Found

**Issue**: Script reports 0 eligible users

**Solutions**:
1. Check users have role = 'CUSTOMER'
2. Verify subscriptions are 'active' or 'trialing'
3. Confirm tiers are tier3, tier4, or tier5
4. Run query to investigate:
   ```sql
   SELECT u.email, u.role, s.status, s.tierId
   FROM users u
   LEFT JOIN subscriptions s ON u.id = s.userId
   WHERE u.role = 'CUSTOMER';
   ```

### Migration Fails for Specific User

**Issue**: User migration fails with error

**Common Causes**:
1. **Missing subscription**: User has no active subscription
2. **Invalid tier**: Subscription tier doesn't support multi-staff
3. **Database constraint**: Existing data conflicts
4. **Network issue**: Supabase sync failed

**Solution**: Check error details in output, fix underlying issue, re-run migration

### Organization Already Exists

**Issue**: Script skips user saying organization exists

**This is normal** if:
- You're re-running the migration
- User was manually added to organization
- Previous migration partially completed

**To verify**:
```sql
SELECT * FROM organizations WHERE owner_id = 'USER_ID';
```

## Rollback

If you need to rollback the migration:

```sql
-- Delete all organization members
DELETE FROM organization_members;

-- Delete all organizations
DELETE FROM organizations;

-- Or specific organization
DELETE FROM organization_members WHERE organization_id = 'ORG_ID';
DELETE FROM organizations WHERE id = 'ORG_ID';
```

**Note**: Also delete from Supabase:
```sql
-- In Supabase SQL Editor
DELETE FROM organization_members;
DELETE FROM organizations;
```

## Next Steps After Migration

1. **Test Multi-Staff Login**:
   - Log in as a migrated user
   - Navigate to Team Management tab
   - Verify seat configuration displays correctly

2. **Test Invitations**:
   - Send invitation to a new team member
   - Accept invitation and verify account creation
   - Check role permissions

3. **Monitor Logs**:
   ```bash
   # Check application logs
   docker-compose logs -f mawidi-dev

   # Check for sync errors
   grep "organization" logs/app.log
   ```

4. **Update Users**:
   - Send email notification about new multi-staff feature
   - Provide documentation on inviting team members
   - Explain role hierarchy (OWNER > ADMIN > STAFF)

## Support

If you encounter issues:

1. **Check Logs**: Review migration output and application logs
2. **Verify Schema**: Run `npm run check:schema`
3. **Test Manually**: Try creating organization via API
4. **Restore Backup**: If needed, restore from backup and investigate

## Related Documentation

- `/Users/Asim/Desktop/mawidi_codex/mawidi-site/lib/types/organization.types.ts` - Type definitions
- `/Users/Asim/Desktop/mawidi_codex/mawidi-site/lib/services/organization.service.ts` - Service layer
- `/Users/Asim/Desktop/mawidi_codex/mawidi-site/lib/dual-database.ts` - Database sync utilities

## Technical Details

### What the Script Does

1. **Queries eligible users** from Prisma:
   ```typescript
   WHERE role = 'CUSTOMER'
   AND subscriptions.status IN ['active', 'trialing']
   AND subscriptions.tierId IN ['tier3', 'tier4', 'tier5']
   ```

2. **For each user**:
   - Checks if organization exists (skip if yes)
   - Generates organization name from `companyName` or creates default
   - Calculates `includedSeats` from tier configuration
   - Creates organization in transaction
   - Creates organization_member record with OWNER role
   - Syncs to Supabase via dual-database utilities

3. **Reports results**: Success, skipped, failed counts

### Data Created

For each migrated user, the script creates:

**organizations table:**
```typescript
{
  id: 'cuid',
  name: string,           // from companyName or generated
  ownerId: string,        // user ID
  stripeCustomerId: string | null,
  includedSeats: number,  // from TIER_SEAT_LIMITS
  purchasedSeats: 0,
  createdAt: DateTime,
  updatedAt: DateTime
}
```

**organization_members table:**
```typescript
{
  id: 'cuid',
  organizationId: string,
  userId: string,
  role: 'OWNER',
  joinedAt: DateTime,
  invitedBy: null,
  lastActiveAt: null
}
```

### Performance

- Processes users sequentially with 100ms delay between each
- Uses database transactions for atomicity
- Non-blocking Supabase sync (won't fail if Supabase unavailable)
- Typical performance: ~1 user per second

For 100 users: ~2 minutes
For 1000 users: ~20 minutes
