# 库存日志 — 技术方案

> **依据：** 《库存日志功能需求.md》v1.0  
> **关联：** 《关联需求分析.md》v1.6；平台《订单管理功能需求》v1.0.1、《商品管理功能需求》v1.3.3；商家《商品入库技术方案》v1.0、《商品出库技术方案》v1.0、《库存调整功能需求-草稿》、《库存查询功能需求-草稿》、《商家端店铺上下文接口说明》  
> **范围：** 商家端 **库存管理 · 库存日志** — **只读** 分页列表、**方向 Tab** 筛选、**关键词** 检索；**不含** 写入/编辑/删除、导出、详情页、平台端。  
> **原则：** `X-Shop-Id` 店铺隔离；**读 `biz_stock_log`**（与入/出库/调整 **同表**）；写入由 **兄弟模块** 完成。

---

## 1. 技术架构

| 项 | 选型 |
|----|------|
| 基础框架 | RuoYi **v3.9.2**（`springboot2` 分支） |
| 数据库 | **MySQL 5.7.39**；复用 **`biz_stock_log`**（[`sql/biz_stock_inbound.sql`](../../../../sql/biz_stock_inbound.sql)） |
| ORM / 权限 / 响应 | MyBatis；`@PreAuthorize`；`TableDataInfo` |
| 店铺上下文 | `SellerShopContextInterceptor` + **`X-Shop-Id`** |
| 事务 | **只读**；无写接口 |

### 1.1 与兄弟模块边界

| 维度 | 本模块 | 协作模块 |
|------|--------|----------|
| 路径 | **`/agri/seller/stock/log`** | 入库 `/inbound`、出库 `/outbound`（已有） |
| 改库存 | **无** | 入库/出库/调整/订单协作 |
| 写流水 | **无** | `IStockLogService.insertLog`（入/出库 Facade/Service 已调） |
| 读流水 | **GET /list** | **库存查询** 将来复用 `selectByGoodsId` |

### 1.2 数据流

```text
【写入 · 已有】
  StockInboundServiceImpl / StockInboundFacadeImpl
  StockOutboundServiceImpl / StockOutboundFacadeImpl
  （将来）StockAdjustServiceImpl、OrderCloseRollback
      → IStockLogService.insertLog → biz_stock_log

【本模块 · 只读】
  GET /agri/seller/stock/log/list
      → BizStockLogMapper.selectList
      → StockSupport.changeReasonText 富化「操作」列文案
```

### 1.3 模块落位

**菜单：** 库存管理 → 库存日志  
**包路径：** `com.ruoyi.web.modules.stock`（扩展已有包）

```text
baqing-shop/src/main/java/com/ruoyi/web/modules/stock/
├── controller/SellerStockLogController.java      # 新建
├── service/
│   ├── IStockLogService.java                     # 扩展 selectList / selectByGoodsId
│   └── impl/StockLogServiceImpl.java             # 扩展
├── dto/StockLogQuery.java                        # 新建
├── vo/StockLogListRowVO.java                     # 新建
├── mapper/BizStockLogMapper.java                 # 扩展
├── constant/StockConstants.java                  # +STOCK_EDIT / ORDER_CANCEL 编码
└── support/StockSupport.java                     # +changeReasonText

baqing-shop/src/main/resources/mapper/stock/
└── BizStockLogMapper.xml                         # 扩展 selectList / selectByGoodsId

sql/biz_stock_log_menu.sql                        # 菜单 6520 段
```

**前端（建议）：**

| 项 | 路径 |
|----|------|
| 列表 | `ruoyi-ui/src/views/agri/seller/stock/log/index.vue` |
| API | `ruoyi-ui/src/api/agri/seller/stock/log.js` |

---

## 2. 数据库设计

**无新建表**；复用 **`biz_stock_log`**。

| 字段 | 列表用途 |
|------|----------|
| goods_name | 商品名称（快照） |
| spec_text | 商品规格（已规范化为 `—`） |
| stock_before / stock_after / change_qty | 变化前/后/量 |
| direction | Tab 筛选：`1` 入库 / `2` 出库 |
| change_reason | 编码 → 展示文案 |
| create_time | 操作时间；**默认倒序** |

**索引（已有）：** `idx_shop_time (shop_id, create_time)` — 支撑全店列表。

### 2.1 change_reason 编码与展示

| code | direction | 展示文案（需求 §3.2～§3.3） |
|------|-----------|---------------------------|
| `NEW_SPEC` | 1 | 新增商品规格 |
| `PURCHASE_IN` | 1 | 采购入库 |
| `RETURN_IN` | 1 | 退货入库 |
| `OTHER_IN` | 1 | 其他入库 |
| `ORDER_CANCEL` | 1 | 取消订单返库存 |
| `STOCK_EDIT` | 1 或 2 | 库存编辑 |
| `ORDER_DEDUCT` | 2 | 下单扣减库存 |
| `DELETE_SPEC` | 2 | 删除产品规格 |
| `MANUAL_ORDER_OUT` | 2 | 订单出库 |
| `EXPIRED_OUT` | 2 | 过期出库 |
| `OTHER_OUT` | 2 | 其他出库 |

> UI 可将 **取消订单返库存** 简写为 **取消订单返库**；后端 `changeReasonText` 返回 **完整文案**，前端可再缩写。

---

## 3. 接口设计

**基路径：** `/agri/seller/stock/log`  
**上下文：** **`X-Shop-Id`** 必填。

### 3.1 接口一览

| 方法 | 路径 | 权限 | 说明 |
|------|------|------|------|
| GET | `/list` | `agri:seller:stock:log:list` | **分页列表**（本期唯一接口） |

### 3.2 列表 `GET /list`

**Query（StockLogQuery）：**

| 参数 | 说明 |
|------|------|
| pageNum, pageSize | 分页 |
| keyword | 模糊匹配 **goods_name** 或 **spec_text**（`spec_text='—'` 时仅匹配名称） |
| direction | 空=全部；`1`=入库；`2`=出库 |

**固定条件：** `shop_id = requireShopId()`。  
**排序：** `create_time DESC, log_id DESC`。

**Row（StockLogListRowVO）：**

| 字段 | 说明 |
|------|------|
| logId | 流水 ID |
| goodsId | 商品 ID |
| goodsName | 商品名称快照 |
| specText | 规格文案 |
| stockBefore | 变化前库存 |
| stockAfter | 变化后库存 |
| changeQty | 变化量 |
| direction | `1`/`2` |
| changeReason | 编码 |
| changeReasonText | **操作** 列展示文案 |
| createTime | 操作时间 |

---

## 4. 服务层

### 4.1 IStockLogService 扩展

| 方法 | 说明 |
|------|------|
| `insertLog` | **已有**；兄弟模块写入 |
| `selectList(shopId, query)` | 本模块列表 |
| `selectByGoodsId(shopId, goodsId)` | **库存查询** 复用；按规格查明细 |

### 4.2 富化规则

- `changeReasonText = StockSupport.changeReasonText(changeReason)`
- 未知编码 **原样返回** code，便于排查

---

## 5. Mapper SQL 要点

**selectList：**

```sql
SELECT log_id, goods_id, goods_name, spec_text, stock_before, stock_after,
       change_qty, direction, change_reason, create_time
FROM biz_stock_log
WHERE shop_id = #{shopId}
  AND (#{direction} IS NULL OR #{direction} = '' OR direction = #{direction})
  AND (#{keyword} IS NULL OR #{keyword} = ''
       OR goods_name LIKE CONCAT('%', #{keyword}, '%')
       OR (spec_text <> '—' AND spec_text LIKE CONCAT('%', #{keyword}, '%')))
ORDER BY create_time DESC, log_id DESC
```

**selectByGoodsId：** 同上条件 + `goods_id = #{goodsId}`（无 keyword/direction 或可选 direction）。

---

## 6. 权限与菜单

| 权限标识 | 说明 |
|----------|------|
| `agri:seller:stock:log:list` | 列表查看 |

菜单：**库存管理 → 库存日志**（`parent_id=6500`，`menu_id=6520`，`path=log`）。  
脚本：`sql/biz_stock_log_menu.sql`。

---

## 7. 实现清单

| # | 项 | 状态 |
|---|-----|------|
| 1 | `StockLogQuery` / `StockLogListRowVO` | 待建 |
| 2 | `BizStockLogMapper.selectList` + XML | 待建 |
| 3 | `StockSupport.changeReasonText` | 待建 |
| 4 | `IStockLogService.selectList` | 待建 |
| 5 | `SellerStockLogController` | 待建 |
| 6 | `sql/biz_stock_log_menu.sql` | 待建 |
| 7 | 单元测试 Controller + Service | 待建 |
| 8 | ruoyi-ui 列表页 | 待建 |

---

## 8. 版本记录

| 版本 | 说明 |
|------|------|
| **v1.0** | 首版：只读列表、方向/关键词检索、复用 biz_stock_log、与入/出库写入链对齐 |

---

*文档版本：v1.0 · 依据《库存日志功能需求.md》v1.0*
