216 lines
6.7 KiB
Markdown
216 lines
6.7 KiB
Markdown
# Persona Data Table Migration Guide
|
|
|
|
## Overview
|
|
This guide explains how to create the `persona_data` table for storing Step 4 (Persona Generation) data from the onboarding flow.
|
|
|
|
## Background
|
|
The `persona_data` table was missing from the database schema, causing Step 4 onboarding data to only be saved to JSON files instead of the database. This migration adds the required table with proper user isolation.
|
|
|
|
## Migration Methods
|
|
|
|
### Method 1: Automatic Migration (Recommended)
|
|
The easiest way is to restart your backend server. The table will be created automatically when the application starts.
|
|
|
|
```bash
|
|
# Stop the backend if running (Ctrl+C)
|
|
# Then restart it:
|
|
python backend/start_alwrity_backend.py --dev
|
|
```
|
|
|
|
**How it works:**
|
|
- The `init_database()` function in `backend/services/database.py` (line 69) calls `OnboardingBase.metadata.create_all(bind=engine)`
|
|
- This automatically creates all missing tables defined in the `OnboardingBase` models
|
|
- Since we added the `PersonaData` model, it will be created on startup
|
|
|
|
### Method 2: Manual Migration Script
|
|
If you prefer to run the migration manually without restarting the backend:
|
|
|
|
```bash
|
|
# From the project root directory:
|
|
python backend/scripts/create_persona_data_table.py
|
|
```
|
|
|
|
**What this script does:**
|
|
1. Checks if the `persona_data` table already exists
|
|
2. Creates the table if it doesn't exist
|
|
3. Verifies the table was created successfully
|
|
4. Shows the table structure (columns and types)
|
|
5. Lists all onboarding-related tables and their status
|
|
|
|
### Method 3: SQL Migration (Production/Manual)
|
|
For production environments or manual database management:
|
|
|
|
```bash
|
|
# Connect to your PostgreSQL database and run:
|
|
psql -U your_username -d your_database -f backend/database/migrations/add_persona_data_table.sql
|
|
```
|
|
|
|
**Or using psql command:**
|
|
```sql
|
|
-- Connect to your database
|
|
\c your_database
|
|
|
|
-- Run the migration
|
|
\i backend/database/migrations/add_persona_data_table.sql
|
|
|
|
-- Verify the table was created
|
|
\dt persona_data
|
|
\d persona_data
|
|
```
|
|
|
|
## Table Structure
|
|
|
|
The `persona_data` table includes:
|
|
|
|
| Column | Type | Description |
|
|
|--------|------|-------------|
|
|
| `id` | SERIAL | Primary key |
|
|
| `session_id` | INTEGER | Foreign key to `onboarding_sessions.id` |
|
|
| `core_persona` | JSONB | Core persona data (demographics, psychographics, etc.) |
|
|
| `platform_personas` | JSONB | Platform-specific personas (LinkedIn, Twitter, etc.) |
|
|
| `quality_metrics` | JSONB | Quality assessment metrics |
|
|
| `selected_platforms` | JSONB | Array of selected platforms |
|
|
| `created_at` | TIMESTAMP | When the record was created |
|
|
| `updated_at` | TIMESTAMP | When the record was last updated |
|
|
|
|
**Indexes:**
|
|
- `idx_persona_data_session_id` - For efficient session lookups
|
|
- `idx_persona_data_created_at` - For time-based queries
|
|
|
|
**Constraints:**
|
|
- Foreign key to `onboarding_sessions.id` with `ON DELETE CASCADE`
|
|
|
|
## Verification
|
|
|
|
After running the migration, verify it was successful:
|
|
|
|
### Using Python:
|
|
```python
|
|
from services.database import engine
|
|
from sqlalchemy import inspect
|
|
|
|
inspector = inspect(engine)
|
|
tables = inspector.get_table_names()
|
|
|
|
if 'persona_data' in tables:
|
|
print("✅ persona_data table exists")
|
|
columns = inspector.get_columns('persona_data')
|
|
for col in columns:
|
|
print(f" - {col['name']}: {col['type']}")
|
|
else:
|
|
print("❌ persona_data table not found")
|
|
```
|
|
|
|
### Using SQL:
|
|
```sql
|
|
-- Check if table exists
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.tables
|
|
WHERE table_name = 'persona_data'
|
|
);
|
|
|
|
-- Show table structure
|
|
\d persona_data
|
|
```
|
|
|
|
### Using the Backend Logs:
|
|
After restarting the backend, look for this log message:
|
|
```
|
|
Database initialized successfully with all models including subscription system and business info
|
|
```
|
|
|
|
Then, when a user completes Step 4, you should see:
|
|
```
|
|
✅ DATABASE: Persona data saved to database for user user_xxxxx
|
|
```
|
|
|
|
## Expected Behavior After Migration
|
|
|
|
Once the table is created and the backend is running with the updated code:
|
|
|
|
1. **Step 4 Completion:**
|
|
- Persona data (corePersona, platformPersonas, qualityMetrics, selectedPlatforms) is saved to the database
|
|
- Database logs confirm: `✅ DATABASE: Persona data saved to database for user {user_id}`
|
|
|
|
2. **User Isolation:**
|
|
- Each user's persona data is stored separately using their `user_id`
|
|
- Data is linked to the user's onboarding session
|
|
|
|
3. **Data Persistence:**
|
|
- Persona data is no longer lost when JSON files are deleted
|
|
- Data survives backend restarts
|
|
- Data is accessible across different sessions
|
|
|
|
## Troubleshooting
|
|
|
|
### Table Already Exists Error
|
|
If you see "table already exists" errors:
|
|
- This is normal! It means the table was already created
|
|
- The migration scripts use `CREATE TABLE IF NOT EXISTS` to handle this
|
|
- No action needed
|
|
|
|
### Permission Denied
|
|
If you get permission errors:
|
|
```
|
|
ERROR: permission denied for schema public
|
|
```
|
|
**Solution:** Ensure your database user has CREATE TABLE permissions:
|
|
```sql
|
|
GRANT CREATE ON SCHEMA public TO your_database_user;
|
|
```
|
|
|
|
### Foreign Key Constraint Fails
|
|
If the `onboarding_sessions` table doesn't exist:
|
|
1. Run the full database initialization first:
|
|
```python
|
|
from services.database import init_database
|
|
init_database()
|
|
```
|
|
2. Then create the `persona_data` table
|
|
|
|
### Missing Database Connection
|
|
If you see "database connection" errors:
|
|
1. Check your `DATABASE_URL` environment variable
|
|
2. Ensure PostgreSQL/SQLite is running
|
|
3. Verify database credentials
|
|
|
|
## Rollback (If Needed)
|
|
|
|
To remove the `persona_data` table:
|
|
|
|
```sql
|
|
DROP TABLE IF EXISTS persona_data CASCADE;
|
|
```
|
|
|
|
**Warning:** This will delete all persona data. Use with caution!
|
|
|
|
## Related Files
|
|
|
|
- **Model:** `backend/models/onboarding.py` - `PersonaData` class (lines 149-183)
|
|
- **Service:** `backend/services/onboarding_database_service.py` - `save_persona_data()` method (lines 298-338)
|
|
- **Migration:** `backend/database/migrations/add_persona_data_table.sql`
|
|
- **Script:** `backend/scripts/create_persona_data_table.py`
|
|
- **Database Init:** `backend/services/database.py` - `init_database()` function (line 63-80)
|
|
|
|
## Summary
|
|
|
|
**Recommended approach for local development:**
|
|
```bash
|
|
# Just restart the backend - the table will be created automatically!
|
|
python backend/start_alwrity_backend.py --dev
|
|
```
|
|
|
|
**For production deployment:**
|
|
- The table will be created automatically on first deployment
|
|
- Or run the SQL migration manually before deployment
|
|
- No downtime required - the migration is additive only
|
|
|
|
## Questions?
|
|
|
|
If you encounter issues:
|
|
1. Check the backend logs for detailed error messages
|
|
2. Verify all onboarding tables exist using the verification script
|
|
3. Ensure your database user has proper permissions
|
|
4. Check that the `PersonaData` model is imported correctly in `backend/services/onboarding_database_service.py`
|
|
|