---
description: 多租户数据隔离规范（所有涉及数据库操作的代码必须遵守）
globs:
alwaysApply: true
---

# 多租户处理规范

⚠️ **极其重要**：所有业务数据查询必须包含 `tenantId` 条件！

## 核心原则

### 1. 数据库查询

- **必须**：所有业务表查询必须包含 `tenantId` 条件
- 超级租户（`isSuper = 1`）可以访问所有租户数据

```typescript
// ✅ 正确示例
const users = await this.prisma.user.findMany({
  where: {
    tenantId,
    validState: 1,
  },
});

// ❌ 错误示例 - 缺少 tenantId
const users = await this.prisma.user.findMany({
  where: {
    validState: 1,
  },
});
```

### 2. 获取租户ID

在控制器中使用 `@CurrentTenantId()` 装饰器：

```typescript
@Get()
async findAll(@CurrentTenantId() tenantId: number) {
  return this.service.findAll(tenantId);
}
```

### 3. 创建数据

创建数据时自动设置 `tenantId`：

```typescript
async create(createDto: CreateDto, tenantId: number) {
  return this.prisma.model.create({
    data: {
      ...createDto,
      tenantId,
    },
  });
}
```

### 4. 更新/删除数据

更新或删除前验证数据属于当前租户：

```typescript
async update(id: number, updateDto: UpdateDto, tenantId: number) {
  // 先验证数据属于当前租户
  const existing = await this.prisma.model.findFirst({
    where: { id, tenantId },
  });

  if (!existing) {
    throw new NotFoundException('数据不存在或不属于当前租户');
  }

  return this.prisma.model.update({
    where: { id },
    data: updateDto,
  });
}
```

## 数据库表设计

所有业务表必须包含：

- `tenantId`: Int - 租户ID（必填）
- `creator`: Int? - 创建人ID
- `modifier`: Int? - 修改人ID
- `createTime`: DateTime @default(now())
- `modifyTime`: DateTime @updatedAt
- `validState`: Int @default(1) - 有效状态（1-有效，2-失效）

## 审查清单

在代码审查时，重点检查：

- [ ] 所有 `findMany`、`findFirst`、`findUnique` 包含 `tenantId` 条件
- [ ] 创建操作设置了 `tenantId`
- [ ] 更新/删除操作验证了 `tenantId`
- [ ] 新的 Prisma 模型包含了 `tenantId` 字段
