# 部署修复说明

## 问题解决

已修复在推送到现有环境时遇到的外键约束错误：

```
Error: insert or update on table "users" violates foreign key constraint "users_subscriptionPlanId_fkey"
```

## 解决方案

通过修改种子脚本 (`prisma/seed.ts`)，确保在数据库推送时：

1. **创建必需的套餐**：使用 `upsert` 确保 'free' 和 'pro' 套餐存在
2. **修复用户数据**：自动修复无效的套餐引用
3. **验证数据完整性**：确保所有用户都有有效的套餐关联

## 使用方法

现在可以直接使用现有命令进行部署：

```bash
npm run db:push
```

这个命令会：
1. 推送数据库架构 (`prisma db push`)
2. 运行种子脚本 (`npm run db:seed`)
3. 自动处理数据修复

## 种子脚本改进

### 主要变更

1. **使用 upsert 而不是 create**
   ```typescript
   // 之前：如果套餐存在就跳过
   if (existingPlans > 0) return
   
   // 现在：确保必需套餐存在
   await prisma.subscriptionPlan.upsert({
     where: { id: 'free' },
     update: { name: 'free', isActive: true },
     create: { /* 完整套餐数据 */ }
   })
   ```

2. **智能用户数据修复**
   ```typescript
   // 检查所有用户的套餐引用
   const validPlanIds = ['free', 'pro']
   const usersToUpdate = users.filter(user => {
     const hasValidSubscribePlan = validPlanIds.includes(user.subscribePlan)
     const hasValidSubscriptionPlanId = validPlanIds.includes(user.subscriptionPlanId)
     return !hasValidSubscribePlan || !hasValidSubscriptionPlanId
   })
   
   // 修复无效引用
   for (const user of usersToUpdate) {
     await prisma.user.update({
       where: { id: user.id },
       data: {
         subscribePlan: validPlanIds.includes(user.subscribePlan) ? user.subscribePlan : 'free',
         subscriptionPlanId: validPlanIds.includes(user.subscribePlan) ? user.subscribePlan : 'free'
       }
     })
   }
   ```

### 执行流程

1. **创建/更新套餐**：确保 'free' 和 'pro' 套餐存在
2. **检查用户数据**：找出有无效套餐引用的用户
3. **修复用户数据**：将无效引用改为 'free'
4. **验证结果**：确认所有数据都是一致的

## 测试验证

种子脚本运行结果：
```
🌱 Starting database seeding...
📦 Ensuring essential subscription plans exist...
✅ Created subscription plan: Free Plan
✅ Created subscription plan: Pro Plan
👥 Updating existing users...
👥 No users need subscription plan updates
📊 Seeding completed:
   • 2 subscription plans created
   • 2 users have valid plan associations
🎉 Database seeding finished successfully!
```

## 部署到现有环境

现在可以安全地部署到任何现有环境：

1. **本地测试**：
   ```bash
   npm run db:push
   npm run build
   ```

2. **生产部署**：
   ```bash
   npm run db:push
   npm start
   ```

## 优势

1. **无需额外脚本**：使用现有的 `npm run db:push` 命令
2. **自动修复**：种子脚本自动处理数据不一致问题
3. **向后兼容**：不会破坏现有数据
4. **幂等操作**：可以重复运行而不会出错

## 注意事项

1. **Stripe 配置**：部署后需要设置 Pro 套餐的 Stripe 价格 ID
   ```sql
   UPDATE subscription_plans 
   SET "stripePriceId" = 'price_your_stripe_price_id' 
   WHERE name = 'pro';
   ```

2. **数据验证**：部署后验证定价页面和订阅功能
3. **备份建议**：在生产环境部署前建议备份数据库

## 故障排除

如果仍然遇到问题：

1. **检查套餐**：
   ```sql
   SELECT id, name, "isActive" FROM subscription_plans;
   ```

2. **检查用户**：
   ```sql
   SELECT "subscribePlan", COUNT(*) FROM users GROUP BY "subscribePlan";
   ```

3. **手动修复**：
   ```sql
   UPDATE users SET "subscribePlan" = 'free' 
   WHERE "subscribePlan" NOT IN ('free', 'pro');
   ```
