# 商户管理模块 - API 文档

## 目录
- [商户管理 API](#商户管理-api)
  - [查询商户列表](#1-查询商户列表)
  - [创建商户](#2-创建商户)
  - [更新商户](#3-更新商户)
  - [删除商户](#4-删除商户)
- [商户账号管理 API](#商户账号管理-api)
  - [查询商户账号列表](#1-查询商户账号列表)
  - [创建商户账号](#2-创建商户账号)
  - [更新商户账号](#3-更新商户账号)
  - [重置账号密码](#4-重置账号密码)
  - [启用/禁用账号](#5-启用禁用账号)
- [数据模型](#数据模型)
- [错误码](#错误码)

---

## 商户管理 API

### 1. 查询商户列表

获取商户列表，支持分页、筛选和搜索。

**请求**

```http
GET /api/admin/shops
```

**查询参数**

| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| page | integer | 否 | 1 | 页码，从 1 开始 |
| size | integer | 否 | 20 | 每页数量，最大 100 |
| name | string | 否 | - | 商户名称（模糊搜索） |
| shop_code | string | 否 | - | 商户编码（精确匹配） |
| status | integer | 否 | - | 状态筛选（1=正常，2=禁用） |
| level | integer | 否 | - | 等级筛选（1-7） |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "items": [
      {
        "id": 1,
        "name": "测试商户",
        "shop_code": "SHOP001",
        "contact": "张三",
        "phone": "13800138000",
        "province": "广东省",
        "city": "深圳市",
        "district": "南山区",
        "address": "科技园",
        "level": 1,
        "status": 1,
        "created_at": "2024-01-01T10:00:00Z",
        "updated_at": "2024-01-01T10:00:00Z"
      }
    ],
    "total": 1,
    "page": 1,
    "size": 20
  },
  "timestamp": 1704096000
}
```

**状态码**

| HTTP 状态码 | 说明 |
|-------------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 |
| 500 | 服务器错误 |

---

### 2. 创建商户

创建新商户，同时创建初始坐席账号。

**请求**

```http
POST /api/admin/shops
Content-Type: application/json
```

**请求体**

```json
{
  "name": "测试商户",
  "shop_code": "SHOP001",
  "contact": "张三",
  "phone": "13800138000",
  "province": "广东省",
  "city": "深圳市",
  "district": "南山区",
  "address": "科技园",
  "level": 1,
  "status": 1,
  "init_username": "admin",
  "init_phone": "13800138000",
  "init_password": "password123"
}
```

**字段说明**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 商户名称 |
| shop_code | string | 是 | 商户编码，全局唯一 |
| contact | string | 否 | 联系人 |
| phone | string | 否 | 联系电话 |
| province | string | 否 | 省份 |
| city | string | 否 | 城市 |
| district | string | 否 | 区域 |
| address | string | 否 | 详细地址 |
| level | integer | 是 | 商户等级（1-7） |
| status | integer | 是 | 状态（1=正常，2=禁用） |
| init_username | string | 是 | 初始账号用户名 |
| init_phone | string | 是 | 初始账号手机号 |
| init_password | string | 是 | 初始账号密码 |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "id": 1,
    "name": "测试商户",
    "shop_code": "SHOP001",
    "contact": "张三",
    "phone": "13800138000",
    "province": "广东省",
    "city": "深圳市",
    "district": "南山区",
    "address": "科技园",
    "level": 1,
    "status": 1,
    "created_at": "2024-01-01T10:00:00Z",
    "updated_at": "2024-01-01T10:00:00Z"
  },
  "timestamp": 1704096000
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | - | 请求参数错误 |
| 400 | 40002 | 商户编码已存在 |
| 400 | 40004 | 商户等级无效 |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

**业务规则**

1. 商户编码（shop_code）必须全局唯一
2. 等级（level）必须在 1-7 范围内
3. 创建商户的同时会自动创建一个初始坐席账号（UserType=3）
4. 初始账号的密码会使用 bcrypt 加密存储
5. 初始账号的 shop_id 会自动关联到新创建的商户

---

### 3. 更新商户

更新商户基本信息。

**请求**

```http
PUT /api/admin/shops/:id
Content-Type: application/json
```

**路径参数**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | integer | 是 | 商户ID |

**请求体**

```json
{
  "name": "更新后的商户名称",
  "shop_code": "SHOP001",
  "contact": "李四",
  "phone": "13900139000",
  "province": "广东省",
  "city": "深圳市",
  "district": "福田区",
  "address": "中心区",
  "level": 2,
  "status": 1
}
```

**字段说明**

所有字段均为可选，但至少需要提供一个字段进行更新。

| 字段 | 类型 | 说明 |
|------|------|------|
| name | string | 商户名称 |
| shop_code | string | 商户编码 |
| contact | string | 联系人 |
| phone | string | 联系电话 |
| province | string | 省份 |
| city | string | 城市 |
| district | string | 区域 |
| address | string | 详细地址 |
| level | integer | 商户等级（1-7） |
| status | integer | 状态（1=正常，2=禁用） |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "id": 1,
    "name": "更新后的商户名称",
    "shop_code": "SHOP001",
    "contact": "李四",
    "phone": "13900139000",
    "province": "广东省",
    "city": "深圳市",
    "district": "福田区",
    "address": "中心区",
    "level": 2,
    "status": 1,
    "created_at": "2024-01-01T10:00:00Z",
    "updated_at": "2024-01-01T11:00:00Z"
  },
  "timestamp": 1704099600
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | - | 请求参数错误 |
| 400 | 40001 | 商户不存在 |
| 400 | 40002 | 商户编码已存在（修改编码时） |
| 400 | 40004 | 商户等级无效 |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

---

### 4. 删除商户

软删除商户，同时批量禁用所有关联的商户账号。

**请求**

```http
DELETE /api/admin/shops/:id
```

**路径参数**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | integer | 是 | 商户ID |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": null,
  "timestamp": 1704096000
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | 40001 | 商户不存在 |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

**业务规则**

1. 删除商户时会进行软删除（设置 deleted_at）
2. 所有关联的商户账号会被批量设置为禁用状态（status=2）
3. 账号不会被物理删除，只是被禁用
4. 删除操作不可逆（除非手动修改数据库）

---

## 商户账号管理 API

### 1. 查询商户账号列表

获取商户账号列表，支持分页、筛选和搜索。

**请求**

```http
GET /api/admin/shop-accounts
```

**查询参数**

| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| page | integer | 否 | 1 | 页码，从 1 开始 |
| size | integer | 否 | 20 | 每页数量，最大 100 |
| shop_id | integer | 否 | - | 商户ID筛选 |
| status | integer | 否 | - | 状态筛选（1=正常，2=禁用） |
| username | string | 否 | - | 用户名（模糊搜索） |
| phone | string | 否 | - | 手机号（模糊搜索） |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "items": [
      {
        "id": 1,
        "username": "admin",
        "phone": "13800138000",
        "user_type": 3,
        "status": 1,
        "shop_id": 1,
        "shop_name": "测试商户",
        "created_at": "2024-01-01T10:00:00Z",
        "updated_at": "2024-01-01T10:00:00Z"
      }
    ],
    "total": 1,
    "page": 1,
    "size": 20
  },
  "timestamp": 1704096000
}
```

**状态码**

| HTTP 状态码 | 说明 |
|-------------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 |
| 500 | 服务器错误 |

---

### 2. 创建商户账号

为指定商户创建新的坐席账号。

**请求**

```http
POST /api/admin/shop-accounts
Content-Type: application/json
```

**请求体**

```json
{
  "shop_id": 1,
  "username": "agent01",
  "phone": "13800138001",
  "password": "password123"
}
```

**字段说明**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| shop_id | integer | 是 | 商户ID |
| username | string | 是 | 用户名 |
| phone | string | 是 | 手机号 |
| password | string | 是 | 密码 |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "id": 2,
    "username": "agent01",
    "phone": "13800138001",
    "user_type": 3,
    "status": 1,
    "shop_id": 1,
    "shop_name": "测试商户",
    "created_at": "2024-01-01T10:05:00Z",
    "updated_at": "2024-01-01T10:05:00Z"
  },
  "timestamp": 1704096300
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | - | 请求参数错误 |
| 400 | 40001 | 商户不存在 |
| 400 | 50002 | 账号已存在（手机号重复） |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

**业务规则**

1. shop_id 必须对应一个存在的商户
2. 创建的账号 UserType 固定为 3（坐席/Agent）
3. 密码会使用 bcrypt 加密存储
4. 手机号必须全局唯一
5. 账号默认状态为正常（status=1）

---

### 3. 更新商户账号

更新商户账号的基本信息（仅限用户名）。

**请求**

```http
PUT /api/admin/shop-accounts/:id
Content-Type: application/json
```

**路径参数**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | integer | 是 | 账号ID |

**请求体**

```json
{
  "username": "new_username"
}
```

**字段说明**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| username | string | 是 | 新的用户名 |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "id": 2,
    "username": "new_username",
    "phone": "13800138001",
    "user_type": 3,
    "status": 1,
    "shop_id": 1,
    "shop_name": "测试商户",
    "created_at": "2024-01-01T10:05:00Z",
    "updated_at": "2024-01-01T11:05:00Z"
  },
  "timestamp": 1704099900
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | - | 请求参数错误 |
| 400 | 50001 | 账号不存在 |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

**业务规则**

1. 此接口只能更新用户名
2. 手机号和密码不可通过此接口修改
3. 密码修改请使用"重置账号密码"接口

---

### 4. 重置账号密码

管理员为账号重置密码（无需提供原密码）。

**请求**

```http
PUT /api/admin/shop-accounts/:id/password
Content-Type: application/json
```

**路径参数**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | integer | 是 | 账号ID |

**请求体**

```json
{
  "new_password": "newpassword123"
}
```

**字段说明**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| new_password | string | 是 | 新密码 |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": null,
  "timestamp": 1704096600
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | - | 请求参数错误 |
| 400 | 50001 | 账号不存在 |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

**业务规则**

1. 管理员操作，无需提供原密码
2. 新密码会使用 bcrypt 加密存储
3. 建议密码长度至少 8 位，包含字母和数字

---

### 5. 启用/禁用账号

更新账号的启用状态。

**请求**

```http
PUT /api/admin/shop-accounts/:id/status
Content-Type: application/json
```

**路径参数**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | integer | 是 | 账号ID |

**请求体**

```json
{
  "status": 2
}
```

**字段说明**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| status | integer | 是 | 状态（1=正常，2=禁用） |

**响应**

```json
{
  "code": 0,
  "msg": "success",
  "data": null,
  "timestamp": 1704096900
}
```

**状态码**

| HTTP 状态码 | 业务错误码 | 说明 |
|-------------|-----------|------|
| 200 | 0 | 成功 |
| 400 | - | 请求参数错误 |
| 400 | 50001 | 账号不存在 |
| 400 | 50003 | 账号状态无效 |
| 401 | - | 未授权 |
| 500 | - | 服务器错误 |

**业务规则**

1. 状态值只能是 1（正常）或 2（禁用）
2. 禁用账号后，该账号无法登录
3. 启用账号后，账号恢复正常使用

---

## 数据模型

### ShopResponse

商户响应对象

```json
{
  "id": 1,
  "name": "测试商户",
  "shop_code": "SHOP001",
  "contact": "张三",
  "phone": "13800138000",
  "province": "广东省",
  "city": "深圳市",
  "district": "南山区",
  "address": "科技园",
  "level": 1,
  "status": 1,
  "created_at": "2024-01-01T10:00:00Z",
  "updated_at": "2024-01-01T10:00:00Z"
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| id | integer | 商户ID |
| name | string | 商户名称 |
| shop_code | string | 商户编码 |
| contact | string | 联系人 |
| phone | string | 联系电话 |
| province | string | 省份 |
| city | string | 城市 |
| district | string | 区域 |
| address | string | 详细地址 |
| level | integer | 商户等级（1-7） |
| status | integer | 状态（1=正常，2=禁用） |
| created_at | string | 创建时间（ISO 8601） |
| updated_at | string | 更新时间（ISO 8601） |

### ShopAccountResponse

商户账号响应对象

```json
{
  "id": 1,
  "username": "admin",
  "phone": "13800138000",
  "user_type": 3,
  "status": 1,
  "shop_id": 1,
  "shop_name": "测试商户",
  "created_at": "2024-01-01T10:00:00Z",
  "updated_at": "2024-01-01T10:00:00Z"
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| id | integer | 账号ID |
| username | string | 用户名 |
| phone | string | 手机号 |
| user_type | integer | 用户类型（固定为 3，表示坐席） |
| status | integer | 状态（1=正常，2=禁用） |
| shop_id | integer | 所属商户ID |
| shop_name | string | 所属商户名称 |
| created_at | string | 创建时间（ISO 8601） |
| updated_at | string | 更新时间（ISO 8601） |

### 分页响应

所有列表接口的响应都包含分页信息

```json
{
  "items": [...],
  "total": 100,
  "page": 1,
  "size": 20
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| items | array | 数据列表 |
| total | integer | 总记录数 |
| page | integer | 当前页码 |
| size | integer | 每页数量 |

---

## 错误码

### 通用错误码

| 错误码 | HTTP 状态码 | 说明 |
|--------|-------------|------|
| 0 | 200 | 成功 |
| 10001 | 400 | 请求参数错误 |
| 10002 | 401 | 未授权 |
| 10003 | 403 | 无权限 |
| 10004 | 404 | 资源不存在 |
| 10005 | 500 | 服务器内部错误 |

### 商户相关错误码

| 错误码 | HTTP 状态码 | 说明 |
|--------|-------------|------|
| 40001 | 400 | 商户不存在 |
| 40002 | 400 | 商户编码已存在 |
| 40003 | 400 | 商户状态无效 |
| 40004 | 400 | 商户等级无效 |

### 账号相关错误码

| 错误码 | HTTP 状态码 | 说明 |
|--------|-------------|------|
| 50001 | 400 | 账号不存在 |
| 50002 | 400 | 账号已存在 |
| 50003 | 400 | 账号状态无效 |

### 错误响应格式

```json
{
  "code": 40001,
  "msg": "商户不存在",
  "data": null,
  "timestamp": 1704096000
}
```

---

## 认证

所有 API 接口都需要在请求头中携带有效的认证 Token：

```http
Authorization: Bearer YOUR_ACCESS_TOKEN
```

如果 Token 无效或过期，将返回 401 错误：

```json
{
  "code": 10002,
  "msg": "未授权",
  "data": null,
  "timestamp": 1704096000
}
```

---

## 速率限制

暂无速率限制。

---

## 版本历史

### v1.0.0 (2024-01-01)
- 初始版本
- 实现商户管理 CRUD 功能
- 实现商户账号管理功能
- 实现关联删除逻辑（删除商户自动禁用账号）

---

## 相关文档

- [使用指南](./使用指南.md) - 功能说明和使用场景
- [项目开发规范](../../AGENTS.md) - 项目整体开发规范
