# 好友申请与待办消息功能设计

**Date:** 2026-02-28
**Status:** Approved

## 1. 数据模型

### Friendship 表 (已存在)

| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| user_low_id | UUID | 用户A ID (固定排序小值) |
| user_high_id | UUID | 用户B ID (固定排序大值) |
| initiator_id | UUID? | 发起请求者 |
| status | VARCHAR(20) | pending/accepted/blocked/declined/canceled |
| requested_at | TIMESTAMP? | 请求时间 |
| accepted_at | TIMESTAMP? | 接受时间 |
| blocked_by | UUID? | 被谁屏蔽 |
| created_by/updated_by | UUID? | 审计字段 |

### InboxMessage 表 (复用)

| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| recipient_id | UUID | 接收方 |
| sender_id | UUID? | 发送方 |
| message_type | VARCHAR(20) | FRIEND_REQUEST / CALENDAR / SYSTEM / GROUP |
| friendship_id | UUID? | 关联 Friendship |
| content | TEXT? | 附加消息 |
| is_read | BOOLEAN | 已读状态 |
| status | VARCHAR(20) | pending/accepted/rejected/dismissed |

## 2. API 设计

| 方法 | 路径 | 功能 |
|------|------|------|
| POST | /friends/requests | 发送好友请求 |
| GET | /friends/requests/outgoing | 获取我发出的请求 |
| GET | /friends/requests/inbox | 获取收到的好友请求 |
| POST | /friends/requests/{id}/accept | 接受好友请求 |
| POST | /friends/requests/{id}/decline | 拒绝好友请求 |
| DELETE | /friends/requests/{id} | 取消我的请求 |
| GET | /friends | 获取好友列表 |
| DELETE | /friends/{id} | 删除好友 |

## 3. 业务逻辑流程

### 3.1 发送好友请求

```
1. 验证 target_user_id != current_user_id
2. 检查是否已存在 Friendship 记录
   - 已 accepted: 返回 409
   - 已 pending: 返回 409
   - 已 blocked: 返回 403
3. 创建 Friendship (status=pending, initiator_id=current_user)
4. 创建 InboxMessage (message_type=FRIEND_REQUEST, recipient=target_user)
5. 提交事务
```

### 3.2 接受好友请求

```
1. 查询 Friendship 和 InboxMessage
2. 验证 current_user == recipient
3. 更新 Friendship (status=accepted, accepted_at=now)
4. 更新 InboxMessage (status=accepted)
5. 提交事务
```

### 3.3 拒绝好友请求

```
1. 查询 Friendship 和 InboxMessage
2. 验证 current_user == recipient
3. 更新 Friendship (status=declined)
4. 更新 InboxMessage (status=rejected)
5. 提交事务
```

### 3.4 获取好友列表

```
查询 Friendship WHERE (user_low_id=current OR user_high_id=current) AND status=accepted
```

## 4. 响应 Schema

### FriendRequestResponse
```python
{
    "id": "uuid",
    "sender": {"id": "uuid", "username": "string", "avatar_url": "string?"},
    "recipient": {"id": "uuid", "username": "string", "avatar_url": "string?"},
    "content": "string?",
    "status": "pending",
    "created_at": "datetime"
}
```

### FriendResponse
```python
{
    "id": "uuid",
    "friend": {"id": "uuid", "username": "string", "avatar_url": "string?"},
    "status": "accepted",
    "created_at": "datetime",
    "accepted_at": "datetime?"
}
```

## 5. 边界处理

| 场景 | 状态码 | 响应 |
|------|--------|------|
| 对自己发送请求 | 400 | Cannot send friend request to yourself |
| 已是好友 | 409 | Already friends |
| 已有待处理请求 | 409 | Friend request already exists |
| 被对方屏蔽 | 403 | Blocked by user |
| 请求不存在 | 404 | Friend request not found |
| 无权限操作 | 403 | Not authorized |

## 6. 测试用例

### 单元测试
- FriendshipService 业务逻辑
- 状态转换验证
- 边界条件处理

### 集成测试
- POST /friends/requests - 成功/失败场景
- GET /friends/requests/inbox - 返回正确列表
- POST /friends/requests/{id}/accept - 状态更新
- DELETE /friends/{id} - 删除好友
