创建订单扣除库存
This commit is contained in:
@@ -5,6 +5,7 @@ import com.chaozhanggui.system.cashierservice.entity.TbProductWithBLOBs;
|
||||
import com.chaozhanggui.system.cashierservice.entity.vo.ShopGroupInfoVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
@@ -36,4 +37,7 @@ public interface TbProductMapper {
|
||||
void upGroupRealSalesNumber(@Param("id") String id,@Param("number") Integer number);
|
||||
|
||||
void updateStockById(@Param("productId") String productId, @Param("num") Integer num);
|
||||
|
||||
@Update("update tb_product set stock_number=stock_number-#{num} WHERE id=#{id} and stock_number-#{num} > 0")
|
||||
int decrStock(@Param("id") String id, @Param("num") Integer num);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.chaozhanggui.system.cashierservice.entity.TbProductSkuWithBLOBs;
|
||||
import com.chaozhanggui.system.cashierservice.entity.vo.HomeVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
@@ -39,4 +40,7 @@ public interface TbProductSkuMapper {
|
||||
|
||||
List<TbProductSku> selectSkus(@Param("list") List<String> productId);
|
||||
List<TbProductSku> selectSku(@Param("productId") String productId);
|
||||
}
|
||||
|
||||
@Update("update tb_product_sku set stock_number=stock_number-#{num} WHERE id=#{id} and stock_number-#{num} > 0")
|
||||
int decrStock(@Param("id") String id, @Param("num") Integer num);
|
||||
}
|
||||
|
||||
@@ -22,4 +22,6 @@ public class RedisCst {
|
||||
public static final String COUPONS_COIN_KEY = "COUPONS:COIN:KEY";
|
||||
|
||||
public static final String OUT_NUMBER="ORDER:NUMBER:";
|
||||
// 创建订单锁
|
||||
public static final String CREATE_ORDER_LOCK = "CREATE_ORDER_LOCK:";
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@ import com.chaozhanggui.system.cashierservice.redis.RedisCst;
|
||||
import com.chaozhanggui.system.cashierservice.redis.RedisUtil;
|
||||
import com.chaozhanggui.system.cashierservice.util.DateUtils;
|
||||
import com.chaozhanggui.system.cashierservice.util.JSONUtil;
|
||||
import com.chaozhanggui.system.cashierservice.util.LockUtils;
|
||||
import com.chaozhanggui.system.cashierservice.util.N;
|
||||
import com.chaozhanggui.system.cashierservice.wxUtil.WechatUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -68,10 +70,20 @@ public class CartService {
|
||||
@Autowired
|
||||
private TbShopInfoMapper tbShopInfoMapper;
|
||||
|
||||
public CartService(TbUserShopMsgMapper tbUserShopMsgMapper, WechatUtil wechatUtil, TbShopOpenIdMapper shopOpenIdMapper) {
|
||||
|
||||
private final ProductService productService;
|
||||
|
||||
private final TbProductMapper tbProductMapper;
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public CartService(TbUserShopMsgMapper tbUserShopMsgMapper, WechatUtil wechatUtil, TbShopOpenIdMapper shopOpenIdMapper, ProductService productService, TbProductMapper tbProductMapper, RedisTemplate<String, Object> redisTemplate) {
|
||||
this.tbUserShopMsgMapper = tbUserShopMsgMapper;
|
||||
this.wechatUtil = wechatUtil;
|
||||
this.shopOpenIdMapper = shopOpenIdMapper;
|
||||
this.productService = productService;
|
||||
this.tbProductMapper = tbProductMapper;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
public void initCart(JSONObject jsonObject) {
|
||||
@@ -110,6 +122,7 @@ public class CartService {
|
||||
|
||||
/**
|
||||
* 加入购物车
|
||||
*
|
||||
* @param jsonObject 商品信息
|
||||
*/
|
||||
// @Transactional(rollbackFor = Exception.class)
|
||||
@@ -276,14 +289,16 @@ public class CartService {
|
||||
// log.error("长链接错误 createCart{}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
public void createCart(JSONObject jsonObject) {
|
||||
try {
|
||||
|
||||
String tableId = jsonObject.getString("tableId");
|
||||
String shopId = jsonObject.getString("shopId");
|
||||
String productId = jsonObject.getString("productId");
|
||||
String key = tableId + "-" + shopId;
|
||||
|
||||
TbProduct tbProduct = productMapper.selectById(Integer.valueOf(productId));
|
||||
TbProductSkuWithBLOBs tbProductSkuWithBLOBs = null;
|
||||
if (tbProduct == null) {
|
||||
JSONObject jsonObject1 = new JSONObject();
|
||||
jsonObject1.put("status", "fail");
|
||||
@@ -307,8 +322,8 @@ public class CartService {
|
||||
throw new MsgException("该商品已售罄");
|
||||
}
|
||||
} else {
|
||||
TbProductSkuWithBLOBs tbProductSkuWithBLOBs = productSkuMapper.selectByPrimaryKey(Integer.valueOf(skuId));
|
||||
if(tbProductSkuWithBLOBs.getIsPauseSale().equals(1)){//是否售罄
|
||||
tbProductSkuWithBLOBs = productSkuMapper.selectByPrimaryKey(Integer.valueOf(skuId));
|
||||
if (tbProductSkuWithBLOBs.getIsPauseSale().equals(1)) {//是否售罄
|
||||
JSONObject jsonObject1 = new JSONObject();
|
||||
jsonObject1.put("status", "fail");
|
||||
jsonObject1.put("msg", "该商品已售罄");
|
||||
@@ -325,10 +340,13 @@ public class CartService {
|
||||
|
||||
if (redisUtil.exists(RedisCst.TABLE_CART.concat(jsonObject.getString("tableId").concat("-").concat(shopId)))) {
|
||||
JSONArray array = JSON.parseArray(redisUtil.getMessage(RedisCst.TABLE_CART.concat(jsonObject.getString("tableId").concat("-").concat(shopId))));
|
||||
// 未创建购物车,新增购物车
|
||||
if (Objects.isNull(array) || array.isEmpty()) {
|
||||
if (buyNum > 0) {
|
||||
|
||||
TbCashierCart cashierCart = addCart(jsonObject.getString("productId"), skuId,
|
||||
jsonObject.getInteger("userId"), buyNum, tableId, shopId);
|
||||
|
||||
jsonArray.add(cashierCart);
|
||||
amount = amount.add(new BigDecimal(cashierCart.getNumber()).multiply(cashierCart.getSalePrice().add(cashierCart.getPackFee())));
|
||||
}
|
||||
@@ -337,10 +355,13 @@ public class CartService {
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject object = array.getJSONObject(i);
|
||||
TbCashierCart cashierCart = JSONUtil.parseJSONStr2T(object.toJSONString(), TbCashierCart.class);
|
||||
|
||||
// 已添加购物车商品,加数量
|
||||
if (cashierCart.getSkuId().equals(skuId)) {
|
||||
cashierCart.setTotalNumber(cashierCart.getTotalNumber() + buyNum);
|
||||
cashierCart.setNumber(cashierCart.getNumber() + buyNum);
|
||||
if (cashierCart.getNumber() > 0) {
|
||||
|
||||
cashierCart.setTotalAmount(new BigDecimal(cashierCart.getTotalNumber()).multiply(cashierCart.getSalePrice().add(cashierCart.getPackFee())));
|
||||
cashierCart.setUpdatedAt(Instant.now().toEpochMilli());
|
||||
cashierCartMapper.updateByPrimaryKeySelective(cashierCart);
|
||||
@@ -353,13 +374,16 @@ public class CartService {
|
||||
jsonArray.add(cashierCart);
|
||||
amount = amount.add(new BigDecimal(cashierCart.getTotalNumber()).multiply(cashierCart.getSalePrice().add(cashierCart.getPackFee())));
|
||||
}
|
||||
// 已有购物车中不存在,新增
|
||||
if (flag && buyNum > 0) {
|
||||
|
||||
TbCashierCart cashierCart = addCart(jsonObject.getString("productId"), skuId,
|
||||
jsonObject.getInteger("userId"), buyNum, tableId, jsonObject.getString("shopId"));
|
||||
jsonArray.add(cashierCart);
|
||||
amount = amount.add(new BigDecimal(cashierCart.getTotalNumber()).multiply(cashierCart.getSalePrice().add(cashierCart.getPackFee())));
|
||||
}
|
||||
}
|
||||
// 未创建购物车新增
|
||||
} else {
|
||||
if (buyNum > 0) {
|
||||
TbCashierCart cashierCart = addCart(jsonObject.getString("productId"), skuId,
|
||||
@@ -376,6 +400,7 @@ public class CartService {
|
||||
jsonObject1.put("data", jsonArray);
|
||||
jsonObject1.put("amount", amount);
|
||||
PushToAppChannelHandlerAdapter.getInstance().AppSendInfo(jsonObject1.toString(), jsonObject.getString("tableId").concat("-").concat(shopId), "", false);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("长链接错误 createCart{}", e.getMessage());
|
||||
}
|
||||
@@ -383,9 +408,10 @@ public class CartService {
|
||||
|
||||
/**
|
||||
* 修改库存并根据警告线发送消息
|
||||
* @param product 商品
|
||||
*
|
||||
* @param product 商品
|
||||
* @param productSku sku
|
||||
* @param num 库存数
|
||||
* @param num 库存数
|
||||
*/
|
||||
private void updateProductStock(TbProduct product, TbProductSkuWithBLOBs productSku, Integer num) {
|
||||
String key = RedisCst.PRODUCT + product.getShopId() + ":product" + product.getId();
|
||||
@@ -411,6 +437,7 @@ public class CartService {
|
||||
|
||||
/**
|
||||
* 校验商品库存警戒线并通知商户
|
||||
*
|
||||
* @param productSku sku
|
||||
*/
|
||||
private void checkWarnLineAndSendMsg(TbProductSku productSku, TbProduct product, Integer num) {
|
||||
@@ -438,13 +465,13 @@ public class CartService {
|
||||
List<TbShopOpenId> shopOpenIds = shopOpenIdMapper.selectByShopId(Integer.valueOf(product.getShopId()));
|
||||
shopOpenIds.forEach(item -> {
|
||||
wechatUtil.sendStockWarnMsg(shopInfo.getShopName(), product.getName(),
|
||||
product.getIsDistribute() == 1 ? String.valueOf(product.getStockNumber()-num) : String.valueOf(productSku.getStockNumber() - num),
|
||||
product.getIsDistribute() == 1 ? String.valueOf(product.getStockNumber() - num) : String.valueOf(productSku.getStockNumber() - num),
|
||||
"耗材库存不足,请及时补充。", item.getOpenId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private TbCashierCart addCart(String productId, String skuId, Integer userId, Integer num, String tableId, String shopId) throws Exception {
|
||||
private TbCashierCart addCart(String productId, String skuId, Integer userId, Integer num, String tableId, String shopId) throws RuntimeException {
|
||||
try {
|
||||
TbProduct product = productMapper.selectById(Integer.valueOf(productId));
|
||||
String key = tableId + "-" + shopId;
|
||||
@@ -536,6 +563,11 @@ public class CartService {
|
||||
JSONObject object = array.getJSONObject(i);
|
||||
TbCashierCart cashierCart = JSONUtil.parseJSONStr2T(object.toJSONString(), TbCashierCart.class);
|
||||
TbProductSkuWithBLOBs tbProduct = productSkuMapper.selectByPrimaryKey(Integer.valueOf(cashierCart.getSkuId()));
|
||||
TbProduct tbProduct1 = tbProductMapper.selectById(Integer.valueOf(tbProduct.getProductId()));
|
||||
log.info("开始修改库存,商品id:{},商品名:{}", tbProduct1.getId(), tbProduct1.getName());
|
||||
// 修改库存
|
||||
productService.updateStock(tbProduct.getProductId(), tbProduct.getId(), cashierCart.getNumber(), tbProduct1.getIsDistribute() == 1);
|
||||
|
||||
totalAmount = totalAmount.add(cashierCart.getTotalAmount());
|
||||
packAMount = packAMount.add(cashierCart.getPackFee());
|
||||
originAmount = originAmount.add(cashierCart.getTotalAmount());
|
||||
@@ -709,11 +741,7 @@ public class CartService {
|
||||
orderInfoMapper.insert(orderInfo);
|
||||
orderId = orderInfo.getId();
|
||||
|
||||
// 发送mq消息
|
||||
JSONObject jsonObject2=new JSONObject();
|
||||
jsonObject2.put("orderId",orderInfo.getId());
|
||||
jsonObject2.put("type","create");
|
||||
producer.cons(jsonObject2.toString());
|
||||
|
||||
}
|
||||
for (TbOrderDetail orderDetail : orderDetails) {
|
||||
orderDetail.setOrderId(orderId);
|
||||
@@ -728,6 +756,14 @@ public class CartService {
|
||||
cashierCartMapper.updateByPrimaryKeySelective(cashierCart);
|
||||
object.put("updatedAt", System.currentTimeMillis());
|
||||
object.put("orderId", orderId + "");
|
||||
|
||||
// 发送mq消息
|
||||
JSONObject jsonObject2 = new JSONObject();
|
||||
jsonObject2.put("orderId", orderInfo.getId());
|
||||
jsonObject2.put("type", "create");
|
||||
jsonObject2.put("cartId", cashierCart.getId());
|
||||
log.info("开始发送mq消息,消耗库存,消息内容:{}", jsonObject2);
|
||||
producer.cons(jsonObject2.toString());
|
||||
}
|
||||
redisUtil.saveMessage(RedisCst.TABLE_CART.concat(jsonObject.getString("tableId")).concat("-").concat(shopId), array.toJSONString());
|
||||
orderInfo.setDetailList(orderDetails);
|
||||
@@ -747,6 +783,8 @@ public class CartService {
|
||||
jsonObject12.put("data", new JSONArray());
|
||||
PushToAppChannelHandlerAdapter.getInstance().AppSendInfo(jsonObject12.toString(), jsonObject.getString("tableId").concat("-").concat(shopId), "", false);
|
||||
redisUtil.saveMessage(RedisCst.ORDER_EXPIRED.concat(orderId.toString()), orderId.toString(), 60 * 16L);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
log.info("长链接错误 addCart{}", e.getMessage());
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.chaozhanggui.system.cashierservice.dao.*;
|
||||
import com.chaozhanggui.system.cashierservice.entity.*;
|
||||
import com.chaozhanggui.system.cashierservice.entity.dto.HomeDto;
|
||||
import com.chaozhanggui.system.cashierservice.entity.vo.*;
|
||||
import com.chaozhanggui.system.cashierservice.exception.MsgException;
|
||||
import com.chaozhanggui.system.cashierservice.sign.CodeEnum;
|
||||
import com.chaozhanggui.system.cashierservice.sign.Result;
|
||||
import com.chaozhanggui.system.cashierservice.util.*;
|
||||
@@ -433,4 +434,35 @@ public class ProductService {
|
||||
}
|
||||
return Result.success(CodeEnum.SUCCESS, confirmVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 库存修改
|
||||
*
|
||||
* @param tbProduct 商品
|
||||
* @param tbProductSkuWithBLOBs sku
|
||||
* @param buyNum 购买数量
|
||||
*/
|
||||
public void updateStock(TbProduct tbProduct, TbProductSkuWithBLOBs tbProductSkuWithBLOBs, Integer buyNum) {
|
||||
if (tbProduct.getIsDistribute() == 1) {
|
||||
if (tbProductMapper.decrStock(String.valueOf(tbProduct.getId()), buyNum) < 1) {
|
||||
throw new MsgException("库存修改失败,请稍后再试");
|
||||
}
|
||||
}else {
|
||||
if (tbProductSkuMapper.decrStock(String.valueOf(tbProductSkuWithBLOBs.getId()), buyNum) < 1) {
|
||||
throw new MsgException("库存修改失败,请稍后再试");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateStock(String id, Integer skuId, Integer buyNum, boolean isDistribute) {
|
||||
if (isDistribute) {
|
||||
if (tbProductMapper.decrStock(String.valueOf(id), buyNum) < 1) {
|
||||
throw new MsgException("库存不足,下单失败");
|
||||
}
|
||||
}else {
|
||||
if (tbProductSkuMapper.decrStock(String.valueOf(skuId), buyNum) < 1) {
|
||||
throw new MsgException("库存不足,下单失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.chaozhanggui.system.cashierservice.util;
|
||||
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Slf4j
|
||||
public class LockUtils {
|
||||
|
||||
public static<T> T runFunAndCheckKey(Supplier<T> supplier, RedisTemplate<String, Object> redisTemplate, String lockKey) {
|
||||
try{
|
||||
// 创建线程id, 用作判断
|
||||
String clientId = UUID.randomUUID().toString();
|
||||
// 设置分布式锁
|
||||
boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS));
|
||||
int count = 0;
|
||||
while (!lock) {
|
||||
if (count++ > 100) {
|
||||
throw new RuntimeException("系统繁忙, 稍后再试");
|
||||
}
|
||||
Thread.sleep(20);
|
||||
lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS));
|
||||
}
|
||||
return supplier.get();
|
||||
} catch (Exception e){
|
||||
log.info("执行出错:{}", e.getMessage());
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}finally{
|
||||
redisTemplate.delete(lockKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user