文章目录
- [模版方法 + 策略模式在库存增加/扣减场景下的应用](#模版方法 + 策略模式在库存增加/扣减场景下的应用)
-
- [1. 库存模型与交互设计](#1. 库存模型与交互设计)
-
- [1.1. 主要字段](#1.1. 主要字段)
- [1.2. 交互模型](#1.2. 交互模型)
-
- [1.2.1. 占用与释放库存](#1.2.1. 占用与释放库存)
-
- [1.2.1.1. 占用](#1.2.1.1. 占用)
- [1.2.1.2. 释放](#1.2.1.2. 释放)
- [1.2.2. 入库完成](#1.2.2. 入库完成)
- [1.2.3. 出库完成](#1.2.3. 出库完成)
- [2. 为什么需要策略 + 模板](#2. 为什么需要策略 + 模板)
-
- [2.1. 为什么需要策略](#2.1. 为什么需要策略)
- [2.1. 为什么需要模板方法](#2.1. 为什么需要模板方法)
- [3. 策略聚合(宏命令)](#3. 策略聚合(宏命令))
- [4. 代码实现](#4. 代码实现)
-
- [4.1. 策略 + 模板](#4.1. 策略 + 模板)
- [4.2. 策略聚合](#4.2. 策略聚合)
模版方法 + 策略模式在库存增加/扣减场景下的应用
1. 库存模型与交互设计
1.1. 主要字段
| 字段 | 说明 |
|---|---|
| totalStock | 总库存 |
| availableStock | 可用库存 |
| reservedStock | 占用库存 |
1.2. 交互模型
1.2.1. 占用与释放库存
1.2.1.1. 占用
可用库存减少,占用库存增加
1.2.1.2. 释放
占用库存减少,可用库存增加
1.2.2. 入库完成
总库存增加,可用库存增加
1.2.3. 出库完成
占用库存减少,总库存减少
2. 为什么需要策略 + 模板
2.1. 为什么需要策略
不同的库存处理可以定义为不同的策略,并且会由一个容器来统一进行管理。
2.1. 为什么需要模板方法
从交互模型上看本质上就是数值的增加或减少,以及在操作之前处理当前库存的查询、库存的校验、以及并发的处理和之后的库存事件的发布等标准流程。而具体处理的是哪个库存以及对应不同场景下的日志输出和异常处理则需要通过子类类实现。
3. 策略聚合(宏命令)
实现了多个策略之后根据不同的场景需要组合,并且不需要调用方随意的组合策略,而是只使用提供的策略聚合。
4. 代码实现
4.1. 策略 + 模板
- AbstractInventoryStrategy(库存策略模板抽象类)
java
@Component
public abstract class AbstractInventoryStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractInventoryStrategy.class);
@Resource
protected InventoryRepo inventoryRepo;
@Resource
private InventoryDomainEventPublisher inventoryDomainEventPublisher;
/**
* 执行库存策略
* 该方法通过事务管理来执行库存操作,包括获取当前库存、计算新库存值、处理库存变更以及发布事件
* 它体现了在进行库存管理时的一系列步骤,确保了操作的原子性和一致性
*
* @param inventoryStrategyDTO 库存策略数据传输对象,包含了执行库存操作所需的所有信息
*/
@Transactional(rollbackFor = Exception.class)
public void execute(InventoryStrategyDTO inventoryStrategyDTO) {
LOGGER.info("开始执行库存策略,参数:{}", inventoryStrategyDTO);
// 获取当前库存信息
InventoryPO inventoryPO = this.getCurrentInventory(inventoryStrategyDTO);
// 获取当前库存的值
Integer currentValue = this.getCurrentInventoryValue(inventoryPO);
// 计算新的库存值
Integer newValue = this.calculateNewInventoryValue(currentValue, inventoryStrategyDTO.getOperationQuantity());
// 校验新的库存值
this.validateNewValue(inventoryPO, newValue);
// 处理库存变更
this.processInventory(inventoryPO.getId(), newValue, inventoryPO.getVersion(), inventoryStrategyDTO.getOperatorId());
// 发布库存变更事件
this.publishEvent(inventoryStrategyDTO, inventoryPO, currentValue, newValue);
}
/**
* 获取当前库存信息
* 通过仓库ID、仓库位置ID、SKU ID和批次号来精确查找库存记录
* 这是为了确保在进行库存操作之前,获取到的库存信息是最准确和相关的
*
* @param inventoryStrategyDTO 包含了定位库存所需的关键信息
* @return InventoryPO 返回找到的库存信息对象
*/
protected InventoryPO getCurrentInventory(InventoryStrategyDTO inventoryStrategyDTO) {
return inventoryRepo.getInventoryPO(inventoryStrategyDTO.getWarehouseId(),
inventoryStrategyDTO.getWarehouseLocationId(),
inventoryStrategyDTO.getSkuId(),
inventoryStrategyDTO.getBatchNumber());
}
/**
* 处理库存变更
* 抽象方法,旨在处理库存值的实际变更,包括必要的事务处理和版本控制
* 该方法的具体实现应在子类中完成,以适应不同的库存策略或业务需求
*
* @param inventoryId 库存ID
* @param newValue 新的库存值
* @param expectedVersion 预期的库存版本号,用于乐观锁控制
* @param operatorId 操作员ID,用于审计或追踪操作责任人
*/
protected abstract void processInventory(Long inventoryId, Integer newValue, Integer expectedVersion, Long operatorId);
/**
* 发布库存变更事件
*
* 构建并发布一个库存变更事件,该事件包含库存变更前后的值、库存信息和变更元数据
* 事件发布机制用于通知其他系统组件或服务有关库存变更的情况
*
* @param InventoryStrategyDTO 库存策略DTO,包含事件处理所需的业务信息
* @param inventoryPO 库存对象,表示变更的库存记录
* @param currentValue 变更前的库存值
* @param newValue 变更后的库存值
*/
private void publishEvent(InventoryStrategyDTO InventoryStrategyDTO,
InventoryPO inventoryPO,
Integer currentValue,
Integer newValue) {
InventoryDomainEvent<InventoryChangeEventPayload> inventoryDomainEvent =
this.getInventoryChangeEvent(InventoryStrategyDTO, inventoryPO, currentValue, newValue);
inventoryDomainEventPublisher.publishEvent(inventoryDomainEvent);
}
/**
* 获取库存变更事件
* 构建具体的库存变更事件对象,该事件对象包含事件源和事件载荷
* 事件源标识事件类型,事件载荷包含具体的库存变更详情
*
* @param inventoryStrategyDTO 库存策略DTO,提供事件处理所需的业务信息
* @param inventoryPO 库存对象,表示变更的库存记录
* @param currentValue 变更前的库存值
* @param newValue 变更后的库存值
* @return InventoryDomainEvent<InventoryChangeEventPayload> 构建好的库存变更事件对象
*/
private InventoryDomainEvent<InventoryChangeEventPayload> getInventoryChangeEvent(InventoryStrategyDTO inventoryStrategyDTO,
InventoryPO inventoryPO,
Integer currentValue,
Integer newValue) {
// 构建事件载荷
InventoryChangeEventPayload inventoryChangeEventPayloadV2 =
this.buildInventoryChangeEventPayload(inventoryStrategyDTO, inventoryPO, currentValue, newValue);
// 根据事件载荷和事件源构建库存变更事件
return new InventoryDomainEvent<>(InventoryDomainEventSource.INVENTORY_CHANGE_EVENT, inventoryChangeEventPayloadV2);
}
/**
* 构建库存变更事件载荷
* 创建库存变更事件的详细载荷,包括变更的库存信息、业务编号、变更量等
* 这些信息对于事件的消费者来说是至关重要的,能够提供关于为何以及如何进行库存变更的上下文
*
* @param inventoryStrategyDTO 库存策略DTO,提供事件处理所需的业务信息
* @param inventoryPO 库存对象,表示变更的库存记录
* @param currentValue 变更前的库存值
* @param newValue 变更后的库存值
* @return InventoryChangeEventPayload 构建好的库存变更事件载荷对象
*/
private InventoryChangeEventPayload buildInventoryChangeEventPayload(InventoryStrategyDTO inventoryStrategyDTO,
InventoryPO inventoryPO,
Integer currentValue,
Integer newValue) {
InventoryChangeEventPayload inventoryChangeEventPayload = new InventoryChangeEventPayload();
inventoryChangeEventPayload.setBizNumber(inventoryStrategyDTO.getBizNumber());
inventoryChangeEventPayload.setBizType(inventoryStrategyDTO.getBizType());
inventoryChangeEventPayload.setBizActionType(inventoryStrategyDTO.getBizActionType());
inventoryChangeEventPayload.setCompanyId(inventoryPO.getCompanyId());
inventoryChangeEventPayload.setInventoryId(inventoryPO.getId());
inventoryChangeEventPayload.setSkuCode(inventoryPO.getSkuCode());
inventoryChangeEventPayload.setSkuId(inventoryStrategyDTO.getSkuId());
inventoryChangeEventPayload.setSpuCode(inventoryPO.getSpuCode());
inventoryChangeEventPayload.setSpuId(inventoryPO.getSpuId());
inventoryChangeEventPayload.setChangeQuantity(inventoryStrategyDTO.getOperationQuantity());
inventoryChangeEventPayload.setQuantityAfterChange(newValue);
inventoryChangeEventPayload.setQuantityBeforeChange(currentValue);
inventoryChangeEventPayload.setStockType(this.getStockType().getType());
inventoryChangeEventPayload.setOperatorId(inventoryStrategyDTO.getOperatorId());
return inventoryChangeEventPayload;
}
/**
* 获取库存对应的库存类型
* 抽象方法,用于确定处理的库存类型,以便于在不同的库存类型下应用特定的规则或策略
* 子类应实现此方法,以返回具体的库存类型
*
* @return StockType 库存类型
*/
public abstract StockType getStockType();
/**
* 计算新的库存值
* 根据当前库存值和操作量来计算新的库存值,这个方法是库存管理中的基本操作
* 它体现了库存变更的计算逻辑,但不涉及实际的库存变更操作
*
* @param currentValue 当前库存值
* @param operationQuantity 操作量,可以是正数(增加)也可以是负数(减少)
* @return Integer 计算得出的新库存值
*/
private Integer calculateNewInventoryValue(Integer currentValue, Integer operationQuantity) {
return currentValue + operationQuantity;
}
/**
* 抽象方法,用于验证库存新值的有效性
*
* @param inventoryPO 库存持久化对象,包含库存的相关信息
* @param newValue 需要验证的新库存值
*/
protected abstract void validateNewValue(InventoryPO inventoryPO, Integer newValue);
/**
* 获取当前库存的值
*
* 抽象方法,旨在获取库存对象中的库存值字段
* 子类应实现此方法,以适应不同的数据模型或库存表示方式
*
* @param inventoryPO 库存对象
* @return Integer 库存的值
*/
protected abstract Integer getCurrentInventoryValue(InventoryPO inventoryPO);
}
- TotalInventoryStrategy(总库存策略子类)
java
@Component
public class TotalInventoryStrategy extends AbstractInventoryStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(TotalInventoryStrategy.class);
@Override
protected void processInventory(Long inventoryId, Integer newValue, Integer expectedVersion, Long operatorId) {
super.inventoryRepo.updateTotalStock(inventoryId, newValue, expectedVersion, operatorId);
}
@Override
public StockType getStockType() {
return StockType.TOTAL_STOCK;
}
@Override
protected void validateNewValue(InventoryPO inventoryPO, Integer newValue) {
if (newValue < 0) {
LOGGER.warn("仓库:{} 货位:{} SKU 编号:{} 批次号:{} 总库存不能为负,当前总库存数量:{},操作总库存数量:{}",
inventoryPO.getWarehouseId(),
inventoryPO.getWarehouseLocationId(),
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
inventoryPO.getTotalStock(),
newValue);
throw new InventoryServiceException(String.format("SKU 编码:%s 批次号:%s 总库存不能为负,当前总库存数量:%s,操作总库存数量:%s",
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
inventoryPO.getTotalStock(),
newValue));
}
}
@Override
protected Integer getCurrentInventoryValue(InventoryPO inventoryPO) {
Integer totalStock = inventoryPO.getTotalStock();
if (totalStock < 0) {
LOGGER.error("仓库:{} 货位:{} SKU 编号:{} 批次号:{} 总库存异常,当前总库存数量:{}",
inventoryPO.getWarehouseId(),
inventoryPO.getWarehouseLocationId(),
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
totalStock);
throw new InventoryServiceException(String.format("SKU 编码:%s 批次号:%s 总库存异常,当前总库存数量:%s",
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
totalStock));
}
return totalStock;
}
}
- AvailableInventoryStrategy(可用库存策略子类)
java
@Component
public class AvailableInventoryStrategy extends AbstractInventoryStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(AvailableInventoryStrategy.class);
@Override
protected void processInventory(Long inventoryId, Integer newValue, Integer expectedVersion, Long operatorId) {
super.inventoryRepo.updateAvailableStock(inventoryId, newValue, expectedVersion, operatorId);
}
@Override
public StockType getStockType() {
return StockType.AVAILABLE_STOCK;
}
@Override
protected void validateNewValue(InventoryPO inventoryPO, Integer newValue) {
if (newValue < 0) {
LOGGER.warn("仓库:{} 货位:{} SKU 编号:{} 批次号:{} 可用库存不足,当前可用库存数量:{},操作后可用库存数量:{}",
inventoryPO.getWarehouseId(),
inventoryPO.getWarehouseLocationId(),
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
inventoryPO.getAvailableStock(),
newValue);
throw new InventoryServiceException(String.format("SKU 编码:%s 批次号:%s 可用库存不足,当前可用库存数量:%s,操作后可用库存数量:%s",
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
inventoryPO.getAvailableStock(),
newValue));
}
}
@Override
protected Integer getCurrentInventoryValue(InventoryPO inventoryPO) {
Integer availableStock = inventoryPO.getAvailableStock();
if (availableStock < 0) {
LOGGER.error("仓库:{} 货位:{} SKU 编号:{} 批次号:{} 可用库存异常,当前可用库存数量:{}",
inventoryPO.getWarehouseId(),
inventoryPO.getWarehouseLocationId(),
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
availableStock);
throw new InventoryServiceException(String.format("SKU 编码:%s 批次号:%s 可用库存异常,当前可用库存数量:%s",
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
availableStock));
}
return availableStock;
}
}
- ReservedInventoryStrategy(占用库存策略子类)
java
Component
public class ReservedInventoryStrategy extends AbstractInventoryStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(ReservedInventoryStrategy.class);
@Override
protected void processInventory(Long inventoryId, Integer newValue, Integer expectedVersion, Long operatorId) {
super.inventoryRepo.updateReservedStock(inventoryId, newValue, expectedVersion, operatorId);
}
@Override
public StockType getStockType() {
return StockType.RESERVED_STOCK;
}
@Override
protected void validateNewValue(InventoryPO inventoryPO, Integer newValue) {
if (newValue < 0) {
LOGGER.warn("仓库:{} 货位:{} SKU 编号:{} 批次号:{} 占用库存不能为负,当前占用库存数量:{},操作后占用库存数量:{}",
inventoryPO.getWarehouseId(),
inventoryPO.getWarehouseLocationId(),
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
inventoryPO.getReservedStock(),
newValue);
throw new InventoryServiceException(String.format("SKU 编码:%s 批次号:%s 占用库存不能为负,当前占用库存数量:%s,操作后占用库存数量:%s",
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
inventoryPO.getReservedStock(),
newValue));
}
}
@Override
protected Integer getCurrentInventoryValue(InventoryPO inventoryPO) {
Integer reservedStock = inventoryPO.getReservedStock();
if (reservedStock < 0) {
LOGGER.error("仓库:{} 货位:{} SKU 编号:{} 批次号:{} 占用库存异常,当前占用库存数量:{}",
inventoryPO.getWarehouseId(),
inventoryPO.getWarehouseLocationId(),
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
reservedStock);
throw new InventoryServiceException(String.format("SKU 编码:%s 批次号:%s 占用库存异常,当前占用库存数量:%s",
inventoryPO.getSkuCode(),
inventoryPO.getBatchNumber(),
reservedStock));
}
return reservedStock;
}
}
- InventoryStrategyManage(策略管理类)
java
@Component
public class InventoryStrategyManage {
public final Map<StockType, AbstractInventoryStrategy> strategyMap = new HashMap<>(3);
public InventoryStrategyManage(ListableBeanFactory listableBeanFactory) {
ObjectProvider<AbstractInventoryStrategy> beanProvider = listableBeanFactory.getBeanProvider(AbstractInventoryStrategy.class);
for (AbstractInventoryStrategy strategy : beanProvider) {
strategyMap.put(strategy.getStockType(), strategy);
}
}
public AbstractInventoryStrategy getStrategy(StockType stockType) {
return strategyMap.get(stockType);
}
}
4.2. 策略聚合
- InventoryOperation(库存操作抽象类)
java
public abstract class InventoryOperation {
/**
* 库存操作类中管理库存策略的实例,用于处理不同的库存操作策略
*/
private final InventoryStrategyManage inventoryStrategyManage;
/**
* 库存操作类中保护库存仓储实例,用于库存数据的持久化操作
*/
protected InventoryRepo inventoryRepo;
/**
* 库存操作类的构造函数,用于初始化库存策略管理和库存仓储对象
*
* @param inventoryStrategyManage 库存策略管理对象,用于管理不同的库存操作策略
* @param inventoryRepo 库存仓储对象,用于库存数据的持久化操作
*/
protected InventoryOperation(InventoryStrategyManage inventoryStrategyManage,
InventoryRepo inventoryRepo) {
this.inventoryStrategyManage = inventoryStrategyManage;
this.inventoryRepo = inventoryRepo;
}
/**
* 应用库存操作,该方法用于处理库存的增加或减少操作
* 该方法通过事务管理,确保操作的原子性,遇到异常会回滚
*
* @param inventoryOperationDTO 库存操作的具体参数,包含操作类型、操作数量等信息
*/
@Transactional(rollbackFor = Exception.class)
public void apply(InventoryOperationDTO inventoryOperationDTO) {
// 获取库存操作的项目列表,并进行非空校验
List<InventoryOperationDTO.InventoryOperationItem> inventoryOperationItemList =
inventoryOperationDTO.getInventoryOperationItemList();
Assert.notEmpty(inventoryOperationItemList, "库存操作参数不能为空");
// 根据多个属性组合唯一 key 将重复的进行合并
inventoryOperationItemList = new ArrayList<>(inventoryOperationItemList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(
item -> new CompositeKey(
item.getWarehouseId(),
item.getWarehouseLocationId(),
item.getSkuId(),
item.getBatchNumber()
),
item -> item,
(existingItem, newItem) -> {
existingItem.setQuantity(existingItem.getQuantity() + newItem.getQuantity());
return existingItem;
}
)).values());
// 对库存操作项目列表按照库存ID进行排序,以控制并发处理的顺序
inventoryOperationItemList = inventoryOperationItemList.stream()
.sorted(Comparator.comparing(InventoryOperationDTO.InventoryOperationItem::getSkuId))
.collect(Collectors.toList());
// 获取需要处理的库存字段类型列表
List<StockType> stockTypes = getStockTypes();
// 遍历库存字段类型,对每个类型确定库存变更类型,并构造库存策略DTO进行处理
for (StockType stockType : stockTypes) {
for (InventoryOperationDTO.InventoryOperationItem inventoryOperationItem : inventoryOperationItemList) {
// 确定当前库存类型的变更类型(增加或减少)
StockChangeType stockChangeType = getStockChangeType(stockType);
// 构造库存策略DTO
InventoryStrategyDTO inventoryStrategyDTO = getInventoryStrategyDTO(
inventoryOperationDTO, inventoryOperationItem, inventoryOperationItem.getQuantity(), stockChangeType);
// 应用库存策略
this.apply(inventoryStrategyDTO, stockType);
}
}
}
/**
* 获取需要处理的库存字段类型列表
*
* @return 库存字段类型列表
*/
protected abstract List<StockType> getStockTypes();
/**
* 根据库存类型获取对应的库存变更类型
*
* @param stockType 库存类型
* @return 库存变更类型,用于确定是增加还是减少库存
*/
protected abstract StockChangeType getStockChangeType(StockType stockType);
/**
* 应用指定的库存策略DTO和库存类型进行库存操作
*
* @param inventoryStrategyDTO 库存策略DTO,包含库存操作的具体参数
* @param stockType 库存类型,用于选择合适的库存操作策略
*/
protected void apply(InventoryStrategyDTO inventoryStrategyDTO, StockType stockType) {
// 根据库存类型获取对应的库存操作策略
AbstractInventoryStrategy strategy = inventoryStrategyManage.getStrategy(stockType);
// 执行库存操作策略
strategy.execute(inventoryStrategyDTO);
}
/**
* 构造库存策略DTO对象,根据库存操作DTO、操作项目和操作数量、库存变更类型
*
* @param inventoryOperationDTO 库存操作的具体参数
* @param inventoryOperationItem 当前操作的项目详情
* @param operationQuantity 操作的数量,正数表示增加,负数表示减少
* @param stockChangeType 库存变更类型,确定当前操作是增加还是减少库存
* @return 构造的库存策略DTO对象
*/
protected InventoryStrategyDTO getInventoryStrategyDTO(InventoryOperationDTO inventoryOperationDTO,
InventoryOperationDTO.InventoryOperationItem inventoryOperationItem,
Integer operationQuantity,
StockChangeType stockChangeType) {
InventoryStrategyDTO inventoryStrategyDTO = new InventoryStrategyDTO();
// 设置库存策略DTO的各种参数
inventoryStrategyDTO.setBizNumber(inventoryOperationDTO.getBizNumber());
inventoryStrategyDTO.setBizType(inventoryOperationDTO.getBizType());
inventoryStrategyDTO.setBizActionType(inventoryOperationDTO.getBizActionType());
inventoryStrategyDTO.setOperatorId(inventoryOperationDTO.getOperatorId());
inventoryStrategyDTO.setSkuId(inventoryOperationItem.getSkuId());
inventoryStrategyDTO.setWarehouseId(inventoryOperationItem.getWarehouseId());
inventoryStrategyDTO.setWarehouseLocationId(inventoryOperationItem.getWarehouseLocationId());
// 根据库存变更类型设置操作数量的正负,增加为正数,减少为负数
inventoryStrategyDTO.setOperationQuantity(StockChangeType.INCREASE.equals(stockChangeType) ? operationQuantity : -operationQuantity);
inventoryStrategyDTO.setBatchNumber(inventoryOperationItem.getBatchNumber());
return inventoryStrategyDTO;
}
}
- InventoryReservedOperation(占用库存操作类)
java
@Component
public class InventoryReservedOperation extends InventoryOperation {
protected InventoryReservedOperation(InventoryStrategyManage inventoryStrategyManage,
InventoryRepo inventoryRepo) {
super(inventoryStrategyManage, inventoryRepo);
}
@Override
protected List<StockType> getStockTypes() {
return List.of(StockType.AVAILABLE_STOCK, StockType.RESERVED_STOCK);
}
@Override
protected StockChangeType getStockChangeType(StockType stockType) {
if (stockType.equals(StockType.AVAILABLE_STOCK)) {
return StockChangeType.DECREASE;
} else if (stockType.equals(StockType.RESERVED_STOCK)) {
return StockChangeType.INCREASE;
} else {
throw new IllegalArgumentException("不存在的库存类型");
}
}
}
- InventoryReleaseOperation(释放库存操作类)
java
@Component
public class InventoryReleaseOperation extends InventoryOperation {
protected InventoryReleaseOperation(InventoryStrategyManage inventoryStrategyManage,
InventoryRepo inventoryRepo) {
super(inventoryStrategyManage, inventoryRepo);
}
@Override
protected List<StockType> getStockTypes() {
return List.of(StockType.AVAILABLE_STOCK, StockType.RESERVED_STOCK);
}
@Override
protected StockChangeType getStockChangeType(StockType stockType) {
if (stockType.equals(StockType.AVAILABLE_STOCK)) {
return StockChangeType.INCREASE;
} else if (stockType.equals(StockType.RESERVED_STOCK)) {
return StockChangeType.DECREASE;
} else {
throw new IllegalArgumentException("不存在的库存类型");
}
}
}
- InventoryInboundCompleteOperation(入库完成操作类)
java
@Component
public class InventoryInboundCompleteOperation extends InventoryOperation {
protected InventoryInboundCompleteOperation(InventoryStrategyManage inventoryStrategyManage, InventoryRepo inventoryRepo) {
super(inventoryStrategyManage, inventoryRepo);
}
@Override
protected List<StockType> getStockTypes() {
return List.of(StockType.TOTAL_STOCK, StockType.AVAILABLE_STOCK);
}
@Override
protected StockChangeType getStockChangeType(StockType stockType) {
if (stockType.equals(StockType.TOTAL_STOCK)) {
return StockChangeType.INCREASE;
} else if (stockType.equals(StockType.AVAILABLE_STOCK)) {
return StockChangeType.INCREASE;
} else {
throw new IllegalArgumentException("不存在的库存类型");
}
}
}
- InventoryOutboundCompleteOperation(出库完成操作类)
java
@Component
public class InventoryOutboundCompleteOperation extends InventoryOperation {
protected InventoryOutboundCompleteOperation(InventoryStrategyManage inventoryStrategyManage, InventoryRepo inventoryRepo) {
super(inventoryStrategyManage, inventoryRepo);
}
@Override
protected List<StockType> getStockTypes() {
return List.of(StockType.RESERVED_STOCK, StockType.TOTAL_STOCK);
}
@Override
protected StockChangeType getStockChangeType(StockType stockType) {
if (stockType.equals(StockType.RESERVED_STOCK)) {
return StockChangeType.DECREASE;
} else if (stockType.equals(StockType.TOTAL_STOCK)) {
return StockChangeType.DECREASE;
} else {
throw new IllegalArgumentException("不存在的库存类型");
}
}
}