# Multi-Tenancy Deployment Guide

## Pre-Deployment Checklist

- [ ] Code review completed
- [ ] All tests passing
- [ ] Database backup created
- [ ] Rollback plan prepared
- [ ] Downtime window scheduled (if needed)

## Deployment Steps

### Step 1: Backup Database

```bash
# SQL Server backup example
BACKUP DATABASE PowderCoatingDb
TO DISK = 'C:\Backups\PowderCoatingDb_PreMultiTenancy.bak'
WITH FORMAT, COMPRESSION;
```

### Step 2: Build Solution

```bash
cd Y:\PCC\PowderCoatingApp
dotnet build
```

Ensure no build errors.

### Step 3: Review Migration

Check the migration file to understand what will happen:
```bash
# View the migration
cat src/PowderCoating.Infrastructure/Migrations/20260205220415_AddMultiTenancy.cs
```

The migration will:
- Create `Companies` table
- Add `CompanyId` columns to all entities
- Add `CompanyRole` to `AspNetUsers`
- Create foreign keys and indexes

### Step 4: Apply Migration

```bash
cd src/PowderCoating.Web
dotnet ef database update --project ../PowderCoating.Infrastructure
```

**Expected output:**
```
Applying migration '20260205220415_AddMultiTenancy'.
Done.
```

### Step 5: Run Seed Data

The seed data will run automatically on application startup and will:
- Create default "Demo Company"
- Create SuperAdmin user
- Create CompanyAdmin user
- Create Manager user

Start the application:
```bash
dotnet run --project src/PowderCoating.Web
```

Watch the logs for:
```
Company 'Demo Company' created
User 'superadmin@powdercoating.com' created
User 'admin@demo.com' created
User 'manager@demo.com' created
```

### Step 6: Verify Migration Success

Connect to the database and verify:

```sql
-- Check Companies table exists
SELECT * FROM Companies;

-- Check CompanyId added to entities
SELECT TOP 5 Id, CompanyId FROM Customers;
SELECT TOP 5 Id, CompanyId FROM Jobs;

-- Check ApplicationUser has CompanyId
SELECT TOP 5 Id, Email, CompanyId, CompanyRole FROM AspNetUsers;

-- Verify foreign keys
SELECT
    fk.name AS ForeignKeyName,
    OBJECT_NAME(fk.parent_object_id) AS TableName,
    COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS ColumnName,
    OBJECT_NAME (fk.referenced_object_id) AS ReferencedTableName
FROM
    sys.foreign_keys AS fk
    INNER JOIN sys.foreign_key_columns AS fkc
        ON fk.object_id = fkc.constraint_object_id
WHERE
    OBJECT_NAME(fk.referenced_object_id) = 'Companies';
```

### Step 7: Test Login

Test each user account:

1. **SuperAdmin Login**
   - URL: https://localhost:5001/Identity/Account/Login
   - Email: superadmin@powdercoating.com
   - Password: SuperAdmin123!
   - Should see: "Companies" menu in Platform Management

2. **Company Admin Login**
   - URL: https://localhost:5001/Identity/Account/Login
   - Email: admin@demo.com
   - Password: CompanyAdmin123!
   - Should see: "Manage Users" menu in Company Settings
   - Should see: "Demo Company" badge in header

3. **Manager Login**
   - URL: https://localhost:5001/Identity/Account/Login
   - Email: manager@demo.com
   - Password: Manager123!
   - Should see: "Demo Company" badge in header
   - Should NOT see: "Manage Users" menu

### Step 8: Verify Data Isolation

1. As **SuperAdmin**, create a second company:
   - Navigate to Companies → Create New Company
   - Company Name: "Test Company"
   - Create admin user for Test Company

2. Login as **Test Company Admin**
   - Verify you only see Test Company data
   - Create a test customer

3. Login as **Demo Company Admin**
   - Verify you CANNOT see Test Company customer
   - Verify you only see Demo Company data

4. Login as **SuperAdmin**
   - Navigate to Customers
   - Should see customers from BOTH companies

## Post-Deployment Verification

### Functional Tests

- [ ] SuperAdmin can create new companies
- [ ] SuperAdmin can see all companies' data
- [ ] Company Admin can create users in their company
- [ ] Company Admin cannot see other companies' data
- [ ] Users can only see data from their own company
- [ ] New entities automatically get CompanyId assigned
- [ ] Query filters work correctly

### Performance Tests

- [ ] Page load times are acceptable
- [ ] No N+1 query issues
- [ ] Indexes are being used (check query plans)

### Security Tests

- [ ] Cannot access other company's data by changing IDs in URL
- [ ] Authorization policies enforce correctly
- [ ] Query filters cannot be bypassed by regular users

## Troubleshooting

### Issue: Migration Fails

**Error: Foreign key constraint conflicts**

This means existing data has CompanyId=0 which doesn't exist.

**Solution:**
```sql
-- Check if default company exists
SELECT * FROM Companies WHERE Id = 1;

-- If no company exists, seed data didn't run
-- Run application to trigger seed, OR manually:
INSERT INTO Companies (CompanyName, CompanyCode, PrimaryContactName, PrimaryContactEmail,
    IsActive, SubscriptionStartDate, CreatedAt, CompanyId)
VALUES ('Demo Company', 'DEMO', 'Admin', 'admin@demo.com',
    1, GETUTCDATE(), GETUTCDATE(), 0);

-- Update CompanyId to self-reference
UPDATE Companies SET CompanyId = Id WHERE Id = 1;

-- Update existing data
UPDATE Customers SET CompanyId = 1 WHERE CompanyId = 0;
UPDATE Jobs SET CompanyId = 1 WHERE CompanyId = 0;
-- ... repeat for all entities
```

### Issue: Users Can't Login

**Error: "Unable to determine your company"**

This means the user's CompanyId is not set or CompanyId claim is missing.

**Solution:**
```sql
-- Check user's CompanyId
SELECT Id, Email, CompanyId FROM AspNetUsers WHERE Email = 'user@example.com';

-- Update if needed
UPDATE AspNetUsers SET CompanyId = 1 WHERE CompanyId = 0 OR CompanyId IS NULL;
```

Then ensure user re-logs in to get fresh claims.

### Issue: Seeing Other Company's Data

This means query filters aren't working.

**Check:**
1. Is `ITenantContext` registered in DI?
2. Is `ApplicationDbContext` receiving `IHttpContextAccessor` and `IServiceProvider`?
3. Are query filters being applied in `OnModelCreating`?
4. Is the user authenticated and has CompanyId claim?

## Rollback Procedure

If critical issues occur:

```bash
# Rollback migration
cd src/PowderCoating.Web
dotnet ef database update 20260205163837_InitialCreate --project ../PowderCoating.Infrastructure

# Restore database backup
RESTORE DATABASE PowderCoatingDb
FROM DISK = 'C:\Backups\PowderCoatingDb_PreMultiTenancy.bak'
WITH REPLACE;

# Revert code changes
git revert <commit-hash>
```

## Support Contacts

- Lead Developer: [Your Name]
- Database Admin: [DBA Name]
- DevOps: [DevOps Contact]

## Post-Deployment Tasks

- [ ] Monitor application logs for errors
- [ ] Monitor database performance
- [ ] Update documentation
- [ ] Train users on new multi-tenancy features
- [ ] Schedule follow-up review (1 week)
