# 借还动态接口文档

## 概述

本文档介绍新增加的借还动态列表接口，该接口将借出和归还操作分别作为独立记录返回，相比原有的 `getBorrowReturnRecordList` 接口，能更清晰地展示订单的生命周期。

## 接口信息

### 新增接口

**接口地址**: `GET /shop/order/borrow-return-dynamic`

**功能描述**: 查询借还动态分页列表，返回借出和归还的独立记录

## 数据结构

### 请求参数

#### SearchBorrowReturnDynamicQuery

| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| goodsId | Long | 否 | 商品ID，精确筛选 |
| status | Integer | 否 | 状态筛选（仅对归还记录有效）<br>- 0: 未退还<br>- 1: 待审批<br>- 2: 已通过<br>- 3: 已驳回<br>- 4: 开柜中 |
| dynamicType | Integer | 否 | 动态类型筛选<br>- 0: 借出记录<br>- 1: 归还记录 |
| pageNum | Integer | 否 | 页码（默认1） |
| pageSize | Integer | 否 | 每页大小（默认10） |

### 响应数据

#### BorrowReturnDynamicDTO

| 字段名 | 类型 | 说明 |
|--------|------|------|
| orderGoodsId | Long | 订单商品ID |
| dynamicType | Integer | 动态类型（0-借出 1-归还） |
| dynamicTypeStr | String | 动态类型描述 |
| orderId | Long | 订单ID |
| orderTime | Date | 订单创建时间/借出时间 |
| goodsId | Long | 商品ID |
| goodsName | String | 商品名称 |
| goodsPrice | BigDecimal | 商品单价 |
| quantity | Integer | 数量 |
| paymentMethod | String | 支付方式 |
| orderName | String | 订单姓名 |
| orderMobile | String | 订单手机号 |
| cellId | Long | 格口ID |
| cellNo | Integer | 格口号 |
| cabinetId | Long | 柜机ID |
| cabinetName | String | 柜机名称 |
| operateTime | Date | 归还/审批时间（归还记录时有效） |
| approvalId | Long | 审批ID（归还记录时有效） |
| status | Integer | 审批状态（归还记录时有效） |
| statusStr | String | 状态描述 |
| auditName | String | 审批人（归还记录时有效） |
| auditRemark | String | 审核说明（归还记录时有效） |
| images | String | 归还图片（归还记录时有效） |

## 业务说明

### 记录分类

每条订单商品会产生两条动态记录：

1. **借出记录** (`dynamicType = 0`)
   - 记录时间：`orderTime` = 订单创建时间
   - 状态：固定为 0（未退还）
   - 审批相关字段：均为 null

2. **归还记录** (`dynamicType = 1`)
   - 记录时间：`operateTime` = 审批时间（若无则为创建时间）
   - 状态：实际的审批状态
   - 审批相关字段：审批人、审核说明、归还图片等

### 与原接口对比

| 特性 | getBorrowReturnRecordList | getBorrowReturnDynamicList |
|------|---------------------------|----------------------------|
| 记录方式 | 一条记录包含借出和归还信息 | 借出和归还分别独立记录 |
| 时间展示 | 只显示一个时间 | 分别显示借出时间和归还时间 |
| 状态展示 | 状态混合显示 | 归还记录显示审批状态，借出记录固定为未退还 |
| 数据清晰度 | 信息集中但复杂 | 信息分离但清晰 |
| 适用场景 | 需要快速查看整体情况 | 需要追踪完整操作流程 |

## 使用示例

### 示例1: 查询所有动态记录

**请求**:
```http
GET /shop/order/borrow-return-dynamic
```

**响应**:
```json
{
  "code": 200,
  "msg": "成功",
  "data": {
    "records": [
      {
        "orderGoodsId": 1001,
        "dynamicType": 0,
        "dynamicTypeStr": "借出",
        "orderId": 1000,
        "orderTime": "2025-11-28 10:00:00",
        "goodsId": 200,
        "goodsName": "iPad",
        "goodsPrice": 3000.00,
        "quantity": 1,
        "paymentMethod": "wechat",
        "orderName": "张三",
        "orderMobile": "13800138000",
        "cellId": 1,
        "cellNo": 5,
        "cabinetId": 1,
        "cabinetName": "主柜A",
        "operateTime": null,
        "approvalId": null,
        "status": 0,
        "statusStr": "未退还",
        "auditName": null,
        "auditRemark": null,
        "images": null
      },
      {
        "orderGoodsId": 1001,
        "dynamicType": 1,
        "dynamicTypeStr": "归还",
        "orderId": 1000,
        "orderTime": "2025-11-28 10:00:00",
        "goodsId": 200,
        "goodsName": "iPad",
        "goodsPrice": 3000.00,
        "quantity": 1,
        "paymentMethod": "wechat",
        "orderName": "张三",
        "orderMobile": "13800138000",
        "cellId": 1,
        "cellNo": 5,
        "cabinetId": 1,
        "cabinetName": "主柜A",
        "operateTime": "2025-11-28 14:00:00",
        "approvalId": 500,
        "status": 2,
        "statusStr": "已通过",
        "auditName": "李四",
        "auditRemark": "商品完好",
        "images": "/images/return/123.jpg"
      }
    ],
    "total": 2,
    "size": 10,
    "current": 1,
    "orders": [],
    "hitCount": false,
    "searchCount": true,
    "pages": 1
  }
}
```

### 示例2: 仅查询借出记录

**请求**:
```http
GET /shop/order/borrow-return-dynamic?dynamicType=0
```

### 示例3: 查询已通过的归还记录

**请求**:
```http
GET /shop/order/borrow-return-dynamic?dynamicType=1&status=2
```

### 示例4: 按商品筛选

**请求**:
```http
GET /shop/order/borrow-return-dynamic?goodsId=200
```

## 实现细节

### 数据库查询

接口使用 `UNION ALL` 查询实现：

1. 第一部分：查询借出记录
   - 来源：`shop_order` + `shop_order_goods` + `cabinet_cell` + `smart_cabinet`
   - 时间字段：`so.create_time`
   - 状态：固定值 0

2. 第二部分：查询归还记录
   - 来源：`shop_order` + `shop_order_goods` + `return_approval` + `cabinet_cell` + `smart_cabinet`
   - 时间字段：`COALESCE(ra.approval_time, ra.create_time)`
   - 状态：实际审批状态

### 服务层实现

- **Mapper**: `ShopOrderMapper.getBorrowReturnDynamicList()`
- **Service**: `ShopOrderService.getBorrowReturnDynamicList()`
- **ApplicationService**: `OrderApplicationService.getBorrowReturnDynamicList()`
- **Controller**: `ShopOrderController.getBorrowReturnDynamicList()`

### 分页处理

使用 MyBatis-Plus 的 `Page` 插件实现分页查询，支持：
- 页码控制（pageNum）
- 每页大小控制（pageSize）
- 总记录数统计

## 注意事项

1. **状态筛选**: `status` 参数仅对 `dynamicType=1`（归还记录）有效，对借出记录无效
2. **空值处理**: 借出记录的审批相关字段（approvalId、auditName、auditRemark、images）均为 null
3. **时间排序**: 查询结果按动态发生时间（dynamic_time）倒序排列
4. **数据权限**: 接口遵循现有的数据权限控制逻辑
5. **性能考虑**: 大量数据时建议使用分页，并合理设置筛选条件

## 相关文件

### 新增文件

- `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/dto/BorrowReturnDynamicDTO.java`
- `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/query/SearchBorrowReturnDynamicQuery.java`

### 修改文件

- `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderMapper.java`
- `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderService.java`
- `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/db/ShopOrderServiceImpl.java`
- `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/OrderApplicationService.java`
- `agileboot-admin/src/main/java/com/agileboot/admin/controller/shop/ShopOrderController.java`

## 更新日志

| 日期 | 版本 | 更新内容 |
|------|------|----------|
| 2025-11-28 | v1.0 | 新增借还动态接口，支持借出和归还分别独立查询 |

## 联系信息

如有问题或建议，请联系开发团队。
