# Web端商户账户余额查询接口文档

## 模块概述

本模块提供账户余额查询功能,包括账户总余额和可提现金额的查询,支持完整的账户资金状态展示。

---

## 接口信息

### 查询账户余额

#### 接口详情

- **接口名称**: 查询账户余额
- **接口路径**: `GET /incomeManage/getAccountBalance`
- **请求方式**: GET
- **接口描述**: 查询指定门店的账户总余额和可提现金额
- **登录验证**: ✅ 需要（使用 `@LoginRequired` 注解）

---

## 请求参数

| 参数名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| storeId | Integer | 是 | 门店ID | 103 |

---

## 请求示例

```http
GET /incomeManage/getAccountBalance?storeId=103
```

```bash
curl "http://localhost:8080/incomeManage/getAccountBalance?storeId=103" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

---

## 响应参数

### 成功响应

```json
{
    "code": 200,
    "success": true,
    "data": {
        "balance": "1234.56",
        "cashOutMoney": "567.89"
    },
    "msg": "操作成功"
}
```

### 响应字段说明

| 字段名 | 类型 | 说明 |
|--------|------|------|
| data.balance | String | 账户总余额（单位：元） |
| data.cashOutMoney | String | 可提现金额（单位：元） |

**字段详细说明**：

#### balance（账户总余额）
- **定义**: 店铺账户中的总金额
- **来源**: `store_user` 表的 `money` 字段
- **单位**: 元（已从分转换）
- **精度**: 保留2位小数
- **说明**: 包含所有收入,不受提现限制影响

#### cashOutMoney（可提现金额）
- **定义**: 当前可以申请提现的金额
- **计算规则**: 
  ```
  可提现金额 = 4~27天内收入 - (已提现金额 + 待审核金额)
  ```
- **时间范围**: 收入创建时间在 [当前时间-27天, 当前时间-4天] 之间
- **条件**: 未绑定提现记录（`cash_out_id` 为空）
- **扣除项**: 
  - 已提现金额（`payment_status = 3`）
  - 待审核金额（`payment_status = 1`）
- **单位**: 元（已从分转换）
- **精度**: 保留2位小数

### 失败响应

#### 1. 店铺用户不存在

```json
{
    "code": 500,
    "success": false,
    "data": null,
    "msg": "查询失败：店铺用户不存在"
}
```

#### 2. 未登录或登录过期

```json
{
    "code": 500,
    "success": false,
    "data": null,
    "msg": "请先登录"
}
```

#### 3. 系统异常

```json
{
    "code": 500,
    "success": false,
    "data": null,
    "msg": "查询失败：{异常信息}"
}
```

---

## 业务逻辑说明

### 查询流程

```
┌─────────────────────────────────────────────┐
│  1. 接收门店ID参数                            │
│  storeId                                     │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  2. 查询店铺用户信息                          │
│  根据 storeId 查询 store_user 表             │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  3. 获取账户总余额                            │
│  balance = money ÷ 100                       │
│  （分→元，保留2位小数）                      │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  4. 查询4~27天内的收入记录                   │
│  条件：                                      │
│  - created_time BETWEEN (now-27天, now-4天)  │
│  - cash_out_id IS NULL                       │
│  - store_id = ?                              │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  5. 计算4~27天内收入总额                     │
│  sum(money)                                  │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  6. 查询已提现和待审核记录                    │
│  条件：                                      │
│  - store_id = ?                              │
│  - payment_status IN (1, 3)                  │
│  - delete_flag = 0                           │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  7. 计算已提现+待审核总额                    │
│  sum(money)                                  │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  8. 计算可提现金额                            │
│  cashOutMoney = 收入总额 - 提现总额          │
│  转换为元（保留2位小数）                     │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│  9. 返回结果                                  │
│  { balance, cashOutMoney }                   │
└─────────────────────────────────────────────┘
```

### 可提现金额计算规则

#### 时间范围说明

```
当前时间: 2025-11-17
可提现收入时间范围: 2025-10-21 ~ 2025-11-13

计算公式:
- 开始时间 = 当前时间 - 27天
- 结束时间 = 当前时间 - 4天
```

**为什么是4~27天？**
- **4天**: 收入需要经过4天账期才能提现（风险控制期）
- **27天**: 超过27天的收入会自动结算或有其他处理

#### 计算示例

**场景1: 正常情况**

```
4~27天内收入总额: 100000分（1000元）
已提现金额: 0分
待审核金额: 0分

可提现金额 = (100000 - 0) ÷ 100 = 1000.00元
```

**场景2: 有待审核提现**

```
4~27天内收入总额: 100000分（1000元）
已提现金额: 0分
待审核金额: 50000分（500元）

可提现金额 = (100000 - 50000) ÷ 100 = 500.00元
```

**场景3: 有已提现记录**

```
4~27天内收入总额: 100000分（1000元）
已提现金额: 30000分（300元）
待审核金额: 20000分（200元）

可提现金额 = (100000 - 30000 - 20000) ÷ 100 = 500.00元
```

**场景4: 收入不足或已全部提现**

```
4~27天内收入总额: 50000分（500元）
已提现金额: 50000分（500元）
待审核金额: 0分

可提现金额 = (50000 - 50000) ÷ 100 = 0.00元
```

---

## 数据库查询

### 涉及的表

#### 1. store_user（店铺用户表）

**查询SQL**:
```sql
SELECT * FROM store_user
WHERE store_id = ?
```

**说明**:
- 获取账户总余额（`money` 字段）
- 单位：分

#### 2. store_income_details_record（收入明细表）

**查询SQL**:
```sql
SELECT * FROM store_income_details_record
WHERE store_id = ?
  AND created_time BETWEEN ? AND ?  -- 4~27天
  AND cash_out_id IS NULL
  AND delete_flag = 0
```

**说明**:
- 查询可提现的收入记录
- `cash_out_id IS NULL`: 未绑定提现记录

#### 3. store_cash_out_record（提现记录表）

**查询SQL**:
```sql
SELECT * FROM store_cash_out_record
WHERE store_id = ?
  AND payment_status IN ('1', '3')
  AND delete_flag = '0'
```

**说明**:
- `payment_status = 1`: 待审核
- `payment_status = 3`: 已提现
- 这两种状态的金额需要从可提现金额中扣除

---

## 提现状态说明

### payment_status 状态值

| Status | 说明 | 是否扣除 |
|--------|------|---------|
| 0 | 审核不通过 | ❌ 不扣除 |
| 1 | 待审核 | ✅ 扣除 |
| 2 | 审核通过待打款 | ❌ 不扣除 |
| 3 | 已提现（已打款） | ✅ 扣除 |

**扣除规则说明**:
- **待审核（1）**: 提现申请已提交,资金被锁定,需要扣除
- **已提现（3）**: 资金已打款,需要扣除
- **其他状态**: 提现未成功或未完成,不扣除

---

## 金额计算规则

### 金额单位转换

| 数据库存储（分） | 显示（元） | 转换公式 |
|------------------|-----------|----------|
| 100000 | 1000.00 | money ÷ 100 |
| 56789 | 567.89 | money ÷ 100 |
| 0 | 0.00 | money ÷ 100 |

### 转换代码

```java
// 账户总余额转换
String balance = new BigDecimal(storeUser.getMoney())
    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)
    .toString();

// 可提现金额转换
BigDecimal finalCashOutMoney = new BigDecimal(cashOutMoney)
    .subtract(BigDecimal.valueOf(totalCashOutAmount))
    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
```

**转换规则**:
- 使用 `BigDecimal` 进行精确计算
- 除以100转换为元
- 保留2位小数
- 舍入模式：`HALF_UP`（四舍五入）

---

## 业务场景

### 场景 1: 新店铺（无收入）

**数据状态**:
- 账户余额: 0分
- 4~27天内收入: 0分
- 已提现: 0分

**响应**:
```json
{
    "code": 200,
    "success": true,
    "data": {
        "balance": "0.00",
        "cashOutMoney": "0.00"
    }
}
```

---

### 场景 2: 有收入但未到提现期

**数据状态**:
- 账户余额: 50000分（500元）
- 4~27天内收入: 0分（收入都在4天内）
- 已提现: 0分

**响应**:
```json
{
    "code": 200,
    "success": true,
    "data": {
        "balance": "500.00",
        "cashOutMoney": "0.00"
    }
}
```

**说明**: 账户有余额,但都是4天内的收入,还未到可提现期

---

### 场景 3: 有可提现金额

**数据状态**:
- 账户余额: 150000分（1500元）
- 4~27天内收入: 100000分（1000元）
- 已提现: 0分

**响应**:
```json
{
    "code": 200,
    "success": true,
    "data": {
        "balance": "1500.00",
        "cashOutMoney": "1000.00"
    }
}
```

**说明**: 账户余额1500元,其中1000元可提现

---

### 场景 4: 有待审核提现

**数据状态**:
- 账户余额: 150000分（1500元）
- 4~27天内收入: 100000分（1000元）
- 待审核提现: 60000分（600元）
- 已提现: 0分

**响应**:
```json
{
    "code": 200,
    "success": true,
    "data": {
        "balance": "1500.00",
        "cashOutMoney": "400.00"
    }
}
```

**说明**: 
- 账户余额: 1500元（不变）
- 可提现金额: 1000 - 600 = 400元

---

### 场景 5: 全部已提现

**数据状态**:
- 账户余额: 50000分（500元）
- 4~27天内收入: 100000分（1000元）
- 已提现: 100000分（1000元）

**响应**:
```json
{
    "code": 200,
    "success": true,
    "data": {
        "balance": "500.00",
        "cashOutMoney": "0.00"
    }
}
```

**说明**: 
- 账户余额: 500元（4天内的新收入）
- 可提现金额: 1000 - 1000 = 0元（4~27天内收入已全部提现）

---

## 登录验证

### 验证机制

接口使用 `@LoginRequired` 注解进行登录验证,通过AOP切面实现:

1. **Token验证**: 从请求中获取JWT Token并解析用户信息
2. **用户类型验证**: 确认用户类型为 `storePlatform`
3. **Redis Token验证**: 检查Token是否在Redis中存在（未过期/未注销）

### 验证失败场景

| 场景 | 返回消息 |
|------|----------|
| Token无效或不存在 | "请先登录" |
| 用户类型不正确 | "请先登录" |
| Token已过期或已注销 | "请先登录" |

---

## 异常处理

### 异常场景

| 异常情况 | HTTP状态码 | 返回code | 返回msg |
|----------|-----------|----------|---------|
| 店铺用户不存在 | 200 | 500 | "查询失败：店铺用户不存在" |
| 未登录 | 200 | 500 | "请先登录" |
| 系统异常 | 200 | 500 | "查询失败：{异常信息}" |

### 日志记录

所有请求和异常都会记录详细日志:

```java
// 请求日志
log.info("IncomeManageController.getAccountBalance?storeId={}", storeId);

// 业务日志
log.debug("IncomeManageServiceImpl.getAccountBalance - 账户总余额: {}元", balance);
log.debug("IncomeManageServiceImpl.getAccountBalance - 4~27天内收入总额: {}分", cashOutMoney);

// 异常日志
log.error("IncomeManageController.getAccountBalance ERROR: {}", e.getMessage(), e);
```

---

## 测试用例

### 测试场景1: 正常查询

**请求**:
```http
GET /incomeManage/getAccountBalance?storeId=103
```

**预期结果**:
- 返回账户总余额和可提现金额
- 两个金额都是字符串格式
- 保留2位小数

---

### 测试场景2: 新店铺（无数据）

**前置条件**:
- 店铺刚注册
- 无任何收入记录

**预期结果**:
```json
{
    "balance": "0.00",
    "cashOutMoney": "0.00"
}
```

---

### 测试场景3: 有待审核提现

**前置条件**:
- 有4~27天内的收入
- 有待审核的提现申请

**预期结果**:
- `cashOutMoney` 应扣除待审核金额
- `balance` 不受影响

---

### 测试场景4: 店铺不存在

**请求**:
```http
GET /incomeManage/getAccountBalance?storeId=999999
```

**预期结果**:
```json
{
    "code": 500,
    "success": false,
    "msg": "查询失败：店铺用户不存在"
}
```

---

## 注意事项

### 1. 账期时间范围

- ⚠️ **可提现时间**: 收入创建后4~27天
- ⚠️ **4天**: 最少账期时间（风险控制期）
- ⚠️ **27天**: 最长账期时间（自动结算期）

### 2. 金额计算

- ⚠️ **数据库单位**: 分（Integer）
- ⚠️ **接口返回**: 元（String）
- ⚠️ **转换规则**: 分 ÷ 100 = 元
- ⚠️ **精度**: 保留2位小数
- ⚠️ **舍入模式**: HALF_UP（四舍五入）

### 3. 提现状态

- ⚠️ **扣除状态**: 待审核（1）、已提现（3）
- ⚠️ **不扣除状态**: 审核不通过（0）、审核通过待打款（2）

### 4. 数据一致性

- ⚠️ `balance`（账户总余额）: 来自 `store_user.money`
- ⚠️ `cashOutMoney`（可提现金额）: 计算得出,受多个因素影响
- ⚠️ 两个金额的关系: `balance >= cashOutMoney`（总是成立）

### 5. 登录验证

- ⚠️ 所有请求必须携带有效Token
- ⚠️ Token过期需要重新登录
- ⚠️ 用户类型必须为 `storePlatform`

---

## 性能优化建议

### 1. 数据库索引

确保以下字段有索引:

```sql
-- store_user表
ALTER TABLE store_user ADD INDEX idx_store_id (store_id);

-- store_income_details_record表
ALTER TABLE store_income_details_record 
ADD INDEX idx_store_created_cashout (store_id, created_time, cash_out_id);

-- store_cash_out_record表
ALTER TABLE store_cash_out_record 
ADD INDEX idx_store_status (store_id, payment_status, delete_flag);
```

### 2. 查询优化

- ✅ 使用复合索引加速查询
- ✅ 时间范围查询使用 `BETWEEN`
- ✅ 使用 Stream API 高效计算总和

### 3. 缓存策略

对于频繁查询的数据,可以考虑:
- Redis缓存账户余额（TTL: 1分钟）
- 在余额变更时清除缓存
- 可提现金额实时计算（不建议缓存）

---

## 迁移说明

### 原接口（app端）

- **服务**: `alien-store`
- **路径**: `/alienStore/storeIncomeDetailsRecord/accountBalance`
- **Controller**: `StoreIncomeDetailsRecordController`
- **Service**: `StoreIncomeDetailsRecordService.accountBalance()`

### 新接口（web端）

- **服务**: `alien-store-platform`
- **路径**: `/incomeManage/getAccountBalance`
- **Controller**: `IncomeManageController`
- **Service**: `IncomeManageService.getAccountBalance()`

### 差异说明

| 项目 | app端 | web端 | 说明 |
|------|-------|-------|------|
| 接口路径 | `/accountBalance` | `/getAccountBalance` | 更符合web端命名规范 |
| 登录验证 | 无 | ✅ 有（@LoginRequired） | 增加登录验证 |
| 返回类型 | Map<String, Object> | Map<String, Object> | 保持一致 |
| 业务逻辑 | ✅ | ✅ | 完全复用 |
| 日志记录 | 基础 | 详细 | 增强日志记录 |

### 复用的核心组件

1. **Mapper**: 
   - `StoreUserMapper`
   - `StoreIncomeDetailsRecordMapper`
   - `StoreCashOutRecordMapper`
2. **Entity**: 
   - `StoreUser`
   - `StoreIncomeDetailsRecord`
   - `StoreCashOutRecord`
3. **Util**: `DateUtils`

---

## 更新日志

### 2025-11-17

**新增接口**:
- ✅ `GET /incomeManage/getAccountBalance` - 查询账户余额

**核心功能**:
- ✅ 查询账户总余额
- ✅ 计算可提现金额（4~27天内收入）
- ✅ 扣除已提现和待审核金额
- ✅ 金额自动格式化（分→元）
- ✅ 登录验证（@LoginRequired）
- ✅ 详细日志记录
- ✅ 完善异常处理

**涉及文件**:
- `IncomeManageController.java` - 更新
- `IncomeManageService.java` - 更新
- `IncomeManageServiceImpl.java` - 更新

**代码质量**:
- ✅ Linter检查：无错误
- ✅ 日志记录：详细
- ✅ 异常处理：完善
- ✅ 代码注释：完整

**开发人员**: ssk

---

**文档版本**: v1.0  
**最后更新**: 2025-11-17  
**维护人员**: ssk







