docs: 添加ShopEntity运行模式处理逻辑文档
添加关于ShopEntity mode字段的详细文档,说明各模式的定义、核心处理逻辑及业务差异
This commit is contained in:
parent
bb9b35fb7a
commit
4a976bf3ba
|
|
@ -0,0 +1,247 @@
|
||||||
|
# ShopEntity Mode 运行模式处理逻辑文档
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
ShopEntity 的 `mode` 字段定义了商店的运行模式,影响订单创建、支付、审批、库存管理等多个业务环节。本文档详细说明 `mode` 字段的定义、各模式的处理逻辑以及在项目中的具体实现。
|
||||||
|
|
||||||
|
## 2. Mode 字段定义
|
||||||
|
|
||||||
|
### 2.1 数据库定义
|
||||||
|
- **字段名**: `mode`
|
||||||
|
- **类型**: `INTEGER`
|
||||||
|
- **位置**: `agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/db/ShopEntity.java:46-48`
|
||||||
|
|
||||||
|
### 2.2 模式枚举
|
||||||
|
```java
|
||||||
|
// 运行模式定义
|
||||||
|
0: 支付模式 (Payment Mode)
|
||||||
|
1: 审批模式 (Approval Mode)
|
||||||
|
2: 借还模式 (Borrow Return Mode)
|
||||||
|
3: 会员模式 (Membership Mode)
|
||||||
|
4: 耗材模式 (Consumable Mode)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 相关DTO/Command定义
|
||||||
|
- **ShopDTO**: 包含 `mode` 字段用于API响应 (`agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/dto/ShopDTO.java:35-36`)
|
||||||
|
- **SubmitOrderCommand**: 包含 `mode` 字段用于订单提交 (`agileboot-domain/src/main/java/com/agileboot/domain/shop/order/command/SubmitOrderCommand.java:34-35`)
|
||||||
|
- **SearchShopQuery**: 包含 `mode` 字段用于商店查询 (`agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/query/SearchShopQuery.java:20-21`)
|
||||||
|
|
||||||
|
## 3. 核心处理逻辑
|
||||||
|
|
||||||
|
### 3.1 ShopApplicationService - 商店模式变更校验
|
||||||
|
|
||||||
|
**文件位置**: `agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/ShopApplicationService.java:72-92`
|
||||||
|
|
||||||
|
**关键逻辑**: 当商店模式从其他模式变更为 **会员模式 (3)** 时,系统会执行严格的校验:
|
||||||
|
|
||||||
|
```java
|
||||||
|
if (command.getMode() != null && !command.getMode().equals(model.getMode())) {
|
||||||
|
if (command.getMode().equals(3)) {
|
||||||
|
// 检查该商店下是否存在已绑定商品的柜子
|
||||||
|
QueryWrapper<SmartCabinetEntity> smartCabinetQueryWrapper = new QueryWrapper<>();
|
||||||
|
smartCabinetQueryWrapper.eq("shop_id", command.getShopId())
|
||||||
|
.eq("deleted", false);
|
||||||
|
List<SmartCabinetEntity> cabinetEntities = smartCabinetService.list(smartCabinetQueryWrapper);
|
||||||
|
|
||||||
|
if (cabinetEntities != null && !cabinetEntities.isEmpty()) {
|
||||||
|
QueryWrapper<CabinetCellEntity> cabinetCellQueryWrapper = new QueryWrapper<>();
|
||||||
|
cabinetCellQueryWrapper.in("cabinet_id", cabinetEntities.stream()
|
||||||
|
.map(SmartCabinetEntity::getCabinetId)
|
||||||
|
.collect(Collectors.toList()))
|
||||||
|
.isNotNull("goods_id")
|
||||||
|
.eq("deleted", false);
|
||||||
|
List<CabinetCellEntity> cells = cabinetCellService.list(cabinetCellQueryWrapper);
|
||||||
|
if (cells != null && !cells.isEmpty()) {
|
||||||
|
throw new RuntimeException("该商店下存在已绑定商品的柜子,请先解绑商品后再修改模式");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**业务含义**: 会员模式下,柜子格口用于会员租赁,不允许绑定具体商品。变更前需确保所有柜子格口未绑定商品。
|
||||||
|
|
||||||
|
### 3.2 OrderApplicationService - 订单创建与模式处理
|
||||||
|
|
||||||
|
**文件位置**: `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/OrderApplicationService.java`
|
||||||
|
|
||||||
|
#### 3.2.1 订单创建时的模式设置
|
||||||
|
- **行 222**: `orderModel.setMode(command.getMode());` - 将命令中的模式设置到订单模型
|
||||||
|
- **行 408-419**: `processOrderGoods` 方法中的模式相关逻辑:
|
||||||
|
|
||||||
|
```java
|
||||||
|
if (orderModel.getMode() != null && orderModel.getMode().equals(3)) {
|
||||||
|
// 会员模式:使用柜子单元价格,商品名称为"柜子名称+格口+格口号"
|
||||||
|
goodsModel.setPrice(cabinetCellEntity.getCellPrice());
|
||||||
|
goodsModel.setTotalAmount(cabinetCellEntity.getCellPrice());
|
||||||
|
goodsModel.setGoodsName(cabinetEntity.getCabinetName() + "格口" + cabinetCellEntity.getCellNo());
|
||||||
|
} else {
|
||||||
|
// 其他模式:计算商品金额并验证库存
|
||||||
|
goodsModel.calculateTotal();
|
||||||
|
goodsModel.validateQuantity();
|
||||||
|
if (cabinetCellEntity == null || cabinetCellEntity.getStock() < goodsModel.getQuantity()) {
|
||||||
|
throw new ApiException(ErrorCode.FAILED, "柜子库存不足");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**业务差异**:
|
||||||
|
- **会员模式**: 商品价格 = 柜子格口价格,商品名称 = 柜子名称 + 格口号
|
||||||
|
- **其他模式**: 商品价格 = 商品单价 × 数量,需验证库存充足性
|
||||||
|
|
||||||
|
### 3.3 OrderModel - 支付成功处理
|
||||||
|
|
||||||
|
**文件位置**: `agileboot-domain/src/main/java/com/agileboot/domain/shop/order/model/OrderModel.java:103-115`
|
||||||
|
|
||||||
|
**关键逻辑**: `handlePaymentSuccess` 方法中的模式分支处理:
|
||||||
|
|
||||||
|
```java
|
||||||
|
if (this.getMode() != null && this.getMode().equals(3)) {
|
||||||
|
for (ShopOrderGoodsEntity orderGoods : orderGoodsList) {
|
||||||
|
CabinetCellEntity cell = cabinetCellService.getById(orderGoods.getCellId());
|
||||||
|
cell.setIsRented(1); // 设置为已租用状态
|
||||||
|
cell.updateById();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
orderGoodsList.forEach(orderGoods -> {
|
||||||
|
// 扣减商品库存
|
||||||
|
deductGoodsStock(orderGoods.getGoodsId(), orderGoods.getQuantity(), orderGoods.getCellId());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**业务差异**:
|
||||||
|
- **会员模式**: 更新柜子格口的 `isRented` 状态为 1(已租用)
|
||||||
|
- **其他模式**: 扣减商品库存和柜子格口库存
|
||||||
|
|
||||||
|
### 3.4 ReturnApprovalApplicationService - 退货审批处理
|
||||||
|
|
||||||
|
**文件位置**: `agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java`
|
||||||
|
|
||||||
|
#### 3.4.1 审批通过后的库存处理
|
||||||
|
- **行 349-364**: 根据订单商品模式进行不同的库存/状态恢复:
|
||||||
|
|
||||||
|
```java
|
||||||
|
if (orderGoodsModel.getMode() != null && orderGoodsModel.getMode().equals(3)) {
|
||||||
|
// 会员模式:更新柜子格口租赁状态为未租用
|
||||||
|
CabinetCellEntity cell = cabinetCellService.getById(orderGoodsModel.getCellId());
|
||||||
|
cell.setIsRented(0);
|
||||||
|
cell.updateById();
|
||||||
|
} else {
|
||||||
|
// 其他模式:恢复商品库存和格口库存
|
||||||
|
GoodsModel goodsModel = goodsModelFactory.loadById(orderGoodsModel.getGoodsId());
|
||||||
|
goodsModel.setStock(goodsModel.getStock() + orderGoodsModel.getQuantity());
|
||||||
|
goodsModel.updateById();
|
||||||
|
|
||||||
|
CabinetCellModel cabinetCellModel = cabinetCellModelFactory.loadById(orderGoodsModel.getCellId());
|
||||||
|
cabinetCellModel.setStock(cabinetCellModel.getStock() + orderGoodsModel.getQuantity());
|
||||||
|
cabinetCellModel.updateById();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.2 自动审批逻辑
|
||||||
|
- **行 830-850**: 提交审批申请时的自动审批判断:
|
||||||
|
|
||||||
|
```java
|
||||||
|
if (orderGoods.getMode() != null && orderGoods.getMode().equals(3)) {
|
||||||
|
// 会员模式:自动审批
|
||||||
|
UpdateReturnApprovalCommand approveCommand = new UpdateReturnApprovalCommand();
|
||||||
|
// ... 设置审批参数
|
||||||
|
approveApproval(approveCommand);
|
||||||
|
} else {
|
||||||
|
// 其他模式:根据商品 autoApproval 字段决定是否自动审批
|
||||||
|
GoodsModel goodsModel = goodsModelFactory.loadById(orderGoods.getGoodsId());
|
||||||
|
if (goodsModel.getAutoApproval().equals(1)) {
|
||||||
|
// 自动审批
|
||||||
|
// ... 设置审批参数
|
||||||
|
approveApproval(approveCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.3 通知消息差异化
|
||||||
|
- **行 864-868**: 发送审批通知时的描述差异:
|
||||||
|
```java
|
||||||
|
if (orderGoods.getMode() != null && orderGoods.getMode().equals(3)) {
|
||||||
|
article.setDescription("退还格口:" + orderGoods.getGoodsName());
|
||||||
|
} else {
|
||||||
|
article.setDescription("退还商品:" + orderGoods.getGoodsName());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.5 ShopService - 模式查询逻辑
|
||||||
|
|
||||||
|
**文件位置**: `agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/db/ShopServiceImpl.java:52-59`
|
||||||
|
|
||||||
|
**关键方法**: `getShopListByCorpid` - 获取指定企业下非特定模式的商店列表
|
||||||
|
|
||||||
|
```java
|
||||||
|
public List<ShopEntity> getShopListByCorpid(String corpid, Long mode) {
|
||||||
|
QueryWrapper<ShopEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("corpid", corpid)
|
||||||
|
.ne("mode", mode) // 排除指定模式
|
||||||
|
.eq("deleted", 0);
|
||||||
|
return this.list(queryWrapper);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**业务用途**: 获取企业微信下除了指定模式外的其他商店,用于模式切换时的校验或展示。
|
||||||
|
|
||||||
|
## 4. 各模式业务特性总结
|
||||||
|
|
||||||
|
| 模式 | 代码 | 核心特性 | 库存管理 | 价格计算 | 审批逻辑 |
|
||||||
|
|------|------|----------|----------|----------|----------|
|
||||||
|
| **支付模式** | 0 | 即时支付,商品交易 | 扣减商品库存 | 商品单价 × 数量 | 不涉及审批 |
|
||||||
|
| **审批模式** | 1 | 需上级审批通过 | 审批后扣减库存 | 商品单价 × 数量 | 人工审批流程 |
|
||||||
|
| **借还模式** | 2 | 借用归还机制 | 借用时扣减,归还时恢复 | 可能涉及租赁费用 | 借用审批 |
|
||||||
|
| **会员模式** | 3 | 柜子格口租赁 | 更新格口租赁状态 | 格口租赁价格 | 自动审批 |
|
||||||
|
| **耗材模式** | 4 | 消耗品领用 | 扣减库存 | 商品单价 × 数量 | 根据商品 autoApproval 配置 |
|
||||||
|
|
||||||
|
## 5. 关键业务规则
|
||||||
|
|
||||||
|
### 5.1 模式变更限制
|
||||||
|
- 变更为 **会员模式 (3)** 前,必须确保商店下所有柜子格口未绑定商品
|
||||||
|
- 模式变更校验仅针对变更为会员模式的情况
|
||||||
|
|
||||||
|
### 5.2 库存管理差异
|
||||||
|
- **会员模式**: 管理格口租赁状态 (`isRented`),不涉及商品库存扣减
|
||||||
|
- **其他模式**: 管理商品库存和格口库存,需确保库存充足
|
||||||
|
|
||||||
|
### 5.3 审批自动化
|
||||||
|
- **会员模式**: 退货申请自动审批
|
||||||
|
- **其他模式**: 根据商品的 `autoApproval` 配置决定是否自动审批
|
||||||
|
|
||||||
|
### 5.4 价格计算
|
||||||
|
- **会员模式**: 价格 = 柜子格口价格 (`cellPrice`)
|
||||||
|
- **其他模式**: 价格 = 商品单价 × 数量
|
||||||
|
|
||||||
|
## 6. 代码调用关系
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 前端提交订单
|
||||||
|
↓
|
||||||
|
2. SubmitOrderCommand (包含 mode)
|
||||||
|
↓
|
||||||
|
3. OrderApplicationService.createOrder()
|
||||||
|
↓
|
||||||
|
4. OrderModel.setMode() / processOrderGoods()
|
||||||
|
↓
|
||||||
|
5. 支付成功 → OrderModel.handlePaymentSuccess()
|
||||||
|
↓
|
||||||
|
6. 根据 mode 执行不同业务逻辑:
|
||||||
|
- mode=3: 更新格口租赁状态
|
||||||
|
- 其他: 扣减库存
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 注意事项
|
||||||
|
|
||||||
|
1. **模式一致性**: 订单中的 `mode` 必须与创建时商店的 `mode` 保持一致
|
||||||
|
2. **数据完整性**: 会员模式下,商品名称和价格来自柜子格口信息,需确保格口数据完整
|
||||||
|
3. **状态管理**: 会员模式的格口租赁状态 (`isRented`) 需与订单状态同步更新
|
||||||
|
4. **审批流程**: 不同模式对应不同的审批策略,需根据业务场景正确配置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档版本**: 1.0
|
||||||
|
**最后更新**: 2025-12-15
|
||||||
|
**相关文件**: ShopEntity.java, ShopApplicationService.java, OrderApplicationService.java, ReturnApprovalApplicationService.java
|
||||||
Loading…
Reference in New Issue