|
|
@ -1,20 +1,35 @@ |
|
|
|
package cn.nla.product.service.impl; |
|
|
|
|
|
|
|
import cn.nla.common.enums.BizCodeEnum; |
|
|
|
import cn.nla.common.enums.ProductOrderStateEnum; |
|
|
|
import cn.nla.common.enums.StockTaskStateEnum; |
|
|
|
import cn.nla.common.exception.BizException; |
|
|
|
import cn.nla.common.model.PageResult; |
|
|
|
import cn.nla.common.model.ProductMessage; |
|
|
|
import cn.nla.common.util.JsonData; |
|
|
|
import cn.nla.product.config.RabbitMQConfig; |
|
|
|
import cn.nla.product.feign.OrderFeignService; |
|
|
|
import cn.nla.product.mapper.ProductTaskMapper; |
|
|
|
import cn.nla.product.model.VO.ProductVO; |
|
|
|
import cn.nla.product.model.entity.ProductEntity; |
|
|
|
import cn.nla.product.mapper.ProductMapper; |
|
|
|
import cn.nla.product.model.entity.ProductTaskEntity; |
|
|
|
import cn.nla.product.model.request.LockProductRequest; |
|
|
|
import cn.nla.product.model.request.OrderItemRequest; |
|
|
|
import cn.nla.product.service.ProductService; |
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.springframework.amqp.rabbit.core.RabbitTemplate; |
|
|
|
import org.springframework.beans.BeanUtils; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
import java.util.HashMap; |
|
|
|
import javax.annotation.Resource; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.function.Function; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
/** |
|
|
@ -25,8 +40,22 @@ import java.util.stream.Collectors; |
|
|
|
* @author YJs |
|
|
|
* @since 2024-08-09 |
|
|
|
*/ |
|
|
|
@Slf4j |
|
|
|
@Service |
|
|
|
public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductEntity> implements ProductService { |
|
|
|
|
|
|
|
@Resource |
|
|
|
private ProductTaskMapper productTaskMapper; |
|
|
|
|
|
|
|
@Resource |
|
|
|
private RabbitTemplate rabbitTemplate; |
|
|
|
|
|
|
|
@Resource |
|
|
|
private RabbitMQConfig rabbitMQConfig; |
|
|
|
|
|
|
|
@Resource |
|
|
|
private OrderFeignService orderFeignService; |
|
|
|
|
|
|
|
@Override |
|
|
|
public ProductVO findDetailById(Long productId) { |
|
|
|
return beanProcess(baseMapper.selectById(productId)); |
|
|
@ -45,6 +74,84 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductEntity |
|
|
|
.stream().map(this::beanProcess).collect(Collectors.toList()); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public JsonData lockProductStock(LockProductRequest lockProductRequest) { |
|
|
|
String outTradeNo = lockProductRequest.getOrderOutTradeNo(); |
|
|
|
List<OrderItemRequest> itemList = lockProductRequest.getOrderItemList(); |
|
|
|
//一行代码,提取对象里面的id并加入到集合里面
|
|
|
|
List<Long> productIdList = itemList.stream().map(OrderItemRequest::getProductId).collect(Collectors.toList()); |
|
|
|
//批量查询
|
|
|
|
List<ProductVO> productVOList = this.findProductsByIdBatch(productIdList); |
|
|
|
//分组
|
|
|
|
Map<Long,ProductVO> productMap = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity())); |
|
|
|
for(OrderItemRequest item:itemList){ |
|
|
|
//锁定商品记录
|
|
|
|
int rows = baseMapper.lockProductStock(item.getProductId(),item.getBuyNum()); |
|
|
|
if(rows != 1){ |
|
|
|
throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL); |
|
|
|
}else { |
|
|
|
//插入商品product_task
|
|
|
|
ProductVO productVO = productMap.get(item.getProductId()); |
|
|
|
ProductTaskEntity productTask = new ProductTaskEntity(); |
|
|
|
productTask.setBuyNum(item.getBuyNum()); |
|
|
|
productTask.setLockState(StockTaskStateEnum.LOCK.name()); |
|
|
|
productTask.setProductId(item.getProductId()); |
|
|
|
productTask.setProductName(productVO.getTitle()); |
|
|
|
productTask.setOutTradeNo(outTradeNo); |
|
|
|
productTaskMapper.insert(productTask); |
|
|
|
log.info("商品库存锁定-插入商品product_task成功:{}",productTask); |
|
|
|
// 发送MQ延迟消息,介绍商品库存
|
|
|
|
ProductMessage productMessage = new ProductMessage(); |
|
|
|
productMessage.setOutTradeNo(outTradeNo); |
|
|
|
productMessage.setTaskId(productTask.getId()); |
|
|
|
rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(),rabbitMQConfig.getStockReleaseDelayRoutingKey(),productMessage); |
|
|
|
log.info("商品库存锁定信息延迟消息发送成功:{}",productMessage); |
|
|
|
} |
|
|
|
} |
|
|
|
return JsonData.buildSuccess(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean releaseProductStock(ProductMessage productMessage) { |
|
|
|
//查询工作单状态
|
|
|
|
ProductTaskEntity taskDO = productTaskMapper.selectOne(new QueryWrapper<ProductTaskEntity>().eq("id",productMessage.getTaskId())); |
|
|
|
if(taskDO == null){ |
|
|
|
log.warn("工作单不存在,消息体为:{}",productMessage); |
|
|
|
} |
|
|
|
//lock状态才处理
|
|
|
|
assert taskDO != null; |
|
|
|
if(taskDO.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())){ |
|
|
|
//查询订单状态
|
|
|
|
JsonData jsonData = orderFeignService.queryProductOrderState(productMessage.getOutTradeNo()); |
|
|
|
if(jsonData.getCode() == 0){ |
|
|
|
String state = jsonData.getData().toString(); |
|
|
|
if(ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)){ |
|
|
|
//状态是NEW新建状态,则返回给消息队,列重新投递
|
|
|
|
log.warn("订单状态是NEW,返回给消息队列,重新投递:{}",productMessage); |
|
|
|
return false; |
|
|
|
} |
|
|
|
//如果是已经支付
|
|
|
|
if(ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)){ |
|
|
|
//如果已经支付,修改task状态为finish
|
|
|
|
taskDO.setLockState(StockTaskStateEnum.FINISH.name()); |
|
|
|
productTaskMapper.update(taskDO,new QueryWrapper<ProductTaskEntity>().eq("id",productMessage.getTaskId())); |
|
|
|
log.info("订单已经支付,修改库存锁定工作单FINISH状态:{}",productMessage); |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
//订单不存在,或者订单被取消,确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW
|
|
|
|
log.warn("订单不存在,或者订单被取消,确认消息,修改task状态为CANCEL,恢复商品库存,message:{}",productMessage); |
|
|
|
taskDO.setLockState(StockTaskStateEnum.CANCEL.name()); |
|
|
|
productTaskMapper.update(taskDO,new QueryWrapper<ProductTaskEntity>().eq("id",productMessage.getTaskId())); |
|
|
|
//恢复商品库存,集锁定库存的值减去当前购买的值
|
|
|
|
baseMapper.unlockProductStock(taskDO.getProductId(),taskDO.getBuyNum()); |
|
|
|
|
|
|
|
} else { |
|
|
|
log.warn("工作单状态不是LOCK,state={},消息体={}",taskDO.getLockState(),productMessage); |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
private ProductVO beanProcess(ProductEntity product) { |
|
|
|
ProductVO result = new ProductVO(); |
|
|
|
BeanUtils.copyProperties(product, result); |
|
|
|